From 707f1109f9680f57ab56927b2b2738d446eca764 Mon Sep 17 00:00:00 2001 From: j3w1 Date: Wed, 14 Oct 2026 15:12:22 -0500 Subject: [PATCH 01/65] tokens: D-037 display and title type sizes (proposed) The portal draws its heroes and metrics at 48/32/24/22/18px, outside the token scale, so the site cannot render from one source of truth. The owner chose token sizes over shrinking every heading to h1. Two roles join the scale: font.size.display 32/40 and font.size.title 24/32, opened as a proposed decision; the owner sets its status. Every port classifies the four new roles the way it classifies h1 (Windows leaves them unsupported: its PowerToys Markdown surface has no level above h1), and each port's tokenDigest follows the new resolved token set. docs/ui-architecture.md states the site chrome contract the redesign uses. Co-Authored-By: Claude Opus 5.5 --- docs/ui-architecture.md | 5 + exports/components/admin-form.brief.txt | 2 +- exports/components/admin-form.json | 2 +- exports/components/alert.brief.txt | 2 +- exports/components/alert.json | 2 +- exports/components/avatar.brief.txt | 2 +- exports/components/avatar.json | 2 +- exports/components/badge.brief.txt | 2 +- exports/components/badge.json | 2 +- exports/components/breadcrumbs.brief.txt | 2 +- exports/components/breadcrumbs.json | 2 +- exports/components/button-group.brief.txt | 2 +- exports/components/button-group.json | 2 +- exports/components/button.brief.txt | 2 +- exports/components/button.json | 2 +- exports/components/card.brief.txt | 2 +- exports/components/card.json | 2 +- exports/components/chart.brief.txt | 2 +- exports/components/chart.json | 2 +- exports/components/checkbox.brief.txt | 2 +- exports/components/checkbox.json | 2 +- exports/components/chip.brief.txt | 2 +- exports/components/chip.json | 2 +- exports/components/code-editor.brief.txt | 2 +- exports/components/code-editor.json | 2 +- exports/components/combobox.brief.txt | 2 +- exports/components/combobox.json | 2 +- exports/components/command-palette.brief.txt | 2 +- exports/components/command-palette.json | 2 +- .../components/compact-dashboard.brief.txt | 2 +- exports/components/compact-dashboard.json | 2 +- exports/components/data-table.brief.txt | 2 +- exports/components/data-table.json | 2 +- exports/components/date-picker.brief.txt | 2 +- exports/components/date-picker.json | 2 +- exports/components/description-list.brief.txt | 2 +- exports/components/description-list.json | 2 +- exports/components/diagnostics.brief.txt | 2 +- exports/components/diagnostics.json | 2 +- exports/components/dialog.brief.txt | 2 +- exports/components/dialog.json | 2 +- exports/components/diff-view.brief.txt | 2 +- exports/components/diff-view.json | 2 +- exports/components/disclosure.brief.txt | 2 +- exports/components/disclosure.json | 2 +- exports/components/drawer.brief.txt | 2 +- exports/components/drawer.json | 2 +- exports/components/editor-search.brief.txt | 2 +- exports/components/editor-search.json | 2 +- exports/components/empty-state.brief.txt | 2 +- exports/components/empty-state.json | 2 +- exports/components/error-state.brief.txt | 2 +- exports/components/error-state.json | 2 +- exports/components/field.brief.txt | 2 +- exports/components/field.json | 2 +- exports/components/fieldset.brief.txt | 2 +- exports/components/fieldset.json | 2 +- exports/components/file-browser.brief.txt | 2 +- exports/components/file-browser.json | 2 +- exports/components/file-input.brief.txt | 2 +- exports/components/file-input.json | 2 +- exports/components/filterable-table.brief.txt | 2 +- exports/components/filterable-table.json | 2 +- exports/components/form-builder.brief.txt | 2 +- exports/components/form-builder.json | 2 +- exports/components/i3-window-frame.brief.txt | 2 +- exports/components/i3-window-frame.json | 2 +- exports/components/icon-button.brief.txt | 2 +- exports/components/icon-button.json | 2 +- exports/components/kbd.brief.txt | 2 +- exports/components/kbd.json | 2 +- exports/components/link.brief.txt | 2 +- exports/components/link.json | 2 +- exports/components/list.brief.txt | 2 +- exports/components/list.json | 2 +- .../components/loading-indicator.brief.txt | 2 +- exports/components/loading-indicator.json | 2 +- exports/components/menu.brief.txt | 2 +- exports/components/menu.json | 2 +- exports/components/multiselect.brief.txt | 2 +- exports/components/multiselect.json | 2 +- exports/components/number-field.brief.txt | 2 +- exports/components/number-field.json | 2 +- exports/components/pagination.brief.txt | 2 +- exports/components/pagination.json | 2 +- exports/components/popover.brief.txt | 2 +- exports/components/popover.json | 2 +- exports/components/progress.brief.txt | 2 +- exports/components/progress.json | 2 +- exports/components/radio-group.brief.txt | 2 +- exports/components/radio-group.json | 2 +- exports/components/range.brief.txt | 2 +- exports/components/range.json | 2 +- exports/components/repeater.brief.txt | 2 +- exports/components/repeater.json | 2 +- exports/components/search-field.brief.txt | 2 +- exports/components/search-field.json | 2 +- .../components/segmented-control.brief.txt | 2 +- exports/components/segmented-control.json | 2 +- exports/components/select.brief.txt | 2 +- exports/components/select.json | 2 +- exports/components/settings-panel.brief.txt | 2 +- exports/components/settings-panel.json | 2 +- exports/components/sidebar-nav.brief.txt | 2 +- exports/components/sidebar-nav.json | 2 +- exports/components/skeleton.brief.txt | 2 +- exports/components/skeleton.json | 2 +- exports/components/skip-link.brief.txt | 2 +- exports/components/skip-link.json | 2 +- exports/components/switch.brief.txt | 2 +- exports/components/switch.json | 2 +- exports/components/table.brief.txt | 2 +- exports/components/table.json | 2 +- exports/components/tabs.brief.txt | 2 +- exports/components/tabs.json | 2 +- exports/components/terminal.brief.txt | 2 +- exports/components/terminal.json | 2 +- exports/components/text-field.brief.txt | 2 +- exports/components/text-field.json | 2 +- exports/components/textarea.brief.txt | 2 +- exports/components/textarea.json | 2 +- exports/components/time-picker.brief.txt | 2 +- exports/components/time-picker.json | 2 +- exports/components/timeline.brief.txt | 2 +- exports/components/timeline.json | 2 +- exports/components/toast.brief.txt | 2 +- exports/components/toast.json | 2 +- exports/components/toolbar.brief.txt | 2 +- exports/components/toolbar.json | 2 +- exports/components/tooltip.brief.txt | 2 +- exports/components/tooltip.json | 2 +- exports/components/tree.brief.txt | 2 +- exports/components/tree.json | 2 +- exports/components/wizard.brief.txt | 2 +- exports/components/wizard.json | 2 +- exports/digests.json | 300 +-- exports/forms/identity.json | 2 +- exports/patterns/validation-recovery.json | 20 +- exports/port-capabilities.json | 54 +- exports/recipes/button/README.md | 2 +- exports/recipes/button/manifest.json | 6 +- exports/recipes/dialog/README.md | 2 +- exports/recipes/dialog/manifest.json | 6 +- exports/recipes/index.json | 6 +- exports/recipes/text-field/README.md | 2 +- exports/recipes/text-field/manifest.json | 6 +- exports/task-inputs.json | 162 +- exports/theme.compact.md | 4 +- exports/theme.full.md | 24 +- exports/token-usage.json | 1610 ++++++++++------- exports/tokens.css | 4 + exports/tokens.resolved.json | 216 +++ packages/ui/dist/canonical/admin-form.json | 2 +- packages/ui/dist/canonical/alert.json | 2 +- packages/ui/dist/canonical/avatar.json | 2 +- packages/ui/dist/canonical/badge.json | 2 +- packages/ui/dist/canonical/breadcrumbs.json | 2 +- packages/ui/dist/canonical/button-group.json | 2 +- packages/ui/dist/canonical/button.json | 2 +- packages/ui/dist/canonical/card.json | 2 +- packages/ui/dist/canonical/chart.json | 2 +- packages/ui/dist/canonical/checkbox.json | 2 +- packages/ui/dist/canonical/chip.json | 2 +- packages/ui/dist/canonical/code-editor.json | 2 +- packages/ui/dist/canonical/combobox.json | 2 +- .../ui/dist/canonical/command-palette.json | 2 +- .../ui/dist/canonical/compact-dashboard.json | 2 +- packages/ui/dist/canonical/data-table.json | 2 +- packages/ui/dist/canonical/date-picker.json | 2 +- .../ui/dist/canonical/description-list.json | 2 +- packages/ui/dist/canonical/diagnostics.json | 2 +- packages/ui/dist/canonical/dialog.json | 2 +- packages/ui/dist/canonical/diff-view.json | 2 +- packages/ui/dist/canonical/disclosure.json | 2 +- packages/ui/dist/canonical/drawer.json | 2 +- packages/ui/dist/canonical/editor-search.json | 2 +- packages/ui/dist/canonical/empty-state.json | 2 +- packages/ui/dist/canonical/error-state.json | 2 +- packages/ui/dist/canonical/field.json | 2 +- packages/ui/dist/canonical/fieldset.json | 2 +- packages/ui/dist/canonical/file-browser.json | 2 +- packages/ui/dist/canonical/file-input.json | 2 +- .../ui/dist/canonical/filterable-table.json | 2 +- packages/ui/dist/canonical/form-builder.json | 2 +- .../ui/dist/canonical/i3-window-frame.json | 2 +- packages/ui/dist/canonical/icon-button.json | 2 +- packages/ui/dist/canonical/kbd.json | 2 +- packages/ui/dist/canonical/link.json | 2 +- packages/ui/dist/canonical/list.json | 2 +- .../ui/dist/canonical/loading-indicator.json | 2 +- packages/ui/dist/canonical/menu.json | 2 +- packages/ui/dist/canonical/multiselect.json | 2 +- packages/ui/dist/canonical/number-field.json | 2 +- packages/ui/dist/canonical/pagination.json | 2 +- packages/ui/dist/canonical/popover.json | 2 +- packages/ui/dist/canonical/progress.json | 2 +- packages/ui/dist/canonical/radio-group.json | 2 +- packages/ui/dist/canonical/range.json | 2 +- packages/ui/dist/canonical/repeater.json | 2 +- packages/ui/dist/canonical/search-field.json | 2 +- .../ui/dist/canonical/segmented-control.json | 2 +- packages/ui/dist/canonical/select.json | 2 +- .../ui/dist/canonical/settings-panel.json | 2 +- packages/ui/dist/canonical/sidebar-nav.json | 2 +- packages/ui/dist/canonical/skeleton.json | 2 +- packages/ui/dist/canonical/skip-link.json | 2 +- packages/ui/dist/canonical/switch.json | 2 +- packages/ui/dist/canonical/table.json | 2 +- packages/ui/dist/canonical/tabs.json | 2 +- packages/ui/dist/canonical/terminal.json | 2 +- packages/ui/dist/canonical/text-field.json | 2 +- packages/ui/dist/canonical/textarea.json | 2 +- packages/ui/dist/canonical/time-picker.json | 2 +- packages/ui/dist/canonical/timeline.json | 2 +- packages/ui/dist/canonical/toast.json | 2 +- packages/ui/dist/canonical/toolbar.json | 2 +- packages/ui/dist/canonical/tooltip.json | 2 +- packages/ui/dist/canonical/tree.json | 2 +- packages/ui/dist/canonical/wizard.json | 2 +- ...r-EQnl1AaR.js => form-builder-C5Kx5G9b.js} | 2 +- ...r-Dkweb1xD.js => form-builder-C6Rhfsz6.js} | 4 +- packages/ui/dist/components/form-builder.js | 2 +- 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 | 2 +- packages/ui/dist/copy/admin-form/tokens.css | 4 + packages/ui/dist/copy/alert/manifest.json | 2 +- packages/ui/dist/copy/alert/tokens.css | 4 + packages/ui/dist/copy/avatar/manifest.json | 2 +- packages/ui/dist/copy/avatar/tokens.css | 4 + packages/ui/dist/copy/badge/manifest.json | 2 +- packages/ui/dist/copy/badge/tokens.css | 4 + .../ui/dist/copy/breadcrumbs/manifest.json | 2 +- packages/ui/dist/copy/breadcrumbs/tokens.css | 4 + .../ui/dist/copy/button-group/manifest.json | 2 +- packages/ui/dist/copy/button-group/tokens.css | 4 + packages/ui/dist/copy/button/manifest.json | 2 +- packages/ui/dist/copy/button/tokens.css | 4 + packages/ui/dist/copy/card/manifest.json | 2 +- packages/ui/dist/copy/card/tokens.css | 4 + packages/ui/dist/copy/chart/manifest.json | 2 +- packages/ui/dist/copy/chart/tokens.css | 4 + packages/ui/dist/copy/checkbox/manifest.json | 2 +- packages/ui/dist/copy/checkbox/tokens.css | 4 + packages/ui/dist/copy/chip/manifest.json | 2 +- packages/ui/dist/copy/chip/tokens.css | 4 + .../ui/dist/copy/code-editor/manifest.json | 2 +- packages/ui/dist/copy/code-editor/tokens.css | 4 + packages/ui/dist/copy/combobox/manifest.json | 2 +- packages/ui/dist/copy/combobox/tokens.css | 4 + .../dist/copy/command-palette/manifest.json | 2 +- .../ui/dist/copy/command-palette/tokens.css | 4 + .../dist/copy/compact-dashboard/manifest.json | 2 +- .../ui/dist/copy/compact-dashboard/tokens.css | 4 + .../ui/dist/copy/data-table/manifest.json | 2 +- packages/ui/dist/copy/data-table/tokens.css | 4 + .../ui/dist/copy/date-picker/manifest.json | 2 +- packages/ui/dist/copy/date-picker/tokens.css | 4 + .../dist/copy/description-list/manifest.json | 2 +- .../ui/dist/copy/description-list/tokens.css | 4 + .../ui/dist/copy/diagnostics/manifest.json | 2 +- packages/ui/dist/copy/diagnostics/tokens.css | 4 + packages/ui/dist/copy/dialog/manifest.json | 2 +- packages/ui/dist/copy/dialog/tokens.css | 4 + packages/ui/dist/copy/diff-view/manifest.json | 2 +- packages/ui/dist/copy/diff-view/tokens.css | 4 + .../ui/dist/copy/disclosure/manifest.json | 2 +- packages/ui/dist/copy/disclosure/tokens.css | 4 + packages/ui/dist/copy/drawer/manifest.json | 2 +- packages/ui/dist/copy/drawer/tokens.css | 4 + .../ui/dist/copy/editor-search/manifest.json | 2 +- .../ui/dist/copy/editor-search/tokens.css | 4 + .../ui/dist/copy/empty-state/manifest.json | 2 +- packages/ui/dist/copy/empty-state/tokens.css | 4 + .../ui/dist/copy/error-state/manifest.json | 2 +- packages/ui/dist/copy/error-state/tokens.css | 4 + packages/ui/dist/copy/field/manifest.json | 2 +- packages/ui/dist/copy/field/tokens.css | 4 + packages/ui/dist/copy/fieldset/manifest.json | 2 +- packages/ui/dist/copy/fieldset/tokens.css | 4 + .../ui/dist/copy/file-browser/manifest.json | 2 +- packages/ui/dist/copy/file-browser/tokens.css | 4 + .../ui/dist/copy/file-input/manifest.json | 2 +- packages/ui/dist/copy/file-input/tokens.css | 4 + .../dist/copy/filterable-table/manifest.json | 2 +- .../ui/dist/copy/filterable-table/tokens.css | 4 + .../ui/dist/copy/form-builder/manifest.json | 12 +- ...r-EQnl1AaR.js => form-builder-C5Kx5G9b.js} | 2 +- ...r-Dkweb1xD.js => form-builder-C6Rhfsz6.js} | 4 +- .../runtime/register/form-builder.js | 2 +- packages/ui/dist/copy/form-builder/tokens.css | 4 + .../dist/copy/i3-window-frame/manifest.json | 2 +- .../ui/dist/copy/i3-window-frame/tokens.css | 4 + .../ui/dist/copy/icon-button/manifest.json | 2 +- packages/ui/dist/copy/icon-button/tokens.css | 4 + packages/ui/dist/copy/kbd/manifest.json | 2 +- packages/ui/dist/copy/kbd/tokens.css | 4 + packages/ui/dist/copy/link/manifest.json | 2 +- packages/ui/dist/copy/link/tokens.css | 4 + packages/ui/dist/copy/list/manifest.json | 2 +- packages/ui/dist/copy/list/tokens.css | 4 + .../dist/copy/loading-indicator/manifest.json | 2 +- .../ui/dist/copy/loading-indicator/tokens.css | 4 + packages/ui/dist/copy/menu/manifest.json | 2 +- packages/ui/dist/copy/menu/tokens.css | 4 + .../ui/dist/copy/multiselect/manifest.json | 2 +- packages/ui/dist/copy/multiselect/tokens.css | 4 + .../ui/dist/copy/number-field/manifest.json | 2 +- packages/ui/dist/copy/number-field/tokens.css | 4 + .../ui/dist/copy/pagination/manifest.json | 2 +- packages/ui/dist/copy/pagination/tokens.css | 4 + packages/ui/dist/copy/popover/manifest.json | 2 +- packages/ui/dist/copy/popover/tokens.css | 4 + packages/ui/dist/copy/progress/manifest.json | 2 +- packages/ui/dist/copy/progress/tokens.css | 4 + .../ui/dist/copy/radio-group/manifest.json | 2 +- packages/ui/dist/copy/radio-group/tokens.css | 4 + packages/ui/dist/copy/range/manifest.json | 2 +- packages/ui/dist/copy/range/tokens.css | 4 + packages/ui/dist/copy/repeater/manifest.json | 2 +- packages/ui/dist/copy/repeater/tokens.css | 4 + .../ui/dist/copy/search-field/manifest.json | 2 +- packages/ui/dist/copy/search-field/tokens.css | 4 + .../dist/copy/segmented-control/manifest.json | 2 +- .../ui/dist/copy/segmented-control/tokens.css | 4 + packages/ui/dist/copy/select/manifest.json | 2 +- packages/ui/dist/copy/select/tokens.css | 4 + .../ui/dist/copy/settings-panel/manifest.json | 2 +- .../ui/dist/copy/settings-panel/tokens.css | 4 + .../ui/dist/copy/sidebar-nav/manifest.json | 2 +- packages/ui/dist/copy/sidebar-nav/tokens.css | 4 + packages/ui/dist/copy/skeleton/manifest.json | 2 +- packages/ui/dist/copy/skeleton/tokens.css | 4 + packages/ui/dist/copy/skip-link/manifest.json | 2 +- packages/ui/dist/copy/skip-link/tokens.css | 4 + packages/ui/dist/copy/switch/manifest.json | 2 +- packages/ui/dist/copy/switch/tokens.css | 4 + packages/ui/dist/copy/table/manifest.json | 2 +- packages/ui/dist/copy/table/tokens.css | 4 + packages/ui/dist/copy/tabs/manifest.json | 2 +- packages/ui/dist/copy/tabs/tokens.css | 4 + packages/ui/dist/copy/terminal/manifest.json | 2 +- packages/ui/dist/copy/terminal/tokens.css | 4 + .../ui/dist/copy/text-field/manifest.json | 2 +- packages/ui/dist/copy/text-field/tokens.css | 4 + packages/ui/dist/copy/textarea/manifest.json | 2 +- packages/ui/dist/copy/textarea/tokens.css | 4 + .../ui/dist/copy/time-picker/manifest.json | 2 +- packages/ui/dist/copy/time-picker/tokens.css | 4 + packages/ui/dist/copy/timeline/manifest.json | 2 +- packages/ui/dist/copy/timeline/tokens.css | 4 + packages/ui/dist/copy/toast/manifest.json | 2 +- packages/ui/dist/copy/toast/tokens.css | 4 + packages/ui/dist/copy/toolbar/manifest.json | 2 +- packages/ui/dist/copy/toolbar/tokens.css | 4 + packages/ui/dist/copy/tooltip/manifest.json | 2 +- packages/ui/dist/copy/tooltip/tokens.css | 4 + packages/ui/dist/copy/tree/manifest.json | 2 +- packages/ui/dist/copy/tree/tokens.css | 4 + packages/ui/dist/copy/wizard/manifest.json | 2 +- packages/ui/dist/copy/wizard/tokens.css | 4 + packages/ui/dist/enhance/form-builder.js | 2 +- packages/ui/dist/index.js | 2 +- packages/ui/dist/manifest.json | 274 +-- packages/ui/dist/register/form-builder.js | 2 +- packages/ui/dist/tokens.css | 4 + ports/chatgpt/capabilities.json | 20 + ports/chatgpt/mapping.json | 4 + ports/chatgpt/port.json | 2 +- ports/claude-code/capabilities.json | 20 + ports/claude-code/mapping.json | 4 + ports/claude-code/port.json | 2 +- ports/codex/capabilities.json | 20 + ports/codex/mapping.json | 4 + ports/codex/port.json | 2 +- ports/ghostty/capabilities.json | 20 + ports/ghostty/mapping.json | 4 + ports/ghostty/port.json | 2 +- ports/obsidian/capabilities.json | 20 + ports/obsidian/mapping.json | 4 + ports/obsidian/port.json | 2 +- ports/orca/capabilities.json | 20 + ports/orca/mapping.json | 4 + ports/orca/port.json | 2 +- ports/telegram/capabilities.json | 20 + ports/telegram/mapping.json | 4 + ports/telegram/port.json | 2 +- ports/warp/capabilities.json | 20 + ports/warp/mapping.json | 4 + ports/warp/port.json | 2 +- ports/windows/capabilities.json | 20 + ports/windows/mapping.json | 4 + ports/windows/port.json | 2 +- schemas/roles.mjs | 4 +- site/src/styles/tokens.generated.css | 4 + spec/decisions.md | 18 + tests/telegram-port.test.js | 2 +- tokens/foundations.tokens.json | 26 + 463 files changed, 2568 insertions(+), 1399 deletions(-) rename packages/ui/dist/chunks/{form-builder-EQnl1AaR.js => form-builder-C5Kx5G9b.js} (99%) rename packages/ui/dist/chunks/{form-builder-Dkweb1xD.js => form-builder-C6Rhfsz6.js} (92%) rename packages/ui/dist/copy/form-builder/runtime/chunks/{form-builder-EQnl1AaR.js => form-builder-C5Kx5G9b.js} (99%) rename packages/ui/dist/copy/form-builder/runtime/chunks/{form-builder-Dkweb1xD.js => form-builder-C6Rhfsz6.js} (92%) diff --git a/docs/ui-architecture.md b/docs/ui-architecture.md index 182f24e05..e184e79e3 100644 --- a/docs/ui-architecture.md +++ b/docs/ui-architecture.md @@ -14,6 +14,11 @@ acceptance and deployment are in the separate delivery and execution records. - The portal and Vue showcase consume those outputs. They carry no second component implementation. +**Site chrome.** The portal is built from the same components it documents. +Chrome uses `comfortable` density and only canonical component classes: actions +are `.button` in one of the four tones, navigation is `.link`, calls to action +are `.link-standalone`. Forced states appear only inside specimens. + UI builds keep stable entry paths under `.cache/ui-build` so emitted bytes and implementation identities are reproducible. An exclusive `.cache/ui-build.lock` coordinates concurrent build and check processes; each waits for the prior diff --git a/exports/components/admin-form.brief.txt b/exports/components/admin-form.brief.txt index 203dfdd94..01b75f138 100644 --- a/exports/components/admin-form.brief.txt +++ b/exports/components/admin-form.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — admin-form -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/admin-form.json spec: spec/components/admin-form.md site: https://j3w1.github.io/theme/reference/#c-admin-form maturity: stable priority: R1 diff --git a/exports/components/admin-form.json b/exports/components/admin-form.json index 2a405a80e..d9c2f0098 100644 --- a/exports/components/admin-form.json +++ b/exports/components/admin-form.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "admin-form", "family": "composed", "maturity": "stable", diff --git a/exports/components/alert.brief.txt b/exports/components/alert.brief.txt index 37909003a..9113e82f1 100644 --- a/exports/components/alert.brief.txt +++ b/exports/components/alert.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — alert -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/alert.json spec: spec/components/alert.md site: https://j3w1.github.io/theme/reference/#c-alert maturity: stable priority: R1 diff --git a/exports/components/alert.json b/exports/components/alert.json index 734c00f1d..b89f74eb8 100644 --- a/exports/components/alert.json +++ b/exports/components/alert.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "alert", "family": "feedback", "maturity": "stable", diff --git a/exports/components/avatar.brief.txt b/exports/components/avatar.brief.txt index 009ad5602..313c2b7f8 100644 --- a/exports/components/avatar.brief.txt +++ b/exports/components/avatar.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — avatar -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/avatar.json spec: spec/components/avatar.md site: https://j3w1.github.io/theme/reference/#c-avatar maturity: stable priority: R2 diff --git a/exports/components/avatar.json b/exports/components/avatar.json index 4ad490b36..b87bc4ba6 100644 --- a/exports/components/avatar.json +++ b/exports/components/avatar.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "avatar", "family": "display", "maturity": "stable", diff --git a/exports/components/badge.brief.txt b/exports/components/badge.brief.txt index 750314488..9ce190f47 100644 --- a/exports/components/badge.brief.txt +++ b/exports/components/badge.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — badge -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/badge.json spec: spec/components/badge.md site: https://j3w1.github.io/theme/reference/#c-badge maturity: stable priority: R1 diff --git a/exports/components/badge.json b/exports/components/badge.json index 76242649a..e8fb3f1d9 100644 --- a/exports/components/badge.json +++ b/exports/components/badge.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "badge", "family": "display", "maturity": "stable", diff --git a/exports/components/breadcrumbs.brief.txt b/exports/components/breadcrumbs.brief.txt index 8858a6083..33822fe3b 100644 --- a/exports/components/breadcrumbs.brief.txt +++ b/exports/components/breadcrumbs.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — breadcrumbs -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/breadcrumbs.json spec: spec/components/breadcrumbs.md site: https://j3w1.github.io/theme/reference/#c-breadcrumbs maturity: stable priority: R1 diff --git a/exports/components/breadcrumbs.json b/exports/components/breadcrumbs.json index d8c3b7b70..4ad9f0157 100644 --- a/exports/components/breadcrumbs.json +++ b/exports/components/breadcrumbs.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "breadcrumbs", "family": "navigation", "maturity": "stable", diff --git a/exports/components/button-group.brief.txt b/exports/components/button-group.brief.txt index e35f637dc..3572c5af6 100644 --- a/exports/components/button-group.brief.txt +++ b/exports/components/button-group.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — button-group -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/button-group.json spec: spec/components/button-group.md site: https://j3w1.github.io/theme/reference/#c-button-group maturity: stable priority: R2 diff --git a/exports/components/button-group.json b/exports/components/button-group.json index 0528fea7b..c9ff24fe3 100644 --- a/exports/components/button-group.json +++ b/exports/components/button-group.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "button-group", "family": "actions", "maturity": "stable", diff --git a/exports/components/button.brief.txt b/exports/components/button.brief.txt index 744954ba7..d7c1d3d8d 100644 --- a/exports/components/button.brief.txt +++ b/exports/components/button.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — button -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/button.json spec: spec/components/button.md site: https://j3w1.github.io/theme/reference/#c-button maturity: stable priority: R1 diff --git a/exports/components/button.json b/exports/components/button.json index 7dfe1b679..09365a973 100644 --- a/exports/components/button.json +++ b/exports/components/button.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "button", "family": "actions", "maturity": "stable", diff --git a/exports/components/card.brief.txt b/exports/components/card.brief.txt index d731aa068..893c55853 100644 --- a/exports/components/card.brief.txt +++ b/exports/components/card.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — card -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/card.json spec: spec/components/card.md site: https://j3w1.github.io/theme/reference/#c-card maturity: stable priority: R1 diff --git a/exports/components/card.json b/exports/components/card.json index 9609b314d..32e6c7b3b 100644 --- a/exports/components/card.json +++ b/exports/components/card.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "card", "family": "display", "maturity": "stable", diff --git a/exports/components/chart.brief.txt b/exports/components/chart.brief.txt index 863a81cf6..2c4a7dc20 100644 --- a/exports/components/chart.brief.txt +++ b/exports/components/chart.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — chart -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/chart.json spec: spec/components/chart.md site: https://j3w1.github.io/theme/reference/#c-chart maturity: stable priority: R2 diff --git a/exports/components/chart.json b/exports/components/chart.json index d1b842613..c9589d641 100644 --- a/exports/components/chart.json +++ b/exports/components/chart.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "chart", "family": "display", "maturity": "stable", diff --git a/exports/components/checkbox.brief.txt b/exports/components/checkbox.brief.txt index d8a57ad06..cf9bbe6d5 100644 --- a/exports/components/checkbox.brief.txt +++ b/exports/components/checkbox.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — checkbox -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/checkbox.json spec: spec/components/checkbox.md site: https://j3w1.github.io/theme/reference/#c-checkbox maturity: stable priority: R1 diff --git a/exports/components/checkbox.json b/exports/components/checkbox.json index 85a51bebb..062776314 100644 --- a/exports/components/checkbox.json +++ b/exports/components/checkbox.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "checkbox", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/chip.brief.txt b/exports/components/chip.brief.txt index b7e11c251..5658aa138 100644 --- a/exports/components/chip.brief.txt +++ b/exports/components/chip.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — chip -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/chip.json spec: spec/components/chip.md site: https://j3w1.github.io/theme/reference/#c-chip maturity: stable priority: R1 diff --git a/exports/components/chip.json b/exports/components/chip.json index 9bcff6220..e3455073c 100644 --- a/exports/components/chip.json +++ b/exports/components/chip.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "chip", "family": "display", "maturity": "stable", diff --git a/exports/components/code-editor.brief.txt b/exports/components/code-editor.brief.txt index b4cd0a8c4..863fa0ab6 100644 --- a/exports/components/code-editor.brief.txt +++ b/exports/components/code-editor.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — code-editor -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/code-editor.json spec: spec/components/code-editor.md site: https://j3w1.github.io/theme/reference/#c-code-editor maturity: stable priority: R1 diff --git a/exports/components/code-editor.json b/exports/components/code-editor.json index 42dfd20e2..e9dfeed82 100644 --- a/exports/components/code-editor.json +++ b/exports/components/code-editor.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "code-editor", "family": "developer", "maturity": "stable", diff --git a/exports/components/combobox.brief.txt b/exports/components/combobox.brief.txt index 620ef89ca..21a400051 100644 --- a/exports/components/combobox.brief.txt +++ b/exports/components/combobox.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — combobox -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/combobox.json spec: spec/components/combobox.md site: https://j3w1.github.io/theme/reference/#c-combobox maturity: stable priority: R1 diff --git a/exports/components/combobox.json b/exports/components/combobox.json index 500aa3312..853b48f08 100644 --- a/exports/components/combobox.json +++ b/exports/components/combobox.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "combobox", "family": "forms-advanced", "maturity": "stable", diff --git a/exports/components/command-palette.brief.txt b/exports/components/command-palette.brief.txt index d47d873e0..cf506f177 100644 --- a/exports/components/command-palette.brief.txt +++ b/exports/components/command-palette.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — command-palette -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/command-palette.json spec: spec/components/command-palette.md site: https://j3w1.github.io/theme/reference/#c-command-palette maturity: stable priority: R2 diff --git a/exports/components/command-palette.json b/exports/components/command-palette.json index df74f683e..43037bcb9 100644 --- a/exports/components/command-palette.json +++ b/exports/components/command-palette.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "command-palette", "family": "navigation", "maturity": "stable", diff --git a/exports/components/compact-dashboard.brief.txt b/exports/components/compact-dashboard.brief.txt index defb1d2fe..01ab15244 100644 --- a/exports/components/compact-dashboard.brief.txt +++ b/exports/components/compact-dashboard.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — compact-dashboard -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/compact-dashboard.json spec: spec/components/compact-dashboard.md site: https://j3w1.github.io/theme/reference/#c-compact-dashboard maturity: stable priority: R2 diff --git a/exports/components/compact-dashboard.json b/exports/components/compact-dashboard.json index 0d40b822a..a4a93d2d4 100644 --- a/exports/components/compact-dashboard.json +++ b/exports/components/compact-dashboard.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "compact-dashboard", "family": "composed", "maturity": "stable", diff --git a/exports/components/data-table.brief.txt b/exports/components/data-table.brief.txt index 2b81908be..c5f721588 100644 --- a/exports/components/data-table.brief.txt +++ b/exports/components/data-table.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — data-table -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/data-table.json spec: spec/components/data-table.md site: https://j3w1.github.io/theme/reference/#c-data-table maturity: stable priority: R1 diff --git a/exports/components/data-table.json b/exports/components/data-table.json index 9624af95a..cfb7375ef 100644 --- a/exports/components/data-table.json +++ b/exports/components/data-table.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "data-table", "family": "display", "maturity": "stable", diff --git a/exports/components/date-picker.brief.txt b/exports/components/date-picker.brief.txt index 723556cd9..63718618b 100644 --- a/exports/components/date-picker.brief.txt +++ b/exports/components/date-picker.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — date-picker -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/date-picker.json spec: spec/components/date-picker.md site: https://j3w1.github.io/theme/reference/#c-date-picker maturity: stable priority: R1 diff --git a/exports/components/date-picker.json b/exports/components/date-picker.json index 6cc8aa696..66f885ab6 100644 --- a/exports/components/date-picker.json +++ b/exports/components/date-picker.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "date-picker", "family": "forms-advanced", "maturity": "stable", diff --git a/exports/components/description-list.brief.txt b/exports/components/description-list.brief.txt index 478bd8237..a9777ac63 100644 --- a/exports/components/description-list.brief.txt +++ b/exports/components/description-list.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — description-list -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/description-list.json spec: spec/components/description-list.md site: https://j3w1.github.io/theme/reference/#c-description-list maturity: stable priority: R2 diff --git a/exports/components/description-list.json b/exports/components/description-list.json index ccc501ae9..3cfa86b3f 100644 --- a/exports/components/description-list.json +++ b/exports/components/description-list.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "description-list", "family": "display", "maturity": "stable", diff --git a/exports/components/diagnostics.brief.txt b/exports/components/diagnostics.brief.txt index 3d6303bf1..dd3f4848c 100644 --- a/exports/components/diagnostics.brief.txt +++ b/exports/components/diagnostics.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — diagnostics -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/diagnostics.json spec: spec/components/diagnostics.md site: https://j3w1.github.io/theme/reference/#c-diagnostics maturity: stable priority: R1 diff --git a/exports/components/diagnostics.json b/exports/components/diagnostics.json index 1d594ef38..ad8d2b2a6 100644 --- a/exports/components/diagnostics.json +++ b/exports/components/diagnostics.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "diagnostics", "family": "developer", "maturity": "stable", diff --git a/exports/components/dialog.brief.txt b/exports/components/dialog.brief.txt index 0bad58b98..f094849ec 100644 --- a/exports/components/dialog.brief.txt +++ b/exports/components/dialog.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — dialog -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/dialog.json spec: spec/components/dialog.md site: https://j3w1.github.io/theme/reference/#c-dialog maturity: stable priority: R1 diff --git a/exports/components/dialog.json b/exports/components/dialog.json index e6f229c3e..e08cffa9e 100644 --- a/exports/components/dialog.json +++ b/exports/components/dialog.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "dialog", "family": "feedback", "maturity": "stable", diff --git a/exports/components/diff-view.brief.txt b/exports/components/diff-view.brief.txt index d708e2d46..81907a036 100644 --- a/exports/components/diff-view.brief.txt +++ b/exports/components/diff-view.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — diff-view -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/diff-view.json spec: spec/components/diff-view.md site: https://j3w1.github.io/theme/reference/#c-diff-view maturity: stable priority: R1 diff --git a/exports/components/diff-view.json b/exports/components/diff-view.json index fd541c692..b6b685ce3 100644 --- a/exports/components/diff-view.json +++ b/exports/components/diff-view.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "diff-view", "family": "developer", "maturity": "stable", diff --git a/exports/components/disclosure.brief.txt b/exports/components/disclosure.brief.txt index 74d7f47d3..3e9286645 100644 --- a/exports/components/disclosure.brief.txt +++ b/exports/components/disclosure.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — disclosure -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/disclosure.json spec: spec/components/disclosure.md site: https://j3w1.github.io/theme/reference/#c-disclosure maturity: stable priority: R2 diff --git a/exports/components/disclosure.json b/exports/components/disclosure.json index f1675afc8..b283693d6 100644 --- a/exports/components/disclosure.json +++ b/exports/components/disclosure.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "disclosure", "family": "navigation", "maturity": "stable", diff --git a/exports/components/drawer.brief.txt b/exports/components/drawer.brief.txt index cd65cbd42..2db724982 100644 --- a/exports/components/drawer.brief.txt +++ b/exports/components/drawer.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — drawer -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/drawer.json spec: spec/components/drawer.md site: https://j3w1.github.io/theme/reference/#c-drawer maturity: stable priority: R1 diff --git a/exports/components/drawer.json b/exports/components/drawer.json index 1dce4cf16..2da96c96d 100644 --- a/exports/components/drawer.json +++ b/exports/components/drawer.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "drawer", "family": "feedback", "maturity": "stable", diff --git a/exports/components/editor-search.brief.txt b/exports/components/editor-search.brief.txt index f40071ae8..be02293cd 100644 --- a/exports/components/editor-search.brief.txt +++ b/exports/components/editor-search.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — editor-search -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/editor-search.json spec: spec/components/editor-search.md site: https://j3w1.github.io/theme/reference/#c-editor-search maturity: stable priority: R2 diff --git a/exports/components/editor-search.json b/exports/components/editor-search.json index da485e0ae..c20a77318 100644 --- a/exports/components/editor-search.json +++ b/exports/components/editor-search.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "editor-search", "family": "developer", "maturity": "stable", diff --git a/exports/components/empty-state.brief.txt b/exports/components/empty-state.brief.txt index 1b3b9aa39..7e4c1861a 100644 --- a/exports/components/empty-state.brief.txt +++ b/exports/components/empty-state.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — empty-state -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/empty-state.json spec: spec/components/empty-state.md site: https://j3w1.github.io/theme/reference/#c-empty-state maturity: stable priority: R1 diff --git a/exports/components/empty-state.json b/exports/components/empty-state.json index 3576b5fe9..73066fccb 100644 --- a/exports/components/empty-state.json +++ b/exports/components/empty-state.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "empty-state", "family": "feedback", "maturity": "stable", diff --git a/exports/components/error-state.brief.txt b/exports/components/error-state.brief.txt index 160a309dc..6342f010b 100644 --- a/exports/components/error-state.brief.txt +++ b/exports/components/error-state.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — error-state -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/error-state.json spec: spec/components/error-state.md site: https://j3w1.github.io/theme/reference/#c-error-state maturity: stable priority: R2 diff --git a/exports/components/error-state.json b/exports/components/error-state.json index 67597b5e9..d3e8aa202 100644 --- a/exports/components/error-state.json +++ b/exports/components/error-state.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "error-state", "family": "feedback", "maturity": "stable", diff --git a/exports/components/field.brief.txt b/exports/components/field.brief.txt index 909e2a096..ce6583a2b 100644 --- a/exports/components/field.brief.txt +++ b/exports/components/field.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — field -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/field.json spec: spec/components/field.md site: https://j3w1.github.io/theme/reference/#c-field maturity: stable priority: R1 diff --git a/exports/components/field.json b/exports/components/field.json index b73218f9d..422db0182 100644 --- a/exports/components/field.json +++ b/exports/components/field.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "field", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/fieldset.brief.txt b/exports/components/fieldset.brief.txt index 98b5c1e07..9905df349 100644 --- a/exports/components/fieldset.brief.txt +++ b/exports/components/fieldset.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — fieldset -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/fieldset.json spec: spec/components/fieldset.md site: https://j3w1.github.io/theme/reference/#c-fieldset maturity: stable priority: R1 diff --git a/exports/components/fieldset.json b/exports/components/fieldset.json index bd73b8c84..e4207c56e 100644 --- a/exports/components/fieldset.json +++ b/exports/components/fieldset.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "fieldset", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/file-browser.brief.txt b/exports/components/file-browser.brief.txt index 5e0e6c966..a3ba5cd9b 100644 --- a/exports/components/file-browser.brief.txt +++ b/exports/components/file-browser.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — file-browser -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/file-browser.json spec: spec/components/file-browser.md site: https://j3w1.github.io/theme/reference/#c-file-browser maturity: stable priority: R2 diff --git a/exports/components/file-browser.json b/exports/components/file-browser.json index 434033e11..3a2728dc5 100644 --- a/exports/components/file-browser.json +++ b/exports/components/file-browser.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "file-browser", "family": "composed", "maturity": "stable", diff --git a/exports/components/file-input.brief.txt b/exports/components/file-input.brief.txt index 00439ea2b..b08d47350 100644 --- a/exports/components/file-input.brief.txt +++ b/exports/components/file-input.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — file-input -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/file-input.json spec: spec/components/file-input.md site: https://j3w1.github.io/theme/reference/#c-file-input maturity: stable priority: R1 diff --git a/exports/components/file-input.json b/exports/components/file-input.json index 7d2a4a833..ef0ebdf9d 100644 --- a/exports/components/file-input.json +++ b/exports/components/file-input.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "file-input", "family": "forms-advanced", "maturity": "stable", diff --git a/exports/components/filterable-table.brief.txt b/exports/components/filterable-table.brief.txt index 4053a2a31..7fcc1a081 100644 --- a/exports/components/filterable-table.brief.txt +++ b/exports/components/filterable-table.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — filterable-table -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/filterable-table.json spec: spec/components/filterable-table.md site: https://j3w1.github.io/theme/reference/#c-filterable-table maturity: stable priority: R1 diff --git a/exports/components/filterable-table.json b/exports/components/filterable-table.json index 7bfb6a3fc..4f4972eb9 100644 --- a/exports/components/filterable-table.json +++ b/exports/components/filterable-table.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "filterable-table", "family": "composed", "maturity": "stable", diff --git a/exports/components/form-builder.brief.txt b/exports/components/form-builder.brief.txt index e35f98b22..a09e3da9d 100644 --- a/exports/components/form-builder.brief.txt +++ b/exports/components/form-builder.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — form-builder -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/form-builder.json spec: spec/components/form-builder.md site: https://j3w1.github.io/theme/reference/#c-form-builder maturity: draft priority: L diff --git a/exports/components/form-builder.json b/exports/components/form-builder.json index 0dedf2bd2..05f599f70 100644 --- a/exports/components/form-builder.json +++ b/exports/components/form-builder.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "form-builder", "family": "forms-advanced", "maturity": "draft", diff --git a/exports/components/i3-window-frame.brief.txt b/exports/components/i3-window-frame.brief.txt index 8b6d5f64d..ee095d8ad 100644 --- a/exports/components/i3-window-frame.brief.txt +++ b/exports/components/i3-window-frame.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — i3-window-frame -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/i3-window-frame.json spec: spec/components/i3-window-frame.md site: https://j3w1.github.io/theme/reference/#c-i3-window-frame maturity: stable priority: R1 diff --git a/exports/components/i3-window-frame.json b/exports/components/i3-window-frame.json index eb42a5106..5f97c9ab6 100644 --- a/exports/components/i3-window-frame.json +++ b/exports/components/i3-window-frame.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "i3-window-frame", "family": "composed", "maturity": "stable", diff --git a/exports/components/icon-button.brief.txt b/exports/components/icon-button.brief.txt index a170fd628..be5237830 100644 --- a/exports/components/icon-button.brief.txt +++ b/exports/components/icon-button.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — icon-button -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/icon-button.json spec: spec/components/icon-button.md site: https://j3w1.github.io/theme/reference/#c-icon-button maturity: stable priority: R1 diff --git a/exports/components/icon-button.json b/exports/components/icon-button.json index 251daf19e..a531d358a 100644 --- a/exports/components/icon-button.json +++ b/exports/components/icon-button.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "icon-button", "family": "actions", "maturity": "stable", diff --git a/exports/components/kbd.brief.txt b/exports/components/kbd.brief.txt index 2e1818049..0072c1b55 100644 --- a/exports/components/kbd.brief.txt +++ b/exports/components/kbd.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — kbd -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/kbd.json spec: spec/components/kbd.md site: https://j3w1.github.io/theme/reference/#c-kbd maturity: stable priority: R2 diff --git a/exports/components/kbd.json b/exports/components/kbd.json index c7de78e55..f95f82cec 100644 --- a/exports/components/kbd.json +++ b/exports/components/kbd.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "kbd", "family": "display", "maturity": "stable", diff --git a/exports/components/link.brief.txt b/exports/components/link.brief.txt index 6a807e10e..4e57e7967 100644 --- a/exports/components/link.brief.txt +++ b/exports/components/link.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — link -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/link.json spec: spec/components/link.md site: https://j3w1.github.io/theme/reference/#c-link maturity: stable priority: R1 diff --git a/exports/components/link.json b/exports/components/link.json index 644a18354..4432d9d60 100644 --- a/exports/components/link.json +++ b/exports/components/link.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "link", "family": "actions", "maturity": "stable", diff --git a/exports/components/list.brief.txt b/exports/components/list.brief.txt index 3448154c1..7d2bbe884 100644 --- a/exports/components/list.brief.txt +++ b/exports/components/list.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — list -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/list.json spec: spec/components/list.md site: https://j3w1.github.io/theme/reference/#c-list maturity: stable priority: R1 diff --git a/exports/components/list.json b/exports/components/list.json index dc0863550..ee36d4e78 100644 --- a/exports/components/list.json +++ b/exports/components/list.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "list", "family": "display", "maturity": "stable", diff --git a/exports/components/loading-indicator.brief.txt b/exports/components/loading-indicator.brief.txt index de450c89a..bd7245285 100644 --- a/exports/components/loading-indicator.brief.txt +++ b/exports/components/loading-indicator.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — loading-indicator -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/loading-indicator.json spec: spec/components/loading-indicator.md site: https://j3w1.github.io/theme/reference/#c-loading-indicator maturity: stable priority: R1 diff --git a/exports/components/loading-indicator.json b/exports/components/loading-indicator.json index 104d2579b..4fd9e2a5c 100644 --- a/exports/components/loading-indicator.json +++ b/exports/components/loading-indicator.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "loading-indicator", "family": "feedback", "maturity": "stable", diff --git a/exports/components/menu.brief.txt b/exports/components/menu.brief.txt index 77b1da8da..655b159fe 100644 --- a/exports/components/menu.brief.txt +++ b/exports/components/menu.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — menu -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/menu.json spec: spec/components/menu.md site: https://j3w1.github.io/theme/reference/#c-menu maturity: stable priority: R1 diff --git a/exports/components/menu.json b/exports/components/menu.json index 347454645..01aa7ef1d 100644 --- a/exports/components/menu.json +++ b/exports/components/menu.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "menu", "family": "navigation", "maturity": "stable", diff --git a/exports/components/multiselect.brief.txt b/exports/components/multiselect.brief.txt index 224a6082a..058bc1f22 100644 --- a/exports/components/multiselect.brief.txt +++ b/exports/components/multiselect.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — multiselect -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/multiselect.json spec: spec/components/multiselect.md site: https://j3w1.github.io/theme/reference/#c-multiselect maturity: stable priority: R2 diff --git a/exports/components/multiselect.json b/exports/components/multiselect.json index a8ba1ce29..978d31ad5 100644 --- a/exports/components/multiselect.json +++ b/exports/components/multiselect.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "multiselect", "family": "forms-advanced", "maturity": "stable", diff --git a/exports/components/number-field.brief.txt b/exports/components/number-field.brief.txt index 51e5989a1..d3d67a5df 100644 --- a/exports/components/number-field.brief.txt +++ b/exports/components/number-field.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — number-field -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/number-field.json spec: spec/components/number-field.md site: https://j3w1.github.io/theme/reference/#c-number-field maturity: stable priority: R1 diff --git a/exports/components/number-field.json b/exports/components/number-field.json index bfb33549d..bfe51d25a 100644 --- a/exports/components/number-field.json +++ b/exports/components/number-field.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "number-field", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/pagination.brief.txt b/exports/components/pagination.brief.txt index 8a207d7ef..8c5ec2f23 100644 --- a/exports/components/pagination.brief.txt +++ b/exports/components/pagination.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — pagination -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/pagination.json spec: spec/components/pagination.md site: https://j3w1.github.io/theme/reference/#c-pagination maturity: stable priority: R1 diff --git a/exports/components/pagination.json b/exports/components/pagination.json index ff123f954..597aae01a 100644 --- a/exports/components/pagination.json +++ b/exports/components/pagination.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "pagination", "family": "navigation", "maturity": "stable", diff --git a/exports/components/popover.brief.txt b/exports/components/popover.brief.txt index 1666f5059..b5a526b0f 100644 --- a/exports/components/popover.brief.txt +++ b/exports/components/popover.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — popover -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/popover.json spec: spec/components/popover.md site: https://j3w1.github.io/theme/reference/#c-popover maturity: stable priority: R2 diff --git a/exports/components/popover.json b/exports/components/popover.json index dcf6bad54..f675faca6 100644 --- a/exports/components/popover.json +++ b/exports/components/popover.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "popover", "family": "feedback", "maturity": "stable", diff --git a/exports/components/progress.brief.txt b/exports/components/progress.brief.txt index 5ceef9185..87490fe0e 100644 --- a/exports/components/progress.brief.txt +++ b/exports/components/progress.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — progress -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/progress.json spec: spec/components/progress.md site: https://j3w1.github.io/theme/reference/#c-progress maturity: stable priority: R1 diff --git a/exports/components/progress.json b/exports/components/progress.json index 7c6daa591..590a3996a 100644 --- a/exports/components/progress.json +++ b/exports/components/progress.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "progress", "family": "feedback", "maturity": "stable", diff --git a/exports/components/radio-group.brief.txt b/exports/components/radio-group.brief.txt index c23871f9d..3fc2f6c4d 100644 --- a/exports/components/radio-group.brief.txt +++ b/exports/components/radio-group.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — radio-group -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/radio-group.json spec: spec/components/radio-group.md site: https://j3w1.github.io/theme/reference/#c-radio-group maturity: stable priority: R1 diff --git a/exports/components/radio-group.json b/exports/components/radio-group.json index 4a9111e7a..af3e3f65d 100644 --- a/exports/components/radio-group.json +++ b/exports/components/radio-group.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "radio-group", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/range.brief.txt b/exports/components/range.brief.txt index 1ac910e67..9c3e52baa 100644 --- a/exports/components/range.brief.txt +++ b/exports/components/range.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — range -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/range.json spec: spec/components/range.md site: https://j3w1.github.io/theme/reference/#c-range maturity: stable priority: R2 diff --git a/exports/components/range.json b/exports/components/range.json index 81b7ed980..b29548f1a 100644 --- a/exports/components/range.json +++ b/exports/components/range.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "range", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/repeater.brief.txt b/exports/components/repeater.brief.txt index 6bbff1e31..c1f87e376 100644 --- a/exports/components/repeater.brief.txt +++ b/exports/components/repeater.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — repeater -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/repeater.json spec: spec/components/repeater.md site: https://j3w1.github.io/theme/reference/#c-repeater maturity: stable priority: R2 diff --git a/exports/components/repeater.json b/exports/components/repeater.json index f3d24afd9..92632a4bb 100644 --- a/exports/components/repeater.json +++ b/exports/components/repeater.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "repeater", "family": "forms-advanced", "maturity": "stable", diff --git a/exports/components/search-field.brief.txt b/exports/components/search-field.brief.txt index 8f7b4fc47..ddd067bb1 100644 --- a/exports/components/search-field.brief.txt +++ b/exports/components/search-field.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — search-field -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/search-field.json spec: spec/components/search-field.md site: https://j3w1.github.io/theme/reference/#c-search-field maturity: stable priority: R1 diff --git a/exports/components/search-field.json b/exports/components/search-field.json index 1dcb56e9c..4ce060cc1 100644 --- a/exports/components/search-field.json +++ b/exports/components/search-field.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "search-field", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/segmented-control.brief.txt b/exports/components/segmented-control.brief.txt index c75e2ba88..b296fd3fa 100644 --- a/exports/components/segmented-control.brief.txt +++ b/exports/components/segmented-control.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — segmented-control -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/segmented-control.json spec: spec/components/segmented-control.md site: https://j3w1.github.io/theme/reference/#c-segmented-control maturity: stable priority: R2 diff --git a/exports/components/segmented-control.json b/exports/components/segmented-control.json index b157ecc0c..e08fc9601 100644 --- a/exports/components/segmented-control.json +++ b/exports/components/segmented-control.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "segmented-control", "family": "actions", "maturity": "stable", diff --git a/exports/components/select.brief.txt b/exports/components/select.brief.txt index bc69688aa..66903a2d0 100644 --- a/exports/components/select.brief.txt +++ b/exports/components/select.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — select -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/select.json spec: spec/components/select.md site: https://j3w1.github.io/theme/reference/#c-select maturity: stable priority: R1 diff --git a/exports/components/select.json b/exports/components/select.json index 012098b94..715260847 100644 --- a/exports/components/select.json +++ b/exports/components/select.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "select", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/settings-panel.brief.txt b/exports/components/settings-panel.brief.txt index 09c7c90bc..7d1d07bf5 100644 --- a/exports/components/settings-panel.brief.txt +++ b/exports/components/settings-panel.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — settings-panel -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/settings-panel.json spec: spec/components/settings-panel.md site: https://j3w1.github.io/theme/reference/#c-settings-panel maturity: stable priority: R1 diff --git a/exports/components/settings-panel.json b/exports/components/settings-panel.json index 611a3f401..0d365f760 100644 --- a/exports/components/settings-panel.json +++ b/exports/components/settings-panel.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "settings-panel", "family": "composed", "maturity": "stable", diff --git a/exports/components/sidebar-nav.brief.txt b/exports/components/sidebar-nav.brief.txt index ef004d8a0..1f9397eac 100644 --- a/exports/components/sidebar-nav.brief.txt +++ b/exports/components/sidebar-nav.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — sidebar-nav -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/sidebar-nav.json spec: spec/components/sidebar-nav.md site: https://j3w1.github.io/theme/reference/#c-sidebar-nav maturity: stable priority: R1 diff --git a/exports/components/sidebar-nav.json b/exports/components/sidebar-nav.json index 6865d49fa..fb4dad9bf 100644 --- a/exports/components/sidebar-nav.json +++ b/exports/components/sidebar-nav.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "sidebar-nav", "family": "navigation", "maturity": "stable", diff --git a/exports/components/skeleton.brief.txt b/exports/components/skeleton.brief.txt index ed1c366d3..9cc80ee0c 100644 --- a/exports/components/skeleton.brief.txt +++ b/exports/components/skeleton.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — skeleton -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/skeleton.json spec: spec/components/skeleton.md site: https://j3w1.github.io/theme/reference/#c-skeleton maturity: stable priority: R2 diff --git a/exports/components/skeleton.json b/exports/components/skeleton.json index 63dd2a064..e9101ab3e 100644 --- a/exports/components/skeleton.json +++ b/exports/components/skeleton.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "skeleton", "family": "feedback", "maturity": "stable", diff --git a/exports/components/skip-link.brief.txt b/exports/components/skip-link.brief.txt index 20f65be56..14dadba49 100644 --- a/exports/components/skip-link.brief.txt +++ b/exports/components/skip-link.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — skip-link -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/skip-link.json spec: spec/components/skip-link.md site: https://j3w1.github.io/theme/reference/#c-skip-link maturity: stable priority: R1 diff --git a/exports/components/skip-link.json b/exports/components/skip-link.json index 0ee9a6759..eb5f58930 100644 --- a/exports/components/skip-link.json +++ b/exports/components/skip-link.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "skip-link", "family": "navigation", "maturity": "stable", diff --git a/exports/components/switch.brief.txt b/exports/components/switch.brief.txt index a17de861e..aa4ed8643 100644 --- a/exports/components/switch.brief.txt +++ b/exports/components/switch.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — switch -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/switch.json spec: spec/components/switch.md site: https://j3w1.github.io/theme/reference/#c-switch maturity: stable priority: R1 diff --git a/exports/components/switch.json b/exports/components/switch.json index e9672d2d0..3e5bb8974 100644 --- a/exports/components/switch.json +++ b/exports/components/switch.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "switch", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/table.brief.txt b/exports/components/table.brief.txt index d5d555127..8bd041232 100644 --- a/exports/components/table.brief.txt +++ b/exports/components/table.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — table -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/table.json spec: spec/components/table.md site: https://j3w1.github.io/theme/reference/#c-table maturity: stable priority: R1 diff --git a/exports/components/table.json b/exports/components/table.json index 43b389639..a4ff2f9d6 100644 --- a/exports/components/table.json +++ b/exports/components/table.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "table", "family": "display", "maturity": "stable", diff --git a/exports/components/tabs.brief.txt b/exports/components/tabs.brief.txt index 21913e896..c7d3da52d 100644 --- a/exports/components/tabs.brief.txt +++ b/exports/components/tabs.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — tabs -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/tabs.json spec: spec/components/tabs.md site: https://j3w1.github.io/theme/reference/#c-tabs maturity: stable priority: R1 diff --git a/exports/components/tabs.json b/exports/components/tabs.json index 58485f204..865b1b258 100644 --- a/exports/components/tabs.json +++ b/exports/components/tabs.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "tabs", "family": "navigation", "maturity": "stable", diff --git a/exports/components/terminal.brief.txt b/exports/components/terminal.brief.txt index 1bc51fe04..35baa7144 100644 --- a/exports/components/terminal.brief.txt +++ b/exports/components/terminal.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — terminal -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/terminal.json spec: spec/components/terminal.md site: https://j3w1.github.io/theme/reference/#c-terminal maturity: stable priority: R1 diff --git a/exports/components/terminal.json b/exports/components/terminal.json index ea4d0847a..f7e9bba1a 100644 --- a/exports/components/terminal.json +++ b/exports/components/terminal.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "terminal", "family": "developer", "maturity": "stable", diff --git a/exports/components/text-field.brief.txt b/exports/components/text-field.brief.txt index 4a2105890..00531521e 100644 --- a/exports/components/text-field.brief.txt +++ b/exports/components/text-field.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — text-field -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/text-field.json spec: spec/components/text-field.md site: https://j3w1.github.io/theme/reference/#c-text-field maturity: stable priority: R1 diff --git a/exports/components/text-field.json b/exports/components/text-field.json index 739cfa09b..719e1ea0c 100644 --- a/exports/components/text-field.json +++ b/exports/components/text-field.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "text-field", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/textarea.brief.txt b/exports/components/textarea.brief.txt index 9d63e061e..1da02c43d 100644 --- a/exports/components/textarea.brief.txt +++ b/exports/components/textarea.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — textarea -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/textarea.json spec: spec/components/textarea.md site: https://j3w1.github.io/theme/reference/#c-textarea maturity: stable priority: R1 diff --git a/exports/components/textarea.json b/exports/components/textarea.json index 78d7dacfc..e28cba603 100644 --- a/exports/components/textarea.json +++ b/exports/components/textarea.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "textarea", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/time-picker.brief.txt b/exports/components/time-picker.brief.txt index 5dc301af5..e797bbf59 100644 --- a/exports/components/time-picker.brief.txt +++ b/exports/components/time-picker.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — time-picker -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/time-picker.json spec: spec/components/time-picker.md site: https://j3w1.github.io/theme/reference/#c-time-picker maturity: stable priority: R1 diff --git a/exports/components/time-picker.json b/exports/components/time-picker.json index 0587e84cf..9621c6b91 100644 --- a/exports/components/time-picker.json +++ b/exports/components/time-picker.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "time-picker", "family": "forms-advanced", "maturity": "stable", diff --git a/exports/components/timeline.brief.txt b/exports/components/timeline.brief.txt index 6aa685053..b7605dabb 100644 --- a/exports/components/timeline.brief.txt +++ b/exports/components/timeline.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — timeline -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/timeline.json spec: spec/components/timeline.md site: https://j3w1.github.io/theme/reference/#c-timeline maturity: stable priority: R2 diff --git a/exports/components/timeline.json b/exports/components/timeline.json index 83ff40778..65d07dcf2 100644 --- a/exports/components/timeline.json +++ b/exports/components/timeline.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "timeline", "family": "display", "maturity": "stable", diff --git a/exports/components/toast.brief.txt b/exports/components/toast.brief.txt index 578d53f13..5a1ea4945 100644 --- a/exports/components/toast.brief.txt +++ b/exports/components/toast.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — toast -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/toast.json spec: spec/components/toast.md site: https://j3w1.github.io/theme/reference/#c-toast maturity: stable priority: R1 diff --git a/exports/components/toast.json b/exports/components/toast.json index cfe4f70b4..e628b3eb1 100644 --- a/exports/components/toast.json +++ b/exports/components/toast.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "toast", "family": "feedback", "maturity": "stable", diff --git a/exports/components/toolbar.brief.txt b/exports/components/toolbar.brief.txt index 4df98396b..c2a1b7df1 100644 --- a/exports/components/toolbar.brief.txt +++ b/exports/components/toolbar.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — toolbar -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/toolbar.json spec: spec/components/toolbar.md site: https://j3w1.github.io/theme/reference/#c-toolbar maturity: stable priority: R1 diff --git a/exports/components/toolbar.json b/exports/components/toolbar.json index 91e767555..4ce267549 100644 --- a/exports/components/toolbar.json +++ b/exports/components/toolbar.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "toolbar", "family": "navigation", "maturity": "stable", diff --git a/exports/components/tooltip.brief.txt b/exports/components/tooltip.brief.txt index 68b71d97f..37f2c931a 100644 --- a/exports/components/tooltip.brief.txt +++ b/exports/components/tooltip.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — tooltip -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/tooltip.json spec: spec/components/tooltip.md site: https://j3w1.github.io/theme/reference/#c-tooltip maturity: stable priority: R1 diff --git a/exports/components/tooltip.json b/exports/components/tooltip.json index ddb21e5a0..0037674f6 100644 --- a/exports/components/tooltip.json +++ b/exports/components/tooltip.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "tooltip", "family": "feedback", "maturity": "stable", diff --git a/exports/components/tree.brief.txt b/exports/components/tree.brief.txt index 6f20fec4b..63e6400c7 100644 --- a/exports/components/tree.brief.txt +++ b/exports/components/tree.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — tree -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/tree.json spec: spec/components/tree.md site: https://j3w1.github.io/theme/reference/#c-tree maturity: stable priority: R2 diff --git a/exports/components/tree.json b/exports/components/tree.json index 0a8264775..f84767084 100644 --- a/exports/components/tree.json +++ b/exports/components/tree.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "tree", "family": "navigation", "maturity": "stable", diff --git a/exports/components/wizard.brief.txt b/exports/components/wizard.brief.txt index 113dd2079..2b0a620d2 100644 --- a/exports/components/wizard.brief.txt +++ b/exports/components/wizard.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — wizard -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/wizard.json spec: spec/components/wizard.md site: https://j3w1.github.io/theme/reference/#c-wizard maturity: stable priority: R1 diff --git a/exports/components/wizard.json b/exports/components/wizard.json index ba5a2363b..54bce18a8 100644 --- a/exports/components/wizard.json +++ b/exports/components/wizard.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "wizard", "family": "forms-advanced", "maturity": "stable", diff --git a/exports/digests.json b/exports/digests.json index 509e017a1..d2131d960 100644 --- a/exports/digests.json +++ b/exports/digests.json @@ -4,185 +4,185 @@ "version": "4.0.0", "algorithm": "sha256 over the file bytes with LF line endings, base64", "files": { - "exports/components/admin-form.brief.txt": "sha256-jwbJKT11RRI34ePCq2IZgv9dBT7kJBBLQ3Zybe5/jSo=", - "exports/components/admin-form.json": "sha256-eRnLywYWpnSnpPiv4MrY0aGZ7BpZEkrJG13tpAxopto=", - "exports/components/alert.brief.txt": "sha256-rklZ1GpI83ub+WSO7GqAjjMnrI41zBQk9LVcUM0bdKU=", - "exports/components/alert.json": "sha256-fY305BXYtrgqi7ICbnawYPMKZC9ff3t3yJ4I2vRbBZU=", - "exports/components/avatar.brief.txt": "sha256-sX1FufhH9Of0Wg7tYb1qJF2AaoZjPCEI4JKafGBQvh8=", - "exports/components/avatar.json": "sha256-xsnyI/5aT2MHasx+JQVNpW8boRicxTzw7yA1saDCjnY=", - "exports/components/badge.brief.txt": "sha256-NslILG4XhfIXyC6aLyGhrkbvklIeBFiflyClTeOCPrc=", - "exports/components/badge.json": "sha256-DwK1qRsb78sSqHyFijG2LGi2lFpfbsuqo/Hn0S+uvK8=", - "exports/components/breadcrumbs.brief.txt": "sha256-xd40jmACLs9vAhAzWiDoluy8v8TmyYZKsP+Zr9SZs2Q=", - "exports/components/breadcrumbs.json": "sha256-zQLfzLX17c6/w9Qc+NDjT46WgvUPizPDz+c6bFM0ghQ=", - "exports/components/button-group.brief.txt": "sha256-4HJE5CQp4x1LbFRLV2eYseIZbWiVzPk15tQTwmG9bKQ=", - "exports/components/button-group.json": "sha256-BSp7Mjeyt4XOWCQXFLRlAx8sJg9nw2GeACg8H+o0FEE=", - "exports/components/button.brief.txt": "sha256-LHU7uNc+/4xF0VXS2ViCRPO5cL8EtquoqPcOBKODthE=", - "exports/components/button.json": "sha256-4p1xTZHKv9gloF1QMtXjx9iP2eX9r9MiKd820lW31eA=", - "exports/components/card.brief.txt": "sha256-a1yzkDx21v3mHLSNDl4AUzF17Q5AAuEZ8C1Dj/JHjXg=", - "exports/components/card.json": "sha256-0yl0cP1PZEnhNuyuDaCh3Sruv1J0TcGwSnVqV6RsJwM=", - "exports/components/chart.brief.txt": "sha256-F8wLgwaGUYUf4JdJPwCMkQwOHrJoeWqhBMOWsnJoSmE=", - "exports/components/chart.json": "sha256-oeL0YqV4bPrm0R9MGZYndDvymTiIipuRNuV6dSTNAWc=", - "exports/components/checkbox.brief.txt": "sha256-dsJdM6l743WIHvRnxMpMbtJwPta4eJFeytTutCxRVvg=", - "exports/components/checkbox.json": "sha256-vKh60jFbH2dStEUVLlAcQGeDkBvWNoY+xASXA2PBvD8=", - "exports/components/chip.brief.txt": "sha256-MrN6hScgTkyStDvURTUbSWV8sPthyw2eW7TN51FB+aw=", - "exports/components/chip.json": "sha256-PUw2hBa9KFySjCvs2KFCcOHknMs3XPW4cmQMZt19Wgg=", - "exports/components/code-editor.brief.txt": "sha256-Pyqk4j6Gb+hpBNBUxbwgCpug4PbCqFOkjiV0SkoHnJw=", - "exports/components/code-editor.json": "sha256-BEBkn4aICM9agXkKXXoD/Vp2vBw9L9xzf+PskyKutps=", - "exports/components/combobox.brief.txt": "sha256-sDigjW+d4STxWdO04+ez10WOcsEjxzil7iji+WwHuu8=", - "exports/components/combobox.json": "sha256-L40mUBv9JftFkoxyytSym7B7RdgvPbzJepfORUt1D+E=", - "exports/components/command-palette.brief.txt": "sha256-TFWPsSRtBxSKsRvQ8n7iQvQRj2vLCoeytkAWBaLBhls=", - "exports/components/command-palette.json": "sha256-v+uBQa15HR8RmrV4TgtASLLL6heTJxuxXd0eLANkAr8=", - "exports/components/compact-dashboard.brief.txt": "sha256-Ubi85HbRa57eo2ZcPeR29fBSefMsgpQmFa2LFxEdKvg=", - "exports/components/compact-dashboard.json": "sha256-46PH1YfxF9fa19v3TMeXZQ7cunnFu60zupp+ilyPDX0=", - "exports/components/data-table.brief.txt": "sha256-LUYVi6Y/DQ+wNLwRJF1KJLs5Jkf3inDckdL99BcWGNE=", - "exports/components/data-table.json": "sha256-Jx64WzlClg9ZEjLxdNQtSVyug+zJB8nR/9Az2E7rjD0=", - "exports/components/date-picker.brief.txt": "sha256-wpASanHFamM0GppDmLIB4YFPeb/m3L1z0BHbU8aolwc=", - "exports/components/date-picker.json": "sha256-OUGlLh96huXjIEMtVvEA+FVyp4wx1rVR4Ycj0/4jqA0=", - "exports/components/description-list.brief.txt": "sha256-qt/tuSFsWeWoAR8vT6gmrHxhNKBuSif4rdzz7YJcCJY=", - "exports/components/description-list.json": "sha256-23PielDBv+IvWwGgCucwAFo4aOa2I3rvIyFz7s2Ppm8=", - "exports/components/diagnostics.brief.txt": "sha256-fDI7OSxc9CY2EGyzUuGDN9LXb6FQkIk6IxKnvfVddXU=", - "exports/components/diagnostics.json": "sha256-DCtdyZ1SB9wO/wcv2e7Vm9K7r7zgTZ/usd0BW+Q+Qns=", - "exports/components/dialog.brief.txt": "sha256-MeLS6MnOQ4F3YA+bgXxqldQr2QqGqPVEpa9MBUHNq20=", - "exports/components/dialog.json": "sha256-3biN4pOh3Xno1zp8fqp+lfgzhZVGDs3fvOwL+ykPLRo=", - "exports/components/diff-view.brief.txt": "sha256-5sEpsA7IuW4dn3BcFHpxXp7FU/Owat7eNbtWLQi5WLQ=", - "exports/components/diff-view.json": "sha256-8wdU0wsWaPK9CQrN7RrbVRlH5MPJzkVRaeSCXtrR62k=", - "exports/components/disclosure.brief.txt": "sha256-PBh8PsiZMnkrLvA7J8mdgnfXSqli0Dd91tJ/M8DIJew=", - "exports/components/disclosure.json": "sha256-shzZ4BJIKao0FVzzv9rmRShM3oUhpXciXiPAEYxhDUg=", - "exports/components/drawer.brief.txt": "sha256-cmJq98a/qV5OXb+5Iobm91BjUAb/Ez0l0FTXIi3RIAc=", - "exports/components/drawer.json": "sha256-QV4H85dSIRy6UAX3RNVGkFy9s2CYHMnbc+T3AozYPfY=", - "exports/components/editor-search.brief.txt": "sha256-oGPJsSf97swfk6I0Px+Ogx50f9iB2xvIZskWvHPV5No=", - "exports/components/editor-search.json": "sha256-Gs8sGmYigdm6zJuRk6PO3SZ7DTxlvC8rYJDfMFv2LGQ=", - "exports/components/empty-state.brief.txt": "sha256-xoJJajh7uUY4yFWQRymXX00+4V+jAsO2by2dLHf2Hqs=", - "exports/components/empty-state.json": "sha256-csrcqKJBMSQ83ah0QGhwEUBUJCzTxs/gmI7Fyew7SAk=", - "exports/components/error-state.brief.txt": "sha256-eZuKDN0F7cPX8xMwgUpDT7Am+FiA2SmyNc1Wr1T2VLk=", - "exports/components/error-state.json": "sha256-J2Ybn0Dp2zC6DcaNms4M95wSwRuOVbdCbSwVTtZBs3A=", - "exports/components/field.brief.txt": "sha256-K/lQS8fpFmYJl7DgnxQOLbEhpIe8bMu2DX+k/dmsHoo=", - "exports/components/field.json": "sha256-CwS97OOd/TiSLj14ddTEjLtB+YFwuFwzOeO3Dh0QQyM=", - "exports/components/fieldset.brief.txt": "sha256-0mxGVYfmgWha3+UoiRC/uXVQ9iQMLg8jOpko+2mdWPA=", - "exports/components/fieldset.json": "sha256-GoUuPV0K4ZEke68Rd5Rep63pZdJrVq0wcP5mtKWaJSA=", - "exports/components/file-browser.brief.txt": "sha256-S5E5Sq1wzWZW3Q0XAvmn1ZtSdAmMtYk/nzM/zxGpuoQ=", - "exports/components/file-browser.json": "sha256-uCnasCmeUQYFtNwJUXAO41JiYtF8z/0EFeoJLvN0jdc=", - "exports/components/file-input.brief.txt": "sha256-MkQDUqeNztoQb94eo3z4EbngNHxY2iL4VU4/CpIPDnQ=", - "exports/components/file-input.json": "sha256-WJZZCzR/rBLpBfBw8APEkufz7gWWEslnGppb/sKAni8=", - "exports/components/filterable-table.brief.txt": "sha256-Cjg4yAjWIfntKkK3rp4sC6ZrOivlikBZaorcJwFoCgI=", - "exports/components/filterable-table.json": "sha256-UFRKkL/36KWNeQWcJ7D0jfZmLoSXvaabNYfVxXy6bBY=", - "exports/components/form-builder.brief.txt": "sha256-jfd9rmwYNaA5t+oZaTbmA4vaGWhBXCMl6tAAGrK/Vq4=", - "exports/components/form-builder.json": "sha256-7EFKC4g8k2rGhehRW1TKvQgyFpElPMPvf33C83xJRNw=", - "exports/components/i3-window-frame.brief.txt": "sha256-HfivqWim5SQbuChd3mlgLGrxRgbQWUtbxX2FbSHlca8=", - "exports/components/i3-window-frame.json": "sha256-3vAv8bfDYiK/FtH4WKmbicoPHFOznTjnqcDlaNK7dt8=", - "exports/components/icon-button.brief.txt": "sha256-QBJjYtgZgDOaDsxE2ICHNeDpSCmmQe9+6QPC1eX5YMY=", - "exports/components/icon-button.json": "sha256-RJm9x6pPDFnF9Q23dbBmUb0E50a1MAx3JroWrDWKS5M=", - "exports/components/kbd.brief.txt": "sha256-ep5N3e/tLj5AzWsy6NHQq9D9VvhyRSLzZ/AAtkuekto=", - "exports/components/kbd.json": "sha256-l5Bw/Ul8RVifiaH6ooa8AlA5sakuJCoZOPQQbPduvYg=", - "exports/components/link.brief.txt": "sha256-+aoKEUepkO+LwMFKQSHfg6qFwtVrsYSYDIdjdlRGwOs=", - "exports/components/link.json": "sha256-+bhCm/tbl4N7iCv2WO4cqaTh4FIT5+MPZHd1u3z4R+s=", - "exports/components/list.brief.txt": "sha256-8oK96x+T4WjoZl3WUKj0usPgd0wZZm/Hv+Sat4AzFrM=", - "exports/components/list.json": "sha256-MpHwE+aKAPvY3CcyudupD7Lw0IjZBimlMjT6TuaS0hA=", - "exports/components/loading-indicator.brief.txt": "sha256-zFgayI5iWwyiRUqrCVPuBEHJZso55nUAXx+ikicaN1E=", - "exports/components/loading-indicator.json": "sha256-2QKuRjZVJXAgdPIO8G8Y6aJ9KGxA6o6rOiSEp/PvcYE=", - "exports/components/menu.brief.txt": "sha256-rQ5I6zaH4mWpqQkN1ObSUmBLu8s6RidDgZ8OiJLvoeE=", - "exports/components/menu.json": "sha256-muiitCeijBJjHeaTp/QQx6+IEmQOM4cWE9TrKO77e1Y=", - "exports/components/multiselect.brief.txt": "sha256-loE95Wt2oY55Nlvr1jUaYy9xK6Uf92kavNRUwpx7w/w=", - "exports/components/multiselect.json": "sha256-4KQgviHmIt6BV24Ovi6iT9bZsRYCKoLRsXv3+6e7bAI=", - "exports/components/number-field.brief.txt": "sha256-nFpFbOWiT1PS84To0htAJv+CS6cpE1YMEutRow3bFGY=", - "exports/components/number-field.json": "sha256-X2RtxXMFv9aZYoHXBehlz8Yd1gRUJGBEaxlrbbpw2dc=", - "exports/components/pagination.brief.txt": "sha256-x9ShiFh4URPO53miHCA7h7hf+ohLXJRZE+tPunBPWpI=", - "exports/components/pagination.json": "sha256-yn4BdNlOV/vtz3svE4If1Bbov1AfMfzpKdiAN6133nA=", - "exports/components/popover.brief.txt": "sha256-CO4SUkjvXA+x5h0be6BlGgvoM2zJ7SEJr0escROTZ1U=", - "exports/components/popover.json": "sha256-EqTG6rC/VtjPzPC5p+8mQCZRmyKmpPaM/gyjnu4fkBs=", - "exports/components/progress.brief.txt": "sha256-6W1ZNcJQH2XpKlMW5VW5ssECR/JfEB5NhaiiUox/Dq4=", - "exports/components/progress.json": "sha256-gQkfI0q7nw95iejhwbgBL+qnK3YC1Ti/A/fqHcUFodw=", - "exports/components/radio-group.brief.txt": "sha256-VFh1W2owO0rv2vP0lxRcVM6BkltbWP13x0QH17x9YTU=", - "exports/components/radio-group.json": "sha256-EfvnwOBwd3pdtmPY0Islp1+TgVzZNhfl2aMwwy/ct0k=", - "exports/components/range.brief.txt": "sha256-c6UdGCwDV/qHcsvsgfEAcwVpJiSGMlsv3POU8Uqnnew=", - "exports/components/range.json": "sha256-acSO0+fixlkKfME6RFcpK00skJMP8gDNPoJhx0jbz90=", - "exports/components/repeater.brief.txt": "sha256-GvadRIC2Mm2d/zAiAEBaoIjsjq81qseZIgPSoT47Erk=", - "exports/components/repeater.json": "sha256-hd5TfCdk3cefdLf2qQ2VvfCFQ0SZRelNey3Rrg+Po5s=", - "exports/components/search-field.brief.txt": "sha256-a4ANkSO5Rms2zHpDdcqsoXVkjOwdGjNvBlFPf8jK8pA=", - "exports/components/search-field.json": "sha256-mBG4aed8CuPQnOqvyyO2Ki/6P7Kd+scL0gvy8BSuh0I=", - "exports/components/segmented-control.brief.txt": "sha256-c2caBWX9z9rZtgmJ902mgeEsWnulDt7zecmw5VY7YSE=", - "exports/components/segmented-control.json": "sha256-NxtziV/OygaDGi6mc6tElJnGbo/IMXmL3Kw0oo4hbWo=", - "exports/components/select.brief.txt": "sha256-SSqgUQstDuH32j/2q4Lzb5ww9flG95DLFagHpoV6jns=", - "exports/components/select.json": "sha256-lxY8viVzwv7lZNWQb25Q710kRbpjsvAiJOCyNsswl/A=", - "exports/components/settings-panel.brief.txt": "sha256-9CbevnNhJSFp+J6YeUF6wFk1wS+1eYu1TAOPJGuVzyk=", - "exports/components/settings-panel.json": "sha256-3LcKWsvRUalOjqpJ8BWHz+NwCeeE1QPVVYKBDRl95c0=", - "exports/components/sidebar-nav.brief.txt": "sha256-SKPC3g84XpJQTQ4b5sapCA5RLvD+NACA09xQacV5Xeg=", - "exports/components/sidebar-nav.json": "sha256-DH9/5y5vhlFC2xhkSRxPHjQUItnETFyylJNlL/eQvZA=", - "exports/components/skeleton.brief.txt": "sha256-3nMJPclGi35+1LPNI3hd4T/RkuX8w8SNxERjXaphKPA=", - "exports/components/skeleton.json": "sha256-G4HrDr9EuEoWZF5QAu2me2ELZv5wbUmJ3BdH88gd2qI=", - "exports/components/skip-link.brief.txt": "sha256-uWgPPgVHrviYczQc2R+mCKgjG+v9o+sou/L2H4k7Rgs=", - "exports/components/skip-link.json": "sha256-BVXQbbhH/Yw/1w4ZH4udwjBvHR9EvpaFCklwRMaBzSY=", - "exports/components/switch.brief.txt": "sha256-PkD0mYGPxqAOdW5f1J8DQZesYnK0BSSIvdR6QUJLudM=", - "exports/components/switch.json": "sha256-oxfIG+7uoRIjqhOX8NJeLOwk96/YOO4xuorhVjcMeBA=", - "exports/components/table.brief.txt": "sha256-OALSm9v4rRsh9VsVmFLV2qRFRSM2nQgJDTX8QLHXIrY=", - "exports/components/table.json": "sha256-SuXNBFtY8Ta7SYiGP++3vK2F1R5qMDhCqm9MsNridnE=", - "exports/components/tabs.brief.txt": "sha256-ksrBHegd+PyVjuaCZDLYEmY8UA1QdiCNL/muJRxmvJc=", - "exports/components/tabs.json": "sha256-kvXJtwi+CXSlwSfuKCFXif3+f4RC46YAdX5OscNk7Ak=", - "exports/components/terminal.brief.txt": "sha256-1WGDa0H6DgukYvYsBMi8b0Ue10UfUwIlesYllmzMZME=", - "exports/components/terminal.json": "sha256-XyXr8dnvYT95prOlPBbRj5a9g68EAugPetzv9jAKXMs=", - "exports/components/text-field.brief.txt": "sha256-/c2NU74fJuS1fNhxw4dlm/qA+uuTKsyQnug1lMZuZDU=", - "exports/components/text-field.json": "sha256-Lex9v1t/4/YXIFJqbJxCwK/4nVl7XPA9D+FEjx0Rn6M=", - "exports/components/textarea.brief.txt": "sha256-0cOxpL4Gck+odFRgkvgepAHWj005baxIU37L8NZMymg=", - "exports/components/textarea.json": "sha256-qV1f7XUpYBKJjKIEnduDtBzG6e0UNZC/YT0VDcNdnCQ=", - "exports/components/time-picker.brief.txt": "sha256-rYH+sfgpjx3LQMjVOUZSSiFlbAhWaWStROmrndPGrCE=", - "exports/components/time-picker.json": "sha256-n9Z27zWFtF0b3GMeCpOO+TyPM/HbKs5YHSFtnu3R8cs=", - "exports/components/timeline.brief.txt": "sha256-LuiZyplAYzu0X5usb55xix3hUbc5sngfFJg7paKC6Dc=", - "exports/components/timeline.json": "sha256-24hw5t5rGVCeQYH/Z0ZPIcm2M/rSYkqCJmgitCPU4ok=", - "exports/components/toast.brief.txt": "sha256-26lfVi1CKS7W31SkMHKFaAeWR0ZsahYdtxsQAxYhPuY=", - "exports/components/toast.json": "sha256-iLhC7qFWAYHMbtBKnDeDEPkHEQ9tbsB6tG/Y9lswAUI=", - "exports/components/toolbar.brief.txt": "sha256-VPYniux9uZAkC+FpBa9mUSIWWyiRrjVotlImdYutF90=", - "exports/components/toolbar.json": "sha256-Qg6UH+C0B9R4jOBl1rmkgPvEiDvUlT3A/wKGVT2XgZM=", - "exports/components/tooltip.brief.txt": "sha256-esSGty5mPswuvR10ztOQG4Gma2XNDMRzzVyGd/cuHvE=", - "exports/components/tooltip.json": "sha256-imfWbgUObvGd82f5lAzHDkjiG7mAqvrJYbZQ8vEISkU=", - "exports/components/tree.brief.txt": "sha256-//WnJZwesy0801qRtjZN5SK7sHOoU7BZ5hJ53/PRvqE=", - "exports/components/tree.json": "sha256-CiayPirCLB4h2A0r+OGyq06JJ6ZVylcVctATkD2K5gg=", - "exports/components/wizard.brief.txt": "sha256-wNlOCnQdn3+kzh4Fu67RdSOFpkqC23SRCSdVuMDaRu0=", - "exports/components/wizard.json": "sha256-pLB+Xs9mSPIhdnsLvv4MEbI4ATie7GjnBP6nAhCf8N4=", + "exports/components/admin-form.brief.txt": "sha256-NAAwvQu4a8OjZrJys+KOZEgYU00bKuc1Fapl7IqW4mM=", + "exports/components/admin-form.json": "sha256-cMCzZ7Y6R5vDQhUKroYjVSLFkJHU3Gli08YeWYYWjMc=", + "exports/components/alert.brief.txt": "sha256-eQwb0CZfTNRQaaQFDNKn3G49wlkgo26nvHx8KmyZgk0=", + "exports/components/alert.json": "sha256-SDyyVlrQ4zCsh1k9d6euBFC5H1XTIXNlwApLZ28huDs=", + "exports/components/avatar.brief.txt": "sha256-yb2E1WYCMFgBlOcQbvmepU3c5w6mhHwH+8xdPbmAffw=", + "exports/components/avatar.json": "sha256-hUNV+6XmlXrHWL6Tic/4F2BgAkQDiplqsBttX7wyBVo=", + "exports/components/badge.brief.txt": "sha256-zTAyOHPX25UjjwGpRZsVWiSmS6faViq2VfnAzbsdobM=", + "exports/components/badge.json": "sha256-J6LygawZXw+gAxgIfKKMtKinZWxdT4fQ7JbeHvOxI7Q=", + "exports/components/breadcrumbs.brief.txt": "sha256-OuXoanuYkjAwlqhnU6De8YxF335ZGg6c/8IxknSz9ss=", + "exports/components/breadcrumbs.json": "sha256-ZEltkBqhykUx1c98sp1AnzBLBOL38xfDyJvOTwm4Sh4=", + "exports/components/button-group.brief.txt": "sha256-CtMpbJZqC4+Bm8c7w5v6zNOkGV8nvpNRSVVkFdwWPf4=", + "exports/components/button-group.json": "sha256-Sq8vsc8jJEpMDIaHTq3UMiJ7LDvSiv5vmDoAuxQX7Wk=", + "exports/components/button.brief.txt": "sha256-X1uJkp22e9mSRPJEfasvID82Ad8Z0C3bErTrPO05CVU=", + "exports/components/button.json": "sha256-ZlEnd0u5yLcxzB1C8tOCxvA8w2H5K9kB6SkPgTufJuk=", + "exports/components/card.brief.txt": "sha256-I0soQzxkKl2Nixtd3Kt2pBtF8VNuVUTHGU5vqK5DfiY=", + "exports/components/card.json": "sha256-sjtZLyhgdgrEFnSySdcpLFbLyZkWKnIa1jsxlIVK71o=", + "exports/components/chart.brief.txt": "sha256-+kw0iLzQaOGGpsuLFKvCRCWOn1lIu6moXm/OT6Oplc4=", + "exports/components/chart.json": "sha256-BasdUdA3MzGo0Rmmrmj+E6bMOtudFa8Xxcdb51Nizp0=", + "exports/components/checkbox.brief.txt": "sha256-pLrJ+lzBro8KDitL8XF5XdRQuWy5oGNHrADg6NUwO98=", + "exports/components/checkbox.json": "sha256-lTwSQVmvHYgltg/LQk97oB/0JbAKuE3b4vjU8EE/mHk=", + "exports/components/chip.brief.txt": "sha256-heS1/C2lQhgqsukPT8EXAGRYFH62hv1OBRZPpMtgbEY=", + "exports/components/chip.json": "sha256-BfTPtwtzIh8BFij9jAuBYFOI1OOsIa/QqxGxoSvruBQ=", + "exports/components/code-editor.brief.txt": "sha256-0JevPIfQ08Byu1c5tM6j3Z7N4v4IBKELg697r3/fR6g=", + "exports/components/code-editor.json": "sha256-9LKz74FqUL7zWtnvvJ/AAzTZkLqpiZk6fmDkxJGzlgg=", + "exports/components/combobox.brief.txt": "sha256-Djz6nfunQW/lHucE3M1DGnpxcYNGhGltjM4l9wwnVKs=", + "exports/components/combobox.json": "sha256-slabxERChhxzMG1On6USB3ilVP2/GZ86qPGxrKtyd/I=", + "exports/components/command-palette.brief.txt": "sha256-P4i1HqelXuwSWLo+fJFbRaPbfULuvq3Z0xI6E1EdLjE=", + "exports/components/command-palette.json": "sha256-kjl20b57OaZaKaOyQYMLeCMiiJtqygpnPayE03RaF9E=", + "exports/components/compact-dashboard.brief.txt": "sha256-AzIJ/y+V4p4pK2jfVVJ5z4SDyPXpkwKTio2tyV36aKo=", + "exports/components/compact-dashboard.json": "sha256-mdvkqeJBaUpbi1OZalkU9nibADqwIXoBlEn7k1c9QK4=", + "exports/components/data-table.brief.txt": "sha256-FzuDtGOqf2PNIP4FAnQ2jtPo3JPZyQI5SHac3M2sI/o=", + "exports/components/data-table.json": "sha256-GtiL/MsfUQrKkEhOX2LBO39gDmHItEupAGUcxO9S7so=", + "exports/components/date-picker.brief.txt": "sha256-xV4lktbb0ewFh7lcEyjGeFoCCBez1VRg12YLrJd5lCg=", + "exports/components/date-picker.json": "sha256-I7/+SFQ5Etf2XhC1KC2zKnJoBuuUfQ+XBwSvzIIM9G4=", + "exports/components/description-list.brief.txt": "sha256-Fdhf8PR6Bbz9jLC8qNyZOFk3MdlA0GLnx8JHKuYqFtM=", + "exports/components/description-list.json": "sha256-TcAgWaXIqrh7GnyY4Fh1sxw18w3Z64obPXXecZjM9PA=", + "exports/components/diagnostics.brief.txt": "sha256-KZtrkyZnan2krY54/TJ3AFhBubQxOnYXMXOtQl1wkBU=", + "exports/components/diagnostics.json": "sha256-XEiEML9kKK1Sx0WE7ntiSRf1x/LsJV0WRD7Ld7KIRBI=", + "exports/components/dialog.brief.txt": "sha256-wZOaSsoMO/4ixbHN5K6nyF+qsoBIBjaX4bE5SUwM2c0=", + "exports/components/dialog.json": "sha256-iW1JIM20K7jbEJPsZT44sXsMWUbFYnoH8MKe+xSwKno=", + "exports/components/diff-view.brief.txt": "sha256-z5YKZZODTo+ZyUSOswS4nVk0oWh8Z7/3MrOXnYSsbUw=", + "exports/components/diff-view.json": "sha256-UV7sIl990iqjdYQ+70hGI5AnnZVgdnk2glZ2TGeMBh0=", + "exports/components/disclosure.brief.txt": "sha256-mKqWXDpZ62MPZq6jbXXtxuHOLyMiv3HAlDT/4U/l0E8=", + "exports/components/disclosure.json": "sha256-9XecJvyNgfoZEOW2s0oYxV0wASigN5AcdFQ5jSvLFl8=", + "exports/components/drawer.brief.txt": "sha256-DmoQYGx/ld4LQpTZ2oIJcp+iVwiJW/89AfH2tWRlwvQ=", + "exports/components/drawer.json": "sha256-UWZZjgftkOkdmmGie3aC6ygvdyubUx31slprKBMVXco=", + "exports/components/editor-search.brief.txt": "sha256-yrbH7rHPERVh+hwA304lqHZAUGDeQwDCUI2W4LZW5gM=", + "exports/components/editor-search.json": "sha256-9OA9zuYcg6E9odzsrjVymAg0bXpA/YrgHDPTF+ZX3fc=", + "exports/components/empty-state.brief.txt": "sha256-9lyNLRfUjcu65/vMMretZMciCRyZzq57dv4BSXlxd5A=", + "exports/components/empty-state.json": "sha256-9jQ+/tMzpDMWDn1FdHFsY5MvGelrQ7ChHrdJgDpPO2Y=", + "exports/components/error-state.brief.txt": "sha256-0peAl3UrEEaj5KcKcjHT3fnZ9qozHdJ2aUgpFj1A728=", + "exports/components/error-state.json": "sha256-vgS8frriX3mDe18TFJsu8qMJ5vGa8pSmryajo5TX8Z0=", + "exports/components/field.brief.txt": "sha256-RdC7dRp8BPZiQ8qQJlPC69gHGgmgB/kEeKy6c8zCmWI=", + "exports/components/field.json": "sha256-/mkJI+8jB6gTFIo3KiYT8xkFsr/YATG/S6dC68UXBL8=", + "exports/components/fieldset.brief.txt": "sha256-kUm5y+ZV2VUb0iW9ciZwBCOMRIs5gF0TMLF2SA2951Y=", + "exports/components/fieldset.json": "sha256-UwVGiS3NbUzuJsIir7uaYz0WnWsR6xBT7/qEBYIX8RI=", + "exports/components/file-browser.brief.txt": "sha256-f5cEc7dJEWxh+5Ekp+sCBL6myZTtmpF5tN9c4ClQdK4=", + "exports/components/file-browser.json": "sha256-5Zla/4ImfqmxvuIKDJDxEQodvH9GaqSc25g7SMLGyMs=", + "exports/components/file-input.brief.txt": "sha256-WJOZu5jgt5O42n6EfQ1pvYgO6queoeEe/85EjED/m/M=", + "exports/components/file-input.json": "sha256-2BPV00mPYWRZwpGSypAWLwmyzqBlF5/h2S4H5pq/2Qc=", + "exports/components/filterable-table.brief.txt": "sha256-UftlMM3WBBZZz+JieQuFR6ssvsZg6/+Zn+FRSSxatFM=", + "exports/components/filterable-table.json": "sha256-t59LtzesMFhdRKldod6ybMMKusCmRLNz4lbCOopPYrg=", + "exports/components/form-builder.brief.txt": "sha256-3tIVMSkQRa81Tj+YbXmv6bj02jjBPR+4A17NAv2EmO8=", + "exports/components/form-builder.json": "sha256-4mIniVSwqBN9xrQw+5U3yNtrlk/aRH8jZPKuY0aIcFo=", + "exports/components/i3-window-frame.brief.txt": "sha256-kDv+CEtJRryjxTwv1PnG48Cv8+gRciQc/tEfZpxam8E=", + "exports/components/i3-window-frame.json": "sha256-HE2yLQP/EeCfukaO9TmrjuntEfxBg45zTLfMTv8dV+w=", + "exports/components/icon-button.brief.txt": "sha256-o07kxhxYhgUsOhGfFHRoF+6W4kJMBNERyPe7lxSyIrc=", + "exports/components/icon-button.json": "sha256-sNwIKljbVPU+JhJSwXGW7HAJqD+603MQomnt9DXiGfg=", + "exports/components/kbd.brief.txt": "sha256-5Lm4w94KsxpfKR47Iv1/sAfRWFO5WGsdFgOwsa2vurE=", + "exports/components/kbd.json": "sha256-qtJdAYhDBzZPtmFspChfruWyiMDL9twSz9dLREQCMQw=", + "exports/components/link.brief.txt": "sha256-FE6d6A4591c35YAVb7659bY2GzDnq3M4DlhzXGH44Nw=", + "exports/components/link.json": "sha256-Ve/sgeCPW8kcWLJQRARNL0CZ6+8QnNZ3pfX5Yy2tjSA=", + "exports/components/list.brief.txt": "sha256-FPhPO7+5z5fR0JzqgVGz3iR8t3dm4IEnFiLv2ZZnrdE=", + "exports/components/list.json": "sha256-ayifS2PLlnD94AVUVt5LUutQj2M8RmG/kLVPtqTuAkY=", + "exports/components/loading-indicator.brief.txt": "sha256-vW2mZkV2Ms3YrQTdCW/OmMHnEnGZz0xnJVh7rnGXKow=", + "exports/components/loading-indicator.json": "sha256-shFLUs9MXfCP4POg3WBzqxyPjk47+79iE82UK5M1V6M=", + "exports/components/menu.brief.txt": "sha256-JnUcFs0FyTXUQe1vIy335Sm6uxRNkoW1OwY82LZsAe8=", + "exports/components/menu.json": "sha256-vxb+FTeoH6TkYXfE0DDg7xcAntQBy94waPLnLqUiB4Y=", + "exports/components/multiselect.brief.txt": "sha256-ttvBKdDsZT/jfCBRe1aqq6/r2pNdDG4PjSu2AFdEouM=", + "exports/components/multiselect.json": "sha256-UiDVzUHMqLI+ruP4XdGhBuhdbP+5baB4PPlvNWBrlw4=", + "exports/components/number-field.brief.txt": "sha256-1UHv+wezTtDaru3yAfHFU4NNUiwwrB0P1YjUbcmiB7U=", + "exports/components/number-field.json": "sha256-CYDT5nidQgoqOlXEDX8P4MMWaVY5gtgr0XoeBFYIFLY=", + "exports/components/pagination.brief.txt": "sha256-HS3XYgnqdUZRhJS3pV+/ONBPPKk/PP3UxB27JeKAC/M=", + "exports/components/pagination.json": "sha256-vFyBtSE4gjXCH2sQZbtvZNAlK2UZRRoX7ogz76srgG4=", + "exports/components/popover.brief.txt": "sha256-MX27nm2zjgLET/8TJVEsmg8L5ZCXcNjlhtHf5tjWORA=", + "exports/components/popover.json": "sha256-mTckWzUiz2rRahydiFa/ONiXepSRsdEbdYRvaJ92k54=", + "exports/components/progress.brief.txt": "sha256-3UWVDj7fnZU6Kg/Loq65nxUOeZ8Ic6EUIsxqSyUx/tI=", + "exports/components/progress.json": "sha256-DQMvp+PkVdptaRd9LjZ19GAiQVgMa0awWfpqeGfMV0o=", + "exports/components/radio-group.brief.txt": "sha256-SYwy36nlfY793FyEc+WJAiElXQ90F3uAzt9MZXkSW1w=", + "exports/components/radio-group.json": "sha256-Ybo2AlA1UgFQjRgOGq07P5lxGTsO4dP+D8wFo3c3qOU=", + "exports/components/range.brief.txt": "sha256-sgmKsutNV3KGyxLykARDuCuKvvKuETnV2nZEA4/x7jc=", + "exports/components/range.json": "sha256-WIF2ZWvwloqTUB+95IHl9aTeKIuaSxFCo/GK3oKxqPo=", + "exports/components/repeater.brief.txt": "sha256-jcLf1GCz7BjgJA+6Y4smUA6uMNLm1mn0Xx1ZdGLndrw=", + "exports/components/repeater.json": "sha256-YW1BZL3NCKzxpyHd/oX4fmkbNzwZIeDh5ImXEZuTlo4=", + "exports/components/search-field.brief.txt": "sha256-5l9Z7TJQTtMS/SNzhI7ccsyqrVJzduADbU/+8cml0sE=", + "exports/components/search-field.json": "sha256-gOrIeIfgFkPVcFjUBIrmT69tTA0ucPhyFpv9/9NLFNY=", + "exports/components/segmented-control.brief.txt": "sha256-3Ezt2/z1kXR8Ymb9XrNx41pCanGPnmpgSIj2DMOgLfY=", + "exports/components/segmented-control.json": "sha256-L4OU1sHlD4fDrmyShueCt1NH9/xM2b71QmPjDetz7Ys=", + "exports/components/select.brief.txt": "sha256-JvqyEwXcadpAK0nKrODCcE4Bfi8iOZzRbn4yzitdxH8=", + "exports/components/select.json": "sha256-yL+LqAY+oEKvdS7BUSSuv0a/z1RpMCc9DH2QhdgJ2JA=", + "exports/components/settings-panel.brief.txt": "sha256-u/BbvlwJJSZQEh7Scpv6qBahcFBzsvyamRL2VOH+CU8=", + "exports/components/settings-panel.json": "sha256-tZqQ8ue4o/6aX+gIHuAw7U7+KfnO1KR+5b/KbqzidzQ=", + "exports/components/sidebar-nav.brief.txt": "sha256-gU1i20+fje2trojd9s/WFrSibLgh/FlJjW+qAwabC+A=", + "exports/components/sidebar-nav.json": "sha256-9M/9axST95VbeHYLN2FsITzn819QUURTBFzeFZ7w3eU=", + "exports/components/skeleton.brief.txt": "sha256-c4VRPqzIplCsFjwHJfHWUkPGOpsRFqZvOimogc4c73s=", + "exports/components/skeleton.json": "sha256-nM5bEtPXQluMleeSjUbHKRiLicp4xKgCshJTmeAE2TQ=", + "exports/components/skip-link.brief.txt": "sha256-ZAdAxqgDih7VyyLLxyZhmVQEfBzbV5sPUMO4E7tXe3I=", + "exports/components/skip-link.json": "sha256-wfbZNR4N5PUEmEQQ7ustM2ZZkw4F4OOgo2uylcTpQA0=", + "exports/components/switch.brief.txt": "sha256-vsKXPfBVqmo9e9x7NLSCUzNO0JlG4ax4zmXgfuM2+MA=", + "exports/components/switch.json": "sha256-+qLnIwiesw3n677GRmUYDQnLQyF7caiVcrQ43qWDqco=", + "exports/components/table.brief.txt": "sha256-JxG4wxtVl+ZA9AI90sTY4Ss9sX8yD1RCOeJoBDnXOI4=", + "exports/components/table.json": "sha256-Y/Q057zrmXpCMHe71Dk+XFeRwLNu0QkE+JJQMgvVwqs=", + "exports/components/tabs.brief.txt": "sha256-qkuyQOiim867uAODSkHU9y6Ni0ljKESlZnJUfZ5EMoo=", + "exports/components/tabs.json": "sha256-4uEKjf6Pcl6epXayzGG7Rb6szfuzs1JaRdBHjSWx28U=", + "exports/components/terminal.brief.txt": "sha256-hW1OOu6uEZ7hs7p94UMI/YMsQxSDZhLOb9L/3wLCLqs=", + "exports/components/terminal.json": "sha256-tmO1tF2j9qKaUBaCWKbLDbwc6RvjOeH/0QsD0HBHuyg=", + "exports/components/text-field.brief.txt": "sha256-GvPsSJHyRwsCbsoEK8FsX3tppSclBhJOFZVzP2sXQPM=", + "exports/components/text-field.json": "sha256-VP6pzK4iEpJYP1z956Hy0l1cuQwtWdF13P3pTkc7hcA=", + "exports/components/textarea.brief.txt": "sha256-bIsyJdMRbA1M2dtJ5FuYPSwZRDoKgIU8/hmr57tLfA8=", + "exports/components/textarea.json": "sha256-soblNoXVqwwH4841ku6gvoWpKHO9aZpUgbKZEdG0UcQ=", + "exports/components/time-picker.brief.txt": "sha256-4qP0ypJVbUPzaw6mrmW8A7FmngUAUuSD/6EenCEtfCY=", + "exports/components/time-picker.json": "sha256-aN3mUcCZMpc0H3B6cGSep2AEEUblbSurbtYZ+4c3voQ=", + "exports/components/timeline.brief.txt": "sha256-YbCNxIhNLizNi9SOPEw/6HvkWPawmiO1/vPLHWuIrFE=", + "exports/components/timeline.json": "sha256-Lrmu0cnFU8OjQU20yskQ+wUPDZIeKHNyt1QL57Hpq8o=", + "exports/components/toast.brief.txt": "sha256-/9Taj+JdvkvseZ44DHzzhmHan6/PBf10nmjSGiJLoyw=", + "exports/components/toast.json": "sha256-kEViFGDQbl6zuTVQWQAkR9uhmJChDetGK+VHu7R7/R4=", + "exports/components/toolbar.brief.txt": "sha256-FfqBUcrrYUYn/XD7rWQIET5om5HoDvKFuMMeg7qlG4Y=", + "exports/components/toolbar.json": "sha256-HR1PNVg/kEeT2sPQLICqlHh2Jpwgmjz2ISDyKNbOnfA=", + "exports/components/tooltip.brief.txt": "sha256-dyNwGTmWnZ/hhUIqb62CnzkylWFOGZp3JA+lzzs4Y2U=", + "exports/components/tooltip.json": "sha256-W6/wWbuwFVhv7bacwRrT7HpcYnZIO0lq7M4l6wET6/4=", + "exports/components/tree.brief.txt": "sha256-D7ZcIgsMm8R2iOjfe3GB+bRj5A35WljbutcciE8Pkm4=", + "exports/components/tree.json": "sha256-oUHCGdl1TrWMb2+5kqpcUru1cUe4isv3d+K5i8m9GBo=", + "exports/components/wizard.brief.txt": "sha256-gRybOypZwtIhzkE9KVcez6ROtQ5/lUJsWaTwPOIikaQ=", + "exports/components/wizard.json": "sha256-gm/Ax9KeTuUiV1krYNzcz6m57jB7lC4lRu3+W+QuZrA=", "exports/contrast.json": "sha256-gmovO9y68psNmmsDElXktOprdI/0LTT6JCo0/bLzCD4=", "exports/contrast.md": "sha256-vSmxTKGCZHxysVYKkQNwoGdqO2prLBJVZjHwnogcY+s=", "exports/coverage.json": "sha256-FeuiH5WV9i3ILuDqqcloRbL6pCMOoA3qZeoMEv1HdDU=", "exports/figma/importer.mjs": "sha256-VXfdSuZ1eYqKIIadm4JI73kT9Or0PTracOyncWAsbnI=", - "exports/forms/identity.json": "sha256-ekAbK96YcmiUX2CTKjroPPKh0RpCXJcduq37KjniCJg=", + "exports/forms/identity.json": "sha256-ReYrFo3DxY3o68oO6n9Hh7gqvZSNze0W7U1mZ7g43ZA=", "exports/forms/templates.json": "sha256-k2e6tcvD0k6hUCU+l+1itDIeEGjAzxvq8bCmewl8XRg=", "exports/llms.txt": "sha256-Bzchjr9xc74FBFmz0hwbl9kjJBWCV/L8ZL/q+NvFOm8=", - "exports/patterns/validation-recovery.json": "sha256-g2g8DBXXPzt8ZbhXmahQay69CDqruxx2m6Mdvga5+UM=", - "exports/port-capabilities.json": "sha256-c4HHGplL/Vh7JJD8MZONBbTRbEpYe+mYNVPsVbFoRRE=", + "exports/patterns/validation-recovery.json": "sha256-hEfzGewdNViHMChlN5b8EXUCao68upU06VxJlR3Dp1w=", + "exports/port-capabilities.json": "sha256-6u3M0mXA+lN5FLjtOJvRkLpcFNePSv8ZUMpIiVohxVQ=", "exports/recipes/button/LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "exports/recipes/button/README.md": "sha256-XMR0WkxC2OZc4k7b4YbzLPO7V+3sqncs+Gp6VrWN/iA=", + "exports/recipes/button/README.md": "sha256-mS8bIWiTXGBfI7igIXsai6GF4p7KlPCfsQvAEFb9fls=", "exports/recipes/button/component.css": "sha256-+Fn90PbGbnW0JxDH1RAdiYrVQ4FrstMA+Rq7HlAQTdU=", "exports/recipes/button/example.html": "sha256-HRSLwap8t93ggusQ8BYoEAE0wPCsBWTKSY+4JGzRNa4=", "exports/recipes/button/foundation.css": "sha256-gItmMJgxTkuTe8+9G3aZQviwGcJ5cQaNANEvpcyOA88=", - "exports/recipes/button/manifest.json": "sha256-GJJVcMHg7JCNv2EwQYzyH8HvblxYINZy4R644vtPIwo=", + "exports/recipes/button/manifest.json": "sha256-AA++frM2He0KhcMDOlEUKBy7S82fbjAvkWU7QAA69uc=", "exports/recipes/button/markup.html": "sha256-9HjLJ98lH4SKiwVWynQKarCqWTK/+IKfcvGr6464P3c=", "exports/recipes/button/template.html": "sha256-FfylFZ+qzMUFxQKnIdqJiYmC8p4F+cNxK8BJSTo8XU8=", "exports/recipes/button/tokens.css": "sha256-a/TLRGPaqlzicffxz3q5+tWHlvaJ9h78GE1mHVxzp/s=", "exports/recipes/button/two-instances.html": "sha256-SUuvR3ZxzWymDnwkF8BdP321ok8G/grt3ePxGLLUBS4=", "exports/recipes/dialog/LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "exports/recipes/dialog/README.md": "sha256-AL07d5Th8y7YXkw0pqRE3C5OtnLoJoPkd0TrkVBXVd0=", + "exports/recipes/dialog/README.md": "sha256-JtVWLmJ6VdsYRA9228KVpvrqV8PdIsYeyo8w2Vm0DOM=", "exports/recipes/dialog/component.css": "sha256-Q2j1S57IHrXP3j0VijKinSjdfBgbr6nkFZHrFbkmNaI=", "exports/recipes/dialog/example.html": "sha256-4W9jw4/GPrhd2VhxlZXF91t2yanib4VIWbJ18XomB0I=", "exports/recipes/dialog/foundation.css": "sha256-gItmMJgxTkuTe8+9G3aZQviwGcJ5cQaNANEvpcyOA88=", - "exports/recipes/dialog/manifest.json": "sha256-0OWeXDl1F2+hy0Go/RDdcxHVzikxDc44qksLw/QgUh0=", + "exports/recipes/dialog/manifest.json": "sha256-ICAb4/dJetXL173dvIYPXJ3XTZbrK5s0tRW/Ky5hH7Q=", "exports/recipes/dialog/markup.html": "sha256-o9WIUCRlY5GUbx8+IYfcIv9JJlXBbiJBjb7jUkjNTHE=", "exports/recipes/dialog/template.html": "sha256-ekYfQWlHu6z/dh7Wi1W3GZayMjEjxB5ru5nU7CKIqMg=", "exports/recipes/dialog/tokens.css": "sha256-H4mpfW2luSqCo9S9PPrDgpevuK2OSiXDpp7+a+dFeFw=", "exports/recipes/dialog/two-instances.html": "sha256-KqTTacdBcUnD+k4PYaBYhC74nsIJ1Twu1IOaDjQdoFI=", - "exports/recipes/index.json": "sha256-p/IWOQ+hZb2Yz3LE0RibtkwkPx2P5NR4elcQqRIkXzg=", + "exports/recipes/index.json": "sha256-qU6LheE0yEJ9e3I8OIEt21BR16XPsgxCmpzLoasScjk=", "exports/recipes/text-field/LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "exports/recipes/text-field/README.md": "sha256-4IdgTG0RNA0xp3IIcosxkwvq7KQdLS2Wiw1TuWxlzas=", + "exports/recipes/text-field/README.md": "sha256-IBA7Qgs31PqUxOZM9Pvcdfrq6E0ccMpSHeNnSTvZ1y4=", "exports/recipes/text-field/component.css": "sha256-VgGNE3+NVtPUYTJf02aIPHq3JrH5EGckSbwQealUEwU=", "exports/recipes/text-field/example.html": "sha256-OT8OHppA6ssLf5OlKXOIqPBdkCDLa9lXaqsUOtT1SyQ=", "exports/recipes/text-field/foundation.css": "sha256-gItmMJgxTkuTe8+9G3aZQviwGcJ5cQaNANEvpcyOA88=", - "exports/recipes/text-field/manifest.json": "sha256-ObZff1cu6gngs5yKnxm7yLN6N816nHa1rrKJYbiHygs=", + "exports/recipes/text-field/manifest.json": "sha256-hG79YUgUPrJHUwebcbJWobszHhgVqfqG1XOBASdFG6Q=", "exports/recipes/text-field/markup.html": "sha256-O4CmIRb2RUPigpgQAcre9bSpIRJxN52MMxJW4fTyhpM=", "exports/recipes/text-field/template.html": "sha256-IlSlLS7sPC3MLqIdxMRQUP4sFnn/58lwM3AFALtdY3c=", "exports/recipes/text-field/tokens.css": "sha256-EqSdsrQqs1NJVLFBDmxFtT0mbcjOiUeAx1G9cTcdpIY=", "exports/recipes/text-field/two-instances.html": "sha256-Abep8m5/si0kuUu3cVGEVzcHqMN1pHkPazmjloND8J0=", - "exports/task-inputs.json": "sha256-fM34VhKdEfU6nCu29ZMwBdovMDMPOVKEQyub/czMMZY=", - "exports/theme.compact.md": "sha256-scHwaXnCWxW392O05sqziYlTLymSaro4g5hSNijAwoo=", - "exports/theme.full.md": "sha256-ZhUQth0gL7M8hymt4ptTqyzWa9qYtCJaoTNp6PAntUU=", - "exports/token-usage.json": "sha256-H96Z5c44DtcP5MzkPiReXm1oXLTe31w6fu20W6dFqHc=", - "exports/tokens.css": "sha256-jcet9sSAiqrRJ5JZAAPP3LQgonPGl51F58SI869KAAg=", - "exports/tokens.resolved.json": "sha256-zFvYCG+sRacSRpLqVjVsMUNxxfakWzjnJrCN7WOgQYY=" + "exports/task-inputs.json": "sha256-MBZr389Gyb8TZfN67iZgvZVQdPziFp2Y252NgbhaLoI=", + "exports/theme.compact.md": "sha256-jrEVDKhdwd24OJBek75+xuGzGoxkykr4U1pjkI5sadQ=", + "exports/theme.full.md": "sha256-vPkn4TtelDvQpwKcvJYx0ROwyHh2QwvuuFvL6Tn7+xI=", + "exports/token-usage.json": "sha256-a1rYc+D6as/OKhMIp1zkGNWMvTXGSuwI6SbU1VNTcKA=", + "exports/tokens.css": "sha256-ePraUzvnHrCsJIZ1frkOqaHPFHo7iT+aE6wrL4ian68=", + "exports/tokens.resolved.json": "sha256-3KBrfmIiz4L6Qyqvi99TdTe4+5NeuA0ZWZe3Am4sRo4=" } } diff --git a/exports/forms/identity.json b/exports/forms/identity.json index 6a81a0aaa..15a4b4214 100644 --- a/exports/forms/identity.json +++ b/exports/forms/identity.json @@ -2,5 +2,5 @@ "name": "j3w1-theme", "version": "4.0.0", "profile": "default", - "sourceDigest": "sha256-0pGYzXZFMWkGlbzNIlyxfInXr3Pog+Q6PuQTyO1Rbu0=" + "sourceDigest": "sha256-KNf9QNXsLy6MzEixJdv+LTT8TglJJgE7H0JwMdzpjfA=" } diff --git a/exports/patterns/validation-recovery.json b/exports/patterns/validation-recovery.json index 82a71c612..994ca572e 100644 --- a/exports/patterns/validation-recovery.json +++ b/exports/patterns/validation-recovery.json @@ -152,17 +152,17 @@ "name": "j3w1-theme", "version": "4.0.0", "profile": "default", - "sourceDigest": "sha256-0pGYzXZFMWkGlbzNIlyxfInXr3Pog+Q6PuQTyO1Rbu0=" + "sourceDigest": "sha256-KNf9QNXsLy6MzEixJdv+LTT8TglJJgE7H0JwMdzpjfA=" }, "componentDigests": { - "admin-form": "sha256-eRnLywYWpnSnpPiv4MrY0aGZ7BpZEkrJG13tpAxopto=", - "alert": "sha256-fY305BXYtrgqi7ICbnawYPMKZC9ff3t3yJ4I2vRbBZU=", - "button": "sha256-4p1xTZHKv9gloF1QMtXjx9iP2eX9r9MiKd820lW31eA=", - "checkbox": "sha256-vKh60jFbH2dStEUVLlAcQGeDkBvWNoY+xASXA2PBvD8=", - "radio-group": "sha256-EfvnwOBwd3pdtmPY0Islp1+TgVzZNhfl2aMwwy/ct0k=", - "select": "sha256-lxY8viVzwv7lZNWQb25Q710kRbpjsvAiJOCyNsswl/A=", - "table": "sha256-SuXNBFtY8Ta7SYiGP++3vK2F1R5qMDhCqm9MsNridnE=", - "text-field": "sha256-Lex9v1t/4/YXIFJqbJxCwK/4nVl7XPA9D+FEjx0Rn6M=", - "textarea": "sha256-qV1f7XUpYBKJjKIEnduDtBzG6e0UNZC/YT0VDcNdnCQ=" + "admin-form": "sha256-cMCzZ7Y6R5vDQhUKroYjVSLFkJHU3Gli08YeWYYWjMc=", + "alert": "sha256-SDyyVlrQ4zCsh1k9d6euBFC5H1XTIXNlwApLZ28huDs=", + "button": "sha256-ZlEnd0u5yLcxzB1C8tOCxvA8w2H5K9kB6SkPgTufJuk=", + "checkbox": "sha256-lTwSQVmvHYgltg/LQk97oB/0JbAKuE3b4vjU8EE/mHk=", + "radio-group": "sha256-Ybo2AlA1UgFQjRgOGq07P5lxGTsO4dP+D8wFo3c3qOU=", + "select": "sha256-yL+LqAY+oEKvdS7BUSSuv0a/z1RpMCc9DH2QhdgJ2JA=", + "table": "sha256-Y/Q057zrmXpCMHe71Dk+XFeRwLNu0QkE+JJQMgvVwqs=", + "text-field": "sha256-VP6pzK4iEpJYP1z956Hy0l1cuQwtWdF13P3pTkc7hcA=", + "textarea": "sha256-soblNoXVqwwH4841ku6gvoWpKHO9aZpUgbKZEdG0UcQ=" } } diff --git a/exports/port-capabilities.json b/exports/port-capabilities.json index 7ebe285f2..275382e58 100644 --- a/exports/port-capabilities.json +++ b/exports/port-capabilities.json @@ -25,7 +25,7 @@ "status": "not verified", "reason": "No recorded real-import protocol bound to this subject." }, - "subjectDigest": "sha256-v22QcxyCUElYae+NTFBE+DC8YOEVx3edOqcEVHymyKU=", + "subjectDigest": "sha256-kheKD6nkxlfUj8YKsleZfeKY1evO477X2W0sQYEX4cE=", "evidencePath": null, "surfaces": { "appearance-settings": { @@ -382,21 +382,25 @@ {"role":"font.letter-spacing.terminal","nativeKeys":[],"value":"-0.5px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.caption","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.code","nativeKeys":[],"value":"19px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, + {"role":"font.line-height.display","nativeKeys":[],"value":"40px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h1","nativeKeys":[],"value":"28px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h2","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h3","nativeKeys":[],"value":"18px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.reading","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.terminal","nativeKeys":[],"value":"19px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, + {"role":"font.line-height.title","nativeKeys":[],"value":"32px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-lg","nativeKeys":[],"value":"20px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-md","nativeKeys":[],"value":"18px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-sm","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.caption","nativeKeys":[],"value":"11px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT has only a UI size and a code size.","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.code","nativeKeys":["Code font size"],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"mapped","surface":"appearance-settings","reason":"Set by Code font size.","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, + {"role":"font.size.display","nativeKeys":[],"value":"32px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT has only a UI size and a code size.","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h1","nativeKeys":[],"value":"20px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT has only a UI size and a code size.","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h2","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT has only a UI size and a code size.","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h3","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT has only a UI size and a code size.","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.reading","nativeKeys":["UI font size"],"value":"15px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"mapped","surface":"appearance-settings","reason":"Set by UI font size.","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.terminal","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT has only a UI size and a code size.","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, + {"role":"font.size.title","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT has only a UI size and a code size.","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-lg","nativeKeys":[],"value":"14px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT has only a UI size and a code size.","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-md","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT has only a UI size and a code size.","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-sm","nativeKeys":[],"value":"12px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"typography","reason":"ChatGPT has only a UI size and a code size.","source":"ports/chatgpt/mapping.json","spec":"spec/portability.md"}, @@ -457,7 +461,7 @@ "status": "not verified", "reason": "No recorded real-import protocol bound to this subject." }, - "subjectDigest": "sha256-me1Sj2tF/8GsHCFBcPzf6IBwNwe/KxVPSe8prdVhw1U=", + "subjectDigest": "sha256-hBBwZ2y1JDohKwDhMwOx2PSdMfmKq5QSsuQv9lTPMik=", "evidencePath": null, "surfaces": { "theme-roles": { @@ -790,21 +794,25 @@ {"role":"font.letter-spacing.terminal","nativeKeys":[],"value":"-0.5px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.caption","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.code","nativeKeys":[],"value":"19px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, + {"role":"font.line-height.display","nativeKeys":[],"value":"40px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h1","nativeKeys":[],"value":"28px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h2","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h3","nativeKeys":[],"value":"18px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.reading","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.terminal","nativeKeys":[],"value":"19px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, + {"role":"font.line-height.title","nativeKeys":[],"value":"32px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-lg","nativeKeys":[],"value":"20px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-md","nativeKeys":[],"value":"18px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-sm","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.caption","nativeKeys":[],"value":"11px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.code","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, + {"role":"font.size.display","nativeKeys":[],"value":"32px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h1","nativeKeys":[],"value":"20px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h2","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h3","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.reading","nativeKeys":[],"value":"15px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.terminal","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, + {"role":"font.size.title","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-lg","nativeKeys":[],"value":"14px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-md","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-sm","nativeKeys":[],"value":"12px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-claude","reason":"Not a colour; a Claude Code theme carries colours only.","source":"ports/claude-code/mapping.json","spec":"spec/portability.md"}, @@ -863,7 +871,7 @@ "status": "not verified", "reason": "No recorded real-import protocol bound to this subject." }, - "subjectDigest": "sha256-YNge+khP5DG3f+D1YdaITPhf+uj9JMQ625qekhussp0=", + "subjectDigest": "sha256-j6tozYh8XFb2iLLcQar/k1OmzLzKjKW3ykMZLKOyZBE=", "evidencePath": null, "surfaces": { "theme-scopes": { @@ -1200,21 +1208,25 @@ {"role":"font.letter-spacing.terminal","nativeKeys":[],"value":"-0.5px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.caption","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.code","nativeKeys":[],"value":"19px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, + {"role":"font.line-height.display","nativeKeys":[],"value":"40px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h1","nativeKeys":[],"value":"28px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h2","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h3","nativeKeys":[],"value":"18px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.reading","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.terminal","nativeKeys":[],"value":"19px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, + {"role":"font.line-height.title","nativeKeys":[],"value":"32px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-lg","nativeKeys":[],"value":"20px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-md","nativeKeys":[],"value":"18px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-sm","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.caption","nativeKeys":[],"value":"11px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.code","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, + {"role":"font.size.display","nativeKeys":[],"value":"32px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h1","nativeKeys":[],"value":"20px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h2","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h3","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.reading","nativeKeys":[],"value":"15px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.terminal","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, + {"role":"font.size.title","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-lg","nativeKeys":[],"value":"14px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-md","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-sm","nativeKeys":[],"value":"12px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-codex","reason":"Not a colour; a tmTheme carries colours only.","source":"ports/codex/mapping.json","spec":"spec/portability.md"}, @@ -1272,7 +1284,7 @@ "status": "not verified", "reason": "No recorded real-import protocol bound to this subject." }, - "subjectDigest": "sha256-ap47jQvF7xqmYy30KRPDNIttIx50q29xjNUFgboSLpQ=", + "subjectDigest": "sha256-TCTn2dZNf0NZqAxuMK6Nj7JA+YAXSdCWYUKu1yZqjDc=", "evidencePath": null, "surfaces": { "terminal-colours": { @@ -1609,21 +1621,25 @@ {"role":"font.letter-spacing.terminal","nativeKeys":[],"value":"-0.5px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"terminal-font","reason":"A Ghostty theme carries colours; Ghostty has no letter-spacing key.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.caption","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.code","nativeKeys":[],"value":"19px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, + {"role":"font.line-height.display","nativeKeys":[],"value":"40px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h1","nativeKeys":[],"value":"28px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h2","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h3","nativeKeys":[],"value":"18px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.reading","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.terminal","nativeKeys":[],"value":"19px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"terminal-font","reason":"A Ghostty theme carries colours; adjust-cell-height has no exact conversion from a pixel line height.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, + {"role":"font.line-height.title","nativeKeys":[],"value":"32px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-lg","nativeKeys":[],"value":"20px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-md","nativeKeys":[],"value":"18px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-sm","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.caption","nativeKeys":[],"value":"11px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.code","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, + {"role":"font.size.display","nativeKeys":[],"value":"32px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h1","nativeKeys":[],"value":"20px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h2","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h3","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.reading","nativeKeys":[],"value":"15px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.terminal","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"terminal-font","reason":"A Ghostty theme carries colours; set font-size in your own config.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, + {"role":"font.size.title","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-lg","nativeKeys":[],"value":"14px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-md","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-sm","nativeKeys":[],"value":"12px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/ghostty/mapping.json","spec":"spec/portability.md"}, @@ -1681,7 +1697,7 @@ "status": "not verified", "reason": "No recorded real-import protocol bound to this subject." }, - "subjectDigest": "sha256-4ZXQpvj4FS4DR0McKIi318xtZV8VaSGtYhHbTmqfVYQ=", + "subjectDigest": "sha256-F7CHr7I+0CQeiD0JTmhzz/e+4KP7FdQyEzY1f9JHQek=", "evidencePath": null, "surfaces": { "interface": { @@ -2027,21 +2043,25 @@ {"role":"font.letter-spacing.terminal","nativeKeys":[],"value":"-0.5px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.letter-spacing.terminal: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.caption","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.line-height.caption: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.code","nativeKeys":[],"value":"19px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.line-height.code: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, + {"role":"font.line-height.display","nativeKeys":[],"value":"40px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.line-height.display: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h1","nativeKeys":[],"value":"28px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.line-height.h1: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h2","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.line-height.h2: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h3","nativeKeys":[],"value":"18px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.line-height.h3: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.reading","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.line-height.reading: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.terminal","nativeKeys":[],"value":"19px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.line-height.terminal: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, + {"role":"font.line-height.title","nativeKeys":[],"value":"32px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.line-height.title: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-lg","nativeKeys":[],"value":"20px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.line-height.ui-lg: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-md","nativeKeys":[],"value":"18px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.line-height.ui-md: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-sm","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.line-height.ui-sm: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.caption","nativeKeys":[],"value":"11px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.size.caption: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.code","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.size.code: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, + {"role":"font.size.display","nativeKeys":[],"value":"32px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.size.display: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h1","nativeKeys":[],"value":"20px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.size.h1: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h2","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.size.h2: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h3","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.size.h3: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.reading","nativeKeys":[],"value":"15px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.size.reading: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.terminal","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.size.terminal: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, + {"role":"font.size.title","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.size.title: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-lg","nativeKeys":[],"value":"14px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.size.ui-lg: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-md","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.size.ui-md: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-sm","nativeKeys":[],"value":"12px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"host-behavior","reason":"font.size.ui-sm: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":"ports/obsidian/mapping.json","spec":"spec/portability.md"}, @@ -2100,7 +2120,7 @@ "status": "not verified", "reason": "No recorded real-import protocol bound to this subject." }, - "subjectDigest": "sha256-M3ZJYgCkqX5Kn+P58DljhgG5enfEGNym9GaGlKrSiKI=", + "subjectDigest": "sha256-rctAPIoIjMypEy1NO4BKeWYU6tAnimXv3jC2mpniXl0=", "evidencePath": null, "surfaces": { "terminal-colours": { @@ -2441,21 +2461,25 @@ {"role":"font.letter-spacing.terminal","nativeKeys":[],"value":"-0.5px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"terminal-line-height","reason":"Neither the Ghostty config nor Orca's import has a letter-spacing key.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.caption","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.code","nativeKeys":[],"value":"19px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, + {"role":"font.line-height.display","nativeKeys":[],"value":"40px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h1","nativeKeys":[],"value":"28px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h2","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h3","nativeKeys":[],"value":"18px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.reading","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.terminal","nativeKeys":[],"value":"19px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"terminal-line-height","reason":"Ghostty's adjust-cell-height, which Orca imports, is relative to the font's own cell height; a pixel line height has no exact conversion. Orca keeps its line-height setting.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, + {"role":"font.line-height.title","nativeKeys":[],"value":"32px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-lg","nativeKeys":[],"value":"20px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-md","nativeKeys":[],"value":"18px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-sm","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.caption","nativeKeys":[],"value":"11px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.code","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, + {"role":"font.size.display","nativeKeys":[],"value":"32px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h1","nativeKeys":[],"value":"20px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h2","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h3","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.reading","nativeKeys":[],"value":"15px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.terminal","nativeKeys":["font-size"],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"mapped","surface":"terminal-font","reason":"Written to the file's font-size key.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, + {"role":"font.size.title","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-lg","nativeKeys":[],"value":"14px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-md","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-sm","nativeKeys":[],"value":"12px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/orca/mapping.json","spec":"spec/portability.md"}, @@ -2519,7 +2543,7 @@ "status": "stale", "reason": "Target, mapping, capabilities, tokens or artifact bytes changed since the recorded import." }, - "subjectDigest": "sha256-Sny0kZ99cieROPgFigFuVMnnLwra5tHhg5nnTpyVXwg=", + "subjectDigest": "sha256-WAnQ+aAPviyHorTX3x1WITFGfECNFvTVUT8VAZeKHII=", "evidencePath": "ports/telegram/evidence/2026-10-06-import.json", "surfaces": { "interface": { @@ -2873,21 +2897,25 @@ {"role":"font.letter-spacing.terminal","nativeKeys":[],"value":"-0.5px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.caption","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.code","nativeKeys":[],"value":"19px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, + {"role":"font.line-height.display","nativeKeys":[],"value":"40px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h1","nativeKeys":[],"value":"28px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h2","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h3","nativeKeys":[],"value":"18px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.reading","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.terminal","nativeKeys":[],"value":"19px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, + {"role":"font.line-height.title","nativeKeys":[],"value":"32px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-lg","nativeKeys":[],"value":"20px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-md","nativeKeys":[],"value":"18px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-sm","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.caption","nativeKeys":[],"value":"11px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.code","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, + {"role":"font.size.display","nativeKeys":[],"value":"32px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h1","nativeKeys":[],"value":"20px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h2","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h3","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.reading","nativeKeys":[],"value":"15px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.terminal","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, + {"role":"font.size.title","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-lg","nativeKeys":[],"value":"14px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-md","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-sm","nativeKeys":[],"value":"12px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"typography","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":"ports/telegram/mapping.json","spec":"spec/portability.md"}, @@ -2946,7 +2974,7 @@ "status": "not verified", "reason": "No recorded real-import protocol bound to this subject." }, - "subjectDigest": "sha256-Fb2GBfKclqhemyy4inGUKz7vjJEBggE/vRHPRdl0VY0=", + "subjectDigest": "sha256-CdVbydceUUE55aHMP0tHPV4TC6BE9k4T2bS2kYPJnCk=", "evidencePath": null, "surfaces": { "terminal-colours": { @@ -3283,21 +3311,25 @@ {"role":"font.letter-spacing.terminal","nativeKeys":[],"value":"-0.5px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"terminal-font","reason":"The application's own terminal font setting.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.caption","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.code","nativeKeys":[],"value":"19px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, + {"role":"font.line-height.display","nativeKeys":[],"value":"40px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h1","nativeKeys":[],"value":"28px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h2","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h3","nativeKeys":[],"value":"18px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.reading","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.terminal","nativeKeys":[],"value":"19px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"terminal-font","reason":"The application's own terminal font setting.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, + {"role":"font.line-height.title","nativeKeys":[],"value":"32px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-lg","nativeKeys":[],"value":"20px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-md","nativeKeys":[],"value":"18px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-sm","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.caption","nativeKeys":[],"value":"11px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.code","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, + {"role":"font.size.display","nativeKeys":[],"value":"32px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h1","nativeKeys":[],"value":"20px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h2","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h3","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.reading","nativeKeys":[],"value":"15px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.terminal","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"inherited","surface":"terminal-font","reason":"The application's own terminal font setting.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, + {"role":"font.size.title","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-lg","nativeKeys":[],"value":"14px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-md","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-sm","nativeKeys":[],"value":"12px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"out-of-scope","surface":"outside-terminal","reason":"Not a colour; a terminal theme file carries colours only.","source":"ports/warp/mapping.json","spec":"spec/portability.md"}, @@ -3355,7 +3387,7 @@ "status": "not verified", "reason": "No recorded real-import protocol bound to this subject." }, - "subjectDigest": "sha256-WoqG4J+X/1c2sUKSgPXjnFcYi2QAh8simGJTtu9S6nE=", + "subjectDigest": "sha256-7Q0Q20bvHZ+sUua3sTP40ORR6r38Kre9kbnTryXDFqc=", "evidencePath": null, "surfaces": { "desktop": { @@ -3740,21 +3772,25 @@ {"role":"font.letter-spacing.terminal","nativeKeys":[],"value":"-0.5px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"unsupported","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.caption","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"unsupported","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.code","nativeKeys":["powertoys.markdown.CODE_LINE"],"value":"19px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"mapped","surface":"powertoys","reason":"Token-derived CSS in the exact-admitted PowerToys Markdown rendering boundary; import and visual acceptance are separate.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, + {"role":"font.line-height.display","nativeKeys":[],"value":"40px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"unsupported","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h1","nativeKeys":["powertoys.markdown.H1_LINE"],"value":"28px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"mapped","surface":"powertoys","reason":"Token-derived CSS in the exact-admitted PowerToys Markdown rendering boundary; import and visual acceptance are separate.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h2","nativeKeys":["powertoys.markdown.H2_LINE"],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"mapped","surface":"powertoys","reason":"Token-derived CSS in the exact-admitted PowerToys Markdown rendering boundary; import and visual acceptance are separate.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.h3","nativeKeys":["powertoys.markdown.H3_LINE"],"value":"18px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"mapped","surface":"powertoys","reason":"Token-derived CSS in the exact-admitted PowerToys Markdown rendering boundary; import and visual acceptance are separate.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.reading","nativeKeys":["powertoys.markdown.READING_LINE"],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"mapped","surface":"powertoys","reason":"Token-derived CSS in the exact-admitted PowerToys Markdown rendering boundary; import and visual acceptance are separate.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.terminal","nativeKeys":[],"value":"19px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"unsupported","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, + {"role":"font.line-height.title","nativeKeys":[],"value":"32px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"unsupported","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-lg","nativeKeys":[],"value":"20px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"unsupported","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-md","nativeKeys":[],"value":"18px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"unsupported","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, {"role":"font.line-height.ui-sm","nativeKeys":[],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"unsupported","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.caption","nativeKeys":[],"value":"11px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"unsupported","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.code","nativeKeys":["powertoys.markdown.CODE_SIZE"],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"mapped","surface":"powertoys","reason":"Token-derived CSS in the exact-admitted PowerToys Markdown rendering boundary; import and visual acceptance are separate.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, + {"role":"font.size.display","nativeKeys":[],"value":"32px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"unsupported","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h1","nativeKeys":["powertoys.markdown.H1_SIZE"],"value":"20px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"mapped","surface":"powertoys","reason":"Token-derived CSS in the exact-admitted PowerToys Markdown rendering boundary; import and visual acceptance are separate.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h2","nativeKeys":["powertoys.markdown.H2_SIZE"],"value":"16px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"mapped","surface":"powertoys","reason":"Token-derived CSS in the exact-admitted PowerToys Markdown rendering boundary; import and visual acceptance are separate.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.h3","nativeKeys":["powertoys.markdown.H3_SIZE"],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"mapped","surface":"powertoys","reason":"Token-derived CSS in the exact-admitted PowerToys Markdown rendering boundary; import and visual acceptance are separate.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.reading","nativeKeys":["powertoys.markdown.READING_SIZE"],"value":"15px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"mapped","surface":"powertoys","reason":"Token-derived CSS in the exact-admitted PowerToys Markdown rendering boundary; import and visual acceptance are separate.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.terminal","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"unsupported","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, + {"role":"font.size.title","nativeKeys":[],"value":"24px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"unsupported","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-lg","nativeKeys":[],"value":"14px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"unsupported","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-md","nativeKeys":[],"value":"13px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"unsupported","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, {"role":"font.size.ui-sm","nativeKeys":[],"value":"12px","eligibility":{"action":"use","reason":"Use within the role's documented scope and restrictions.","decisionIds":[]},"state":"unsupported","surface":"unsupported","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":"ports/windows/mapping.json","spec":"spec/portability.md"}, diff --git a/exports/recipes/button/README.md b/exports/recipes/button/README.md index f1e3670fa..b93f3284e 100644 --- a/exports/recipes/button/README.md +++ b/exports/recipes/button/README.md @@ -2,7 +2,7 @@ j3w1 theme 4.0.0. Markup adapted from j3w1 UI Theme Spec, https://github.com/j3w1/theme, CC BY 4.0: https://creativecommons.org/licenses/by/4.0/. Changes: scoped instance IDs and documentation-only content removed. CSS and generator: MIT; see LICENSE.md. -Version 4.0.0; profile default; source digest sha256-tLOvGHSxAnJojvXOq307DdwimfKorzgnNxhuLtFEc6k=. Pin the supplying commit and verify manifest source/file digests; the version alone does not identify a revision. +Version 4.0.0; profile default; source digest sha256-hOIrvGlqp/Z7O1QGYmAJCA5koRmhBBdkctoKbof/hOU=. Pin the supplying commit and verify manifest source/file digests; the version alone does not identify a revision. Open example.html directly, without Astro, network assets or a build step. two-instances.html demonstrates independent IDs. For integration, include tokens.css, foundation.css and component.css in that order, then markup.html. Keep .j3w1-recipe and data-density on the wrapper. The source viewer can make a fresh instance prefix; use a unique prefix for every copy and rewrite all ID references together. diff --git a/exports/recipes/button/manifest.json b/exports/recipes/button/manifest.json index c204372c3..09b2efb9d 100644 --- a/exports/recipes/button/manifest.json +++ b/exports/recipes/button/manifest.json @@ -21,9 +21,9 @@ "LICENSE.md": "sha256-Ih5+DpqcNXGWJX6BbYgpt6psmJi9lGcXGJzuiU7elE0=", "tokens/primitives.tokens.json": "sha256-cmydigBuNgi4hyQLi+3VS5JBhDQ8VMStlmUtPSSc05E=", "tokens/semantic.tokens.json": "sha256-jbrikW294TIEdB7rAiqlLPAiLUy2CMyLT/opZiVe/E0=", - "tokens/foundations.tokens.json": "sha256-/gYmJavPwEyem7mpNRhaBa8jjyuPKnSisugGky3PdCY=" + "tokens/foundations.tokens.json": "sha256-e5OLoStuVryktzLt5O1yFmTb1CR3DcgqccWy5SdB2fw=" }, - "digest": "sha256-tLOvGHSxAnJojvXOq307DdwimfKorzgnNxhuLtFEc6k=", + "digest": "sha256-hOIrvGlqp/Z7O1QGYmAJCA5koRmhBBdkctoKbof/hOU=", "revisionPolicy": "Resolve these paths at the same pinned commit as this manifest. The hosted source viewer identifies its supplying commit; generated source files contain content digests, never a floating revision claim." }, "dependencies": { @@ -394,6 +394,6 @@ "example.html": "sha256-HRSLwap8t93ggusQ8BYoEAE0wPCsBWTKSY+4JGzRNa4=", "two-instances.html": "sha256-SUuvR3ZxzWymDnwkF8BdP321ok8G/grt3ePxGLLUBS4=", "LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "README.md": "sha256-XMR0WkxC2OZc4k7b4YbzLPO7V+3sqncs+Gp6VrWN/iA=" + "README.md": "sha256-mS8bIWiTXGBfI7igIXsai6GF4p7KlPCfsQvAEFb9fls=" } } diff --git a/exports/recipes/dialog/README.md b/exports/recipes/dialog/README.md index 7d94f1550..670b6835e 100644 --- a/exports/recipes/dialog/README.md +++ b/exports/recipes/dialog/README.md @@ -2,7 +2,7 @@ j3w1 theme 4.0.0. Markup adapted from j3w1 UI Theme Spec, https://github.com/j3w1/theme, CC BY 4.0: https://creativecommons.org/licenses/by/4.0/. Changes: scoped instance IDs and documentation-only content removed. CSS and generator: MIT; see LICENSE.md. -Version 4.0.0; profile default; source digest sha256-O/XLRlwd5dEvDccFKU/lnvNi424Qy8nvTrinPm4hgZU=. Pin the supplying commit and verify manifest source/file digests; the version alone does not identify a revision. +Version 4.0.0; profile default; source digest sha256-rGmI15TyvMxO8spWUF+5eZKe7AY/PEAFRjjtWy4dmbE=. Pin the supplying commit and verify manifest source/file digests; the version alone does not identify a revision. Open example.html directly, without Astro, network assets or a build step. two-instances.html demonstrates independent IDs. For integration, include tokens.css, foundation.css and component.css in that order, then markup.html. Keep .j3w1-recipe and data-density on the wrapper. The source viewer can make a fresh instance prefix; use a unique prefix for every copy and rewrite all ID references together. diff --git a/exports/recipes/dialog/manifest.json b/exports/recipes/dialog/manifest.json index 03d876cb1..e2151ed90 100644 --- a/exports/recipes/dialog/manifest.json +++ b/exports/recipes/dialog/manifest.json @@ -21,9 +21,9 @@ "LICENSE.md": "sha256-Ih5+DpqcNXGWJX6BbYgpt6psmJi9lGcXGJzuiU7elE0=", "tokens/primitives.tokens.json": "sha256-cmydigBuNgi4hyQLi+3VS5JBhDQ8VMStlmUtPSSc05E=", "tokens/semantic.tokens.json": "sha256-jbrikW294TIEdB7rAiqlLPAiLUy2CMyLT/opZiVe/E0=", - "tokens/foundations.tokens.json": "sha256-/gYmJavPwEyem7mpNRhaBa8jjyuPKnSisugGky3PdCY=" + "tokens/foundations.tokens.json": "sha256-e5OLoStuVryktzLt5O1yFmTb1CR3DcgqccWy5SdB2fw=" }, - "digest": "sha256-O/XLRlwd5dEvDccFKU/lnvNi424Qy8nvTrinPm4hgZU=", + "digest": "sha256-rGmI15TyvMxO8spWUF+5eZKe7AY/PEAFRjjtWy4dmbE=", "revisionPolicy": "Resolve these paths at the same pinned commit as this manifest. The hosted source viewer identifies its supplying commit; generated source files contain content digests, never a floating revision claim." }, "dependencies": { @@ -476,6 +476,6 @@ "example.html": "sha256-4W9jw4/GPrhd2VhxlZXF91t2yanib4VIWbJ18XomB0I=", "two-instances.html": "sha256-KqTTacdBcUnD+k4PYaBYhC74nsIJ1Twu1IOaDjQdoFI=", "LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "README.md": "sha256-AL07d5Th8y7YXkw0pqRE3C5OtnLoJoPkd0TrkVBXVd0=" + "README.md": "sha256-JtVWLmJ6VdsYRA9228KVpvrqV8PdIsYeyo8w2Vm0DOM=" } } diff --git a/exports/recipes/index.json b/exports/recipes/index.json index d314d216d..9e61e3c5c 100644 --- a/exports/recipes/index.json +++ b/exports/recipes/index.json @@ -7,7 +7,7 @@ "id": "button", "variant": "default", "manifest": "exports/recipes/button/manifest.json", - "sourceDigest": "sha256-tLOvGHSxAnJojvXOq307DdwimfKorzgnNxhuLtFEc6k=", + "sourceDigest": "sha256-hOIrvGlqp/Z7O1QGYmAJCA5koRmhBBdkctoKbof/hOU=", "limitations": [ "Native button activation only; application actions are supplied by the host.", "aria-busy supplies the loading appearance; the host must suppress repeated activation while busy." @@ -17,7 +17,7 @@ "id": "text-field", "variant": "default", "manifest": "exports/recipes/text-field/manifest.json", - "sourceDigest": "sha256-0dRyQbwiDMQLwJzeoNbHAnfQaeDkppIgJOluTJqTdWU=", + "sourceDigest": "sha256-iO7O5tqk4cxfEtjsWh8120uVrqnkvliv37lngYjJXvw=", "limitations": [ "Native text editing only; validation messages and aria-invalid are managed by the host.", "The default text variant is packaged. Password reveal, search clearing and number steppers are not implemented." @@ -27,7 +27,7 @@ "id": "dialog", "variant": "default", "manifest": "exports/recipes/dialog/manifest.json", - "sourceDigest": "sha256-O/XLRlwd5dEvDccFKU/lnvNi424Qy8nvTrinPm4hgZU=", + "sourceDigest": "sha256-rGmI15TyvMxO8spWUF+5eZKe7AY/PEAFRjjtWy4dmbE=", "limitations": [ "Visual-only: the native dialog is open in normal flow with a simulated backdrop.", "No showModal, focus trap, Escape handling, close actions or focus return is supplied. The host owns the complete modal lifecycle and positioning.", diff --git a/exports/recipes/text-field/README.md b/exports/recipes/text-field/README.md index b2899f873..8f7021cfc 100644 --- a/exports/recipes/text-field/README.md +++ b/exports/recipes/text-field/README.md @@ -2,7 +2,7 @@ j3w1 theme 4.0.0. Markup adapted from j3w1 UI Theme Spec, https://github.com/j3w1/theme, CC BY 4.0: https://creativecommons.org/licenses/by/4.0/. Changes: scoped instance IDs and documentation-only content removed. CSS and generator: MIT; see LICENSE.md. -Version 4.0.0; profile default; source digest sha256-0dRyQbwiDMQLwJzeoNbHAnfQaeDkppIgJOluTJqTdWU=. Pin the supplying commit and verify manifest source/file digests; the version alone does not identify a revision. +Version 4.0.0; profile default; source digest sha256-iO7O5tqk4cxfEtjsWh8120uVrqnkvliv37lngYjJXvw=. Pin the supplying commit and verify manifest source/file digests; the version alone does not identify a revision. Open example.html directly, without Astro, network assets or a build step. two-instances.html demonstrates independent IDs. For integration, include tokens.css, foundation.css and component.css in that order, then markup.html. Keep .j3w1-recipe and data-density on the wrapper. The source viewer can make a fresh instance prefix; use a unique prefix for every copy and rewrite all ID references together. diff --git a/exports/recipes/text-field/manifest.json b/exports/recipes/text-field/manifest.json index 693541504..c1d318365 100644 --- a/exports/recipes/text-field/manifest.json +++ b/exports/recipes/text-field/manifest.json @@ -21,9 +21,9 @@ "LICENSE.md": "sha256-Ih5+DpqcNXGWJX6BbYgpt6psmJi9lGcXGJzuiU7elE0=", "tokens/primitives.tokens.json": "sha256-cmydigBuNgi4hyQLi+3VS5JBhDQ8VMStlmUtPSSc05E=", "tokens/semantic.tokens.json": "sha256-jbrikW294TIEdB7rAiqlLPAiLUy2CMyLT/opZiVe/E0=", - "tokens/foundations.tokens.json": "sha256-/gYmJavPwEyem7mpNRhaBa8jjyuPKnSisugGky3PdCY=" + "tokens/foundations.tokens.json": "sha256-e5OLoStuVryktzLt5O1yFmTb1CR3DcgqccWy5SdB2fw=" }, - "digest": "sha256-0dRyQbwiDMQLwJzeoNbHAnfQaeDkppIgJOluTJqTdWU=", + "digest": "sha256-iO7O5tqk4cxfEtjsWh8120uVrqnkvliv37lngYjJXvw=", "revisionPolicy": "Resolve these paths at the same pinned commit as this manifest. The hosted source viewer identifies its supplying commit; generated source files contain content digests, never a floating revision claim." }, "dependencies": { @@ -359,6 +359,6 @@ "example.html": "sha256-OT8OHppA6ssLf5OlKXOIqPBdkCDLa9lXaqsUOtT1SyQ=", "two-instances.html": "sha256-Abep8m5/si0kuUu3cVGEVzcHqMN1pHkPazmjloND8J0=", "LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "README.md": "sha256-4IdgTG0RNA0xp3IIcosxkwvq7KQdLS2Wiw1TuWxlzas=" + "README.md": "sha256-IBA7Qgs31PqUxOZM9Pvcdfrq6E0ccMpSHeNnSTvZ1y4=" } } diff --git a/exports/task-inputs.json b/exports/task-inputs.json index f287a3459..f23f72100 100644 --- a/exports/task-inputs.json +++ b/exports/task-inputs.json @@ -145,21 +145,25 @@ "font.letter-spacing.terminal", "font.line-height.caption", "font.line-height.code", + "font.line-height.display", "font.line-height.h1", "font.line-height.h2", "font.line-height.h3", "font.line-height.reading", "font.line-height.terminal", + "font.line-height.title", "font.line-height.ui-lg", "font.line-height.ui-md", "font.line-height.ui-sm", "font.size.caption", "font.size.code", + "font.size.display", "font.size.h1", "font.size.h2", "font.size.h3", "font.size.reading", "font.size.terminal", + "font.size.title", "font.size.ui-lg", "font.size.ui-md", "font.size.ui-sm", @@ -195,7 +199,7 @@ "z.skip-link", "z.toast" ], - "usageDigest": "sha256-H96Z5c44DtcP5MzkPiReXm1oXLTe31w6fu20W6dFqHc=", + "usageDigest": "sha256-a1rYc+D6as/OKhMIp1zkGNWMvTXGSuwI6SbU1VNTcKA=", "tokenDependencies": { "border.width.default": [], "border.width.emphasis": [], @@ -941,21 +945,25 @@ "font.letter-spacing.terminal": [], "font.line-height.caption": [], "font.line-height.code": [], + "font.line-height.display": [], "font.line-height.h1": [], "font.line-height.h2": [], "font.line-height.h3": [], "font.line-height.reading": [], "font.line-height.terminal": [], + "font.line-height.title": [], "font.line-height.ui-lg": [], "font.line-height.ui-md": [], "font.line-height.ui-sm": [], "font.size.caption": [], "font.size.code": [], + "font.size.display": [], "font.size.h1": [], "font.size.h2": [], "font.size.h3": [], "font.size.reading": [], "font.size.terminal": [], + "font.size.title": [], "font.size.ui-lg": [], "font.size.ui-md": [], "font.size.ui-sm": [], @@ -996,81 +1004,81 @@ }, "files": { "agents/consume.md": "sha256-i6Yk0kTqauioqD23HdGiN3S1EkyVC1bn/m86OR99hqc=", - "exports/components/admin-form.json": "sha256-eRnLywYWpnSnpPiv4MrY0aGZ7BpZEkrJG13tpAxopto=", - "exports/components/alert.json": "sha256-fY305BXYtrgqi7ICbnawYPMKZC9ff3t3yJ4I2vRbBZU=", - "exports/components/avatar.json": "sha256-xsnyI/5aT2MHasx+JQVNpW8boRicxTzw7yA1saDCjnY=", - "exports/components/badge.json": "sha256-DwK1qRsb78sSqHyFijG2LGi2lFpfbsuqo/Hn0S+uvK8=", - "exports/components/breadcrumbs.json": "sha256-zQLfzLX17c6/w9Qc+NDjT46WgvUPizPDz+c6bFM0ghQ=", - "exports/components/button-group.json": "sha256-BSp7Mjeyt4XOWCQXFLRlAx8sJg9nw2GeACg8H+o0FEE=", - "exports/components/button.json": "sha256-4p1xTZHKv9gloF1QMtXjx9iP2eX9r9MiKd820lW31eA=", - "exports/components/card.json": "sha256-0yl0cP1PZEnhNuyuDaCh3Sruv1J0TcGwSnVqV6RsJwM=", - "exports/components/chart.json": "sha256-oeL0YqV4bPrm0R9MGZYndDvymTiIipuRNuV6dSTNAWc=", - "exports/components/checkbox.json": "sha256-vKh60jFbH2dStEUVLlAcQGeDkBvWNoY+xASXA2PBvD8=", - "exports/components/chip.json": "sha256-PUw2hBa9KFySjCvs2KFCcOHknMs3XPW4cmQMZt19Wgg=", - "exports/components/code-editor.json": "sha256-BEBkn4aICM9agXkKXXoD/Vp2vBw9L9xzf+PskyKutps=", - "exports/components/combobox.json": "sha256-L40mUBv9JftFkoxyytSym7B7RdgvPbzJepfORUt1D+E=", - "exports/components/command-palette.json": "sha256-v+uBQa15HR8RmrV4TgtASLLL6heTJxuxXd0eLANkAr8=", - "exports/components/compact-dashboard.json": "sha256-46PH1YfxF9fa19v3TMeXZQ7cunnFu60zupp+ilyPDX0=", - "exports/components/data-table.json": "sha256-Jx64WzlClg9ZEjLxdNQtSVyug+zJB8nR/9Az2E7rjD0=", - "exports/components/date-picker.json": "sha256-OUGlLh96huXjIEMtVvEA+FVyp4wx1rVR4Ycj0/4jqA0=", - "exports/components/description-list.json": "sha256-23PielDBv+IvWwGgCucwAFo4aOa2I3rvIyFz7s2Ppm8=", - "exports/components/diagnostics.json": "sha256-DCtdyZ1SB9wO/wcv2e7Vm9K7r7zgTZ/usd0BW+Q+Qns=", - "exports/components/dialog.json": "sha256-3biN4pOh3Xno1zp8fqp+lfgzhZVGDs3fvOwL+ykPLRo=", - "exports/components/diff-view.json": "sha256-8wdU0wsWaPK9CQrN7RrbVRlH5MPJzkVRaeSCXtrR62k=", - "exports/components/disclosure.json": "sha256-shzZ4BJIKao0FVzzv9rmRShM3oUhpXciXiPAEYxhDUg=", - "exports/components/drawer.json": "sha256-QV4H85dSIRy6UAX3RNVGkFy9s2CYHMnbc+T3AozYPfY=", - "exports/components/editor-search.json": "sha256-Gs8sGmYigdm6zJuRk6PO3SZ7DTxlvC8rYJDfMFv2LGQ=", - "exports/components/empty-state.json": "sha256-csrcqKJBMSQ83ah0QGhwEUBUJCzTxs/gmI7Fyew7SAk=", - "exports/components/error-state.json": "sha256-J2Ybn0Dp2zC6DcaNms4M95wSwRuOVbdCbSwVTtZBs3A=", - "exports/components/field.json": "sha256-CwS97OOd/TiSLj14ddTEjLtB+YFwuFwzOeO3Dh0QQyM=", - "exports/components/fieldset.json": "sha256-GoUuPV0K4ZEke68Rd5Rep63pZdJrVq0wcP5mtKWaJSA=", - "exports/components/file-browser.json": "sha256-uCnasCmeUQYFtNwJUXAO41JiYtF8z/0EFeoJLvN0jdc=", - "exports/components/file-input.json": "sha256-WJZZCzR/rBLpBfBw8APEkufz7gWWEslnGppb/sKAni8=", - "exports/components/filterable-table.json": "sha256-UFRKkL/36KWNeQWcJ7D0jfZmLoSXvaabNYfVxXy6bBY=", - "exports/components/form-builder.json": "sha256-7EFKC4g8k2rGhehRW1TKvQgyFpElPMPvf33C83xJRNw=", - "exports/components/i3-window-frame.json": "sha256-3vAv8bfDYiK/FtH4WKmbicoPHFOznTjnqcDlaNK7dt8=", - "exports/components/icon-button.json": "sha256-RJm9x6pPDFnF9Q23dbBmUb0E50a1MAx3JroWrDWKS5M=", - "exports/components/kbd.json": "sha256-l5Bw/Ul8RVifiaH6ooa8AlA5sakuJCoZOPQQbPduvYg=", - "exports/components/link.json": "sha256-+bhCm/tbl4N7iCv2WO4cqaTh4FIT5+MPZHd1u3z4R+s=", - "exports/components/list.json": "sha256-MpHwE+aKAPvY3CcyudupD7Lw0IjZBimlMjT6TuaS0hA=", - "exports/components/loading-indicator.json": "sha256-2QKuRjZVJXAgdPIO8G8Y6aJ9KGxA6o6rOiSEp/PvcYE=", - "exports/components/menu.json": "sha256-muiitCeijBJjHeaTp/QQx6+IEmQOM4cWE9TrKO77e1Y=", - "exports/components/multiselect.json": "sha256-4KQgviHmIt6BV24Ovi6iT9bZsRYCKoLRsXv3+6e7bAI=", - "exports/components/number-field.json": "sha256-X2RtxXMFv9aZYoHXBehlz8Yd1gRUJGBEaxlrbbpw2dc=", - "exports/components/pagination.json": "sha256-yn4BdNlOV/vtz3svE4If1Bbov1AfMfzpKdiAN6133nA=", - "exports/components/popover.json": "sha256-EqTG6rC/VtjPzPC5p+8mQCZRmyKmpPaM/gyjnu4fkBs=", - "exports/components/progress.json": "sha256-gQkfI0q7nw95iejhwbgBL+qnK3YC1Ti/A/fqHcUFodw=", - "exports/components/radio-group.json": "sha256-EfvnwOBwd3pdtmPY0Islp1+TgVzZNhfl2aMwwy/ct0k=", - "exports/components/range.json": "sha256-acSO0+fixlkKfME6RFcpK00skJMP8gDNPoJhx0jbz90=", - "exports/components/repeater.json": "sha256-hd5TfCdk3cefdLf2qQ2VvfCFQ0SZRelNey3Rrg+Po5s=", - "exports/components/search-field.json": "sha256-mBG4aed8CuPQnOqvyyO2Ki/6P7Kd+scL0gvy8BSuh0I=", - "exports/components/segmented-control.json": "sha256-NxtziV/OygaDGi6mc6tElJnGbo/IMXmL3Kw0oo4hbWo=", - "exports/components/select.json": "sha256-lxY8viVzwv7lZNWQb25Q710kRbpjsvAiJOCyNsswl/A=", - "exports/components/settings-panel.json": "sha256-3LcKWsvRUalOjqpJ8BWHz+NwCeeE1QPVVYKBDRl95c0=", - "exports/components/sidebar-nav.json": "sha256-DH9/5y5vhlFC2xhkSRxPHjQUItnETFyylJNlL/eQvZA=", - "exports/components/skeleton.json": "sha256-G4HrDr9EuEoWZF5QAu2me2ELZv5wbUmJ3BdH88gd2qI=", - "exports/components/skip-link.json": "sha256-BVXQbbhH/Yw/1w4ZH4udwjBvHR9EvpaFCklwRMaBzSY=", - "exports/components/switch.json": "sha256-oxfIG+7uoRIjqhOX8NJeLOwk96/YOO4xuorhVjcMeBA=", - "exports/components/table.json": "sha256-SuXNBFtY8Ta7SYiGP++3vK2F1R5qMDhCqm9MsNridnE=", - "exports/components/tabs.json": "sha256-kvXJtwi+CXSlwSfuKCFXif3+f4RC46YAdX5OscNk7Ak=", - "exports/components/terminal.json": "sha256-XyXr8dnvYT95prOlPBbRj5a9g68EAugPetzv9jAKXMs=", - "exports/components/text-field.json": "sha256-Lex9v1t/4/YXIFJqbJxCwK/4nVl7XPA9D+FEjx0Rn6M=", - "exports/components/textarea.json": "sha256-qV1f7XUpYBKJjKIEnduDtBzG6e0UNZC/YT0VDcNdnCQ=", - "exports/components/time-picker.json": "sha256-n9Z27zWFtF0b3GMeCpOO+TyPM/HbKs5YHSFtnu3R8cs=", - "exports/components/timeline.json": "sha256-24hw5t5rGVCeQYH/Z0ZPIcm2M/rSYkqCJmgitCPU4ok=", - "exports/components/toast.json": "sha256-iLhC7qFWAYHMbtBKnDeDEPkHEQ9tbsB6tG/Y9lswAUI=", - "exports/components/toolbar.json": "sha256-Qg6UH+C0B9R4jOBl1rmkgPvEiDvUlT3A/wKGVT2XgZM=", - "exports/components/tooltip.json": "sha256-imfWbgUObvGd82f5lAzHDkjiG7mAqvrJYbZQ8vEISkU=", - "exports/components/tree.json": "sha256-CiayPirCLB4h2A0r+OGyq06JJ6ZVylcVctATkD2K5gg=", - "exports/components/wizard.json": "sha256-pLB+Xs9mSPIhdnsLvv4MEbI4ATie7GjnBP6nAhCf8N4=", - "exports/port-capabilities.json": "sha256-c4HHGplL/Vh7JJD8MZONBbTRbEpYe+mYNVPsVbFoRRE=", + "exports/components/admin-form.json": "sha256-cMCzZ7Y6R5vDQhUKroYjVSLFkJHU3Gli08YeWYYWjMc=", + "exports/components/alert.json": "sha256-SDyyVlrQ4zCsh1k9d6euBFC5H1XTIXNlwApLZ28huDs=", + "exports/components/avatar.json": "sha256-hUNV+6XmlXrHWL6Tic/4F2BgAkQDiplqsBttX7wyBVo=", + "exports/components/badge.json": "sha256-J6LygawZXw+gAxgIfKKMtKinZWxdT4fQ7JbeHvOxI7Q=", + "exports/components/breadcrumbs.json": "sha256-ZEltkBqhykUx1c98sp1AnzBLBOL38xfDyJvOTwm4Sh4=", + "exports/components/button-group.json": "sha256-Sq8vsc8jJEpMDIaHTq3UMiJ7LDvSiv5vmDoAuxQX7Wk=", + "exports/components/button.json": "sha256-ZlEnd0u5yLcxzB1C8tOCxvA8w2H5K9kB6SkPgTufJuk=", + "exports/components/card.json": "sha256-sjtZLyhgdgrEFnSySdcpLFbLyZkWKnIa1jsxlIVK71o=", + "exports/components/chart.json": "sha256-BasdUdA3MzGo0Rmmrmj+E6bMOtudFa8Xxcdb51Nizp0=", + "exports/components/checkbox.json": "sha256-lTwSQVmvHYgltg/LQk97oB/0JbAKuE3b4vjU8EE/mHk=", + "exports/components/chip.json": "sha256-BfTPtwtzIh8BFij9jAuBYFOI1OOsIa/QqxGxoSvruBQ=", + "exports/components/code-editor.json": "sha256-9LKz74FqUL7zWtnvvJ/AAzTZkLqpiZk6fmDkxJGzlgg=", + "exports/components/combobox.json": "sha256-slabxERChhxzMG1On6USB3ilVP2/GZ86qPGxrKtyd/I=", + "exports/components/command-palette.json": "sha256-kjl20b57OaZaKaOyQYMLeCMiiJtqygpnPayE03RaF9E=", + "exports/components/compact-dashboard.json": "sha256-mdvkqeJBaUpbi1OZalkU9nibADqwIXoBlEn7k1c9QK4=", + "exports/components/data-table.json": "sha256-GtiL/MsfUQrKkEhOX2LBO39gDmHItEupAGUcxO9S7so=", + "exports/components/date-picker.json": "sha256-I7/+SFQ5Etf2XhC1KC2zKnJoBuuUfQ+XBwSvzIIM9G4=", + "exports/components/description-list.json": "sha256-TcAgWaXIqrh7GnyY4Fh1sxw18w3Z64obPXXecZjM9PA=", + "exports/components/diagnostics.json": "sha256-XEiEML9kKK1Sx0WE7ntiSRf1x/LsJV0WRD7Ld7KIRBI=", + "exports/components/dialog.json": "sha256-iW1JIM20K7jbEJPsZT44sXsMWUbFYnoH8MKe+xSwKno=", + "exports/components/diff-view.json": "sha256-UV7sIl990iqjdYQ+70hGI5AnnZVgdnk2glZ2TGeMBh0=", + "exports/components/disclosure.json": "sha256-9XecJvyNgfoZEOW2s0oYxV0wASigN5AcdFQ5jSvLFl8=", + "exports/components/drawer.json": "sha256-UWZZjgftkOkdmmGie3aC6ygvdyubUx31slprKBMVXco=", + "exports/components/editor-search.json": "sha256-9OA9zuYcg6E9odzsrjVymAg0bXpA/YrgHDPTF+ZX3fc=", + "exports/components/empty-state.json": "sha256-9jQ+/tMzpDMWDn1FdHFsY5MvGelrQ7ChHrdJgDpPO2Y=", + "exports/components/error-state.json": "sha256-vgS8frriX3mDe18TFJsu8qMJ5vGa8pSmryajo5TX8Z0=", + "exports/components/field.json": "sha256-/mkJI+8jB6gTFIo3KiYT8xkFsr/YATG/S6dC68UXBL8=", + "exports/components/fieldset.json": "sha256-UwVGiS3NbUzuJsIir7uaYz0WnWsR6xBT7/qEBYIX8RI=", + "exports/components/file-browser.json": "sha256-5Zla/4ImfqmxvuIKDJDxEQodvH9GaqSc25g7SMLGyMs=", + "exports/components/file-input.json": "sha256-2BPV00mPYWRZwpGSypAWLwmyzqBlF5/h2S4H5pq/2Qc=", + "exports/components/filterable-table.json": "sha256-t59LtzesMFhdRKldod6ybMMKusCmRLNz4lbCOopPYrg=", + "exports/components/form-builder.json": "sha256-4mIniVSwqBN9xrQw+5U3yNtrlk/aRH8jZPKuY0aIcFo=", + "exports/components/i3-window-frame.json": "sha256-HE2yLQP/EeCfukaO9TmrjuntEfxBg45zTLfMTv8dV+w=", + "exports/components/icon-button.json": "sha256-sNwIKljbVPU+JhJSwXGW7HAJqD+603MQomnt9DXiGfg=", + "exports/components/kbd.json": "sha256-qtJdAYhDBzZPtmFspChfruWyiMDL9twSz9dLREQCMQw=", + "exports/components/link.json": "sha256-Ve/sgeCPW8kcWLJQRARNL0CZ6+8QnNZ3pfX5Yy2tjSA=", + "exports/components/list.json": "sha256-ayifS2PLlnD94AVUVt5LUutQj2M8RmG/kLVPtqTuAkY=", + "exports/components/loading-indicator.json": "sha256-shFLUs9MXfCP4POg3WBzqxyPjk47+79iE82UK5M1V6M=", + "exports/components/menu.json": "sha256-vxb+FTeoH6TkYXfE0DDg7xcAntQBy94waPLnLqUiB4Y=", + "exports/components/multiselect.json": "sha256-UiDVzUHMqLI+ruP4XdGhBuhdbP+5baB4PPlvNWBrlw4=", + "exports/components/number-field.json": "sha256-CYDT5nidQgoqOlXEDX8P4MMWaVY5gtgr0XoeBFYIFLY=", + "exports/components/pagination.json": "sha256-vFyBtSE4gjXCH2sQZbtvZNAlK2UZRRoX7ogz76srgG4=", + "exports/components/popover.json": "sha256-mTckWzUiz2rRahydiFa/ONiXepSRsdEbdYRvaJ92k54=", + "exports/components/progress.json": "sha256-DQMvp+PkVdptaRd9LjZ19GAiQVgMa0awWfpqeGfMV0o=", + "exports/components/radio-group.json": "sha256-Ybo2AlA1UgFQjRgOGq07P5lxGTsO4dP+D8wFo3c3qOU=", + "exports/components/range.json": "sha256-WIF2ZWvwloqTUB+95IHl9aTeKIuaSxFCo/GK3oKxqPo=", + "exports/components/repeater.json": "sha256-YW1BZL3NCKzxpyHd/oX4fmkbNzwZIeDh5ImXEZuTlo4=", + "exports/components/search-field.json": "sha256-gOrIeIfgFkPVcFjUBIrmT69tTA0ucPhyFpv9/9NLFNY=", + "exports/components/segmented-control.json": "sha256-L4OU1sHlD4fDrmyShueCt1NH9/xM2b71QmPjDetz7Ys=", + "exports/components/select.json": "sha256-yL+LqAY+oEKvdS7BUSSuv0a/z1RpMCc9DH2QhdgJ2JA=", + "exports/components/settings-panel.json": "sha256-tZqQ8ue4o/6aX+gIHuAw7U7+KfnO1KR+5b/KbqzidzQ=", + "exports/components/sidebar-nav.json": "sha256-9M/9axST95VbeHYLN2FsITzn819QUURTBFzeFZ7w3eU=", + "exports/components/skeleton.json": "sha256-nM5bEtPXQluMleeSjUbHKRiLicp4xKgCshJTmeAE2TQ=", + "exports/components/skip-link.json": "sha256-wfbZNR4N5PUEmEQQ7ustM2ZZkw4F4OOgo2uylcTpQA0=", + "exports/components/switch.json": "sha256-+qLnIwiesw3n677GRmUYDQnLQyF7caiVcrQ43qWDqco=", + "exports/components/table.json": "sha256-Y/Q057zrmXpCMHe71Dk+XFeRwLNu0QkE+JJQMgvVwqs=", + "exports/components/tabs.json": "sha256-4uEKjf6Pcl6epXayzGG7Rb6szfuzs1JaRdBHjSWx28U=", + "exports/components/terminal.json": "sha256-tmO1tF2j9qKaUBaCWKbLDbwc6RvjOeH/0QsD0HBHuyg=", + "exports/components/text-field.json": "sha256-VP6pzK4iEpJYP1z956Hy0l1cuQwtWdF13P3pTkc7hcA=", + "exports/components/textarea.json": "sha256-soblNoXVqwwH4841ku6gvoWpKHO9aZpUgbKZEdG0UcQ=", + "exports/components/time-picker.json": "sha256-aN3mUcCZMpc0H3B6cGSep2AEEUblbSurbtYZ+4c3voQ=", + "exports/components/timeline.json": "sha256-Lrmu0cnFU8OjQU20yskQ+wUPDZIeKHNyt1QL57Hpq8o=", + "exports/components/toast.json": "sha256-kEViFGDQbl6zuTVQWQAkR9uhmJChDetGK+VHu7R7/R4=", + "exports/components/toolbar.json": "sha256-HR1PNVg/kEeT2sPQLICqlHh2Jpwgmjz2ISDyKNbOnfA=", + "exports/components/tooltip.json": "sha256-W6/wWbuwFVhv7bacwRrT7HpcYnZIO0lq7M4l6wET6/4=", + "exports/components/tree.json": "sha256-oUHCGdl1TrWMb2+5kqpcUru1cUe4isv3d+K5i8m9GBo=", + "exports/components/wizard.json": "sha256-gm/Ax9KeTuUiV1krYNzcz6m57jB7lC4lRu3+W+QuZrA=", + "exports/port-capabilities.json": "sha256-6u3M0mXA+lN5FLjtOJvRkLpcFNePSv8ZUMpIiVohxVQ=", "exports/recipes/button/component.css": "sha256-+Fn90PbGbnW0JxDH1RAdiYrVQ4FrstMA+Rq7HlAQTdU=", "exports/recipes/button/example.html": "sha256-HRSLwap8t93ggusQ8BYoEAE0wPCsBWTKSY+4JGzRNa4=", "exports/recipes/button/foundation.css": "sha256-gItmMJgxTkuTe8+9G3aZQviwGcJ5cQaNANEvpcyOA88=", "exports/recipes/button/LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "exports/recipes/button/manifest.json": "sha256-GJJVcMHg7JCNv2EwQYzyH8HvblxYINZy4R644vtPIwo=", + "exports/recipes/button/manifest.json": "sha256-AA++frM2He0KhcMDOlEUKBy7S82fbjAvkWU7QAA69uc=", "exports/recipes/button/markup.html": "sha256-9HjLJ98lH4SKiwVWynQKarCqWTK/+IKfcvGr6464P3c=", - "exports/recipes/button/README.md": "sha256-XMR0WkxC2OZc4k7b4YbzLPO7V+3sqncs+Gp6VrWN/iA=", + "exports/recipes/button/README.md": "sha256-mS8bIWiTXGBfI7igIXsai6GF4p7KlPCfsQvAEFb9fls=", "exports/recipes/button/template.html": "sha256-FfylFZ+qzMUFxQKnIdqJiYmC8p4F+cNxK8BJSTo8XU8=", "exports/recipes/button/tokens.css": "sha256-a/TLRGPaqlzicffxz3q5+tWHlvaJ9h78GE1mHVxzp/s=", "exports/recipes/button/two-instances.html": "sha256-SUuvR3ZxzWymDnwkF8BdP321ok8G/grt3ePxGLLUBS4=", @@ -1078,9 +1086,9 @@ "exports/recipes/dialog/example.html": "sha256-4W9jw4/GPrhd2VhxlZXF91t2yanib4VIWbJ18XomB0I=", "exports/recipes/dialog/foundation.css": "sha256-gItmMJgxTkuTe8+9G3aZQviwGcJ5cQaNANEvpcyOA88=", "exports/recipes/dialog/LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "exports/recipes/dialog/manifest.json": "sha256-0OWeXDl1F2+hy0Go/RDdcxHVzikxDc44qksLw/QgUh0=", + "exports/recipes/dialog/manifest.json": "sha256-ICAb4/dJetXL173dvIYPXJ3XTZbrK5s0tRW/Ky5hH7Q=", "exports/recipes/dialog/markup.html": "sha256-o9WIUCRlY5GUbx8+IYfcIv9JJlXBbiJBjb7jUkjNTHE=", - "exports/recipes/dialog/README.md": "sha256-AL07d5Th8y7YXkw0pqRE3C5OtnLoJoPkd0TrkVBXVd0=", + "exports/recipes/dialog/README.md": "sha256-JtVWLmJ6VdsYRA9228KVpvrqV8PdIsYeyo8w2Vm0DOM=", "exports/recipes/dialog/template.html": "sha256-ekYfQWlHu6z/dh7Wi1W3GZayMjEjxB5ru5nU7CKIqMg=", "exports/recipes/dialog/tokens.css": "sha256-H4mpfW2luSqCo9S9PPrDgpevuK2OSiXDpp7+a+dFeFw=", "exports/recipes/dialog/two-instances.html": "sha256-KqTTacdBcUnD+k4PYaBYhC74nsIJ1Twu1IOaDjQdoFI=", @@ -1088,14 +1096,14 @@ "exports/recipes/text-field/example.html": "sha256-OT8OHppA6ssLf5OlKXOIqPBdkCDLa9lXaqsUOtT1SyQ=", "exports/recipes/text-field/foundation.css": "sha256-gItmMJgxTkuTe8+9G3aZQviwGcJ5cQaNANEvpcyOA88=", "exports/recipes/text-field/LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "exports/recipes/text-field/manifest.json": "sha256-ObZff1cu6gngs5yKnxm7yLN6N816nHa1rrKJYbiHygs=", + "exports/recipes/text-field/manifest.json": "sha256-hG79YUgUPrJHUwebcbJWobszHhgVqfqG1XOBASdFG6Q=", "exports/recipes/text-field/markup.html": "sha256-O4CmIRb2RUPigpgQAcre9bSpIRJxN52MMxJW4fTyhpM=", - "exports/recipes/text-field/README.md": "sha256-4IdgTG0RNA0xp3IIcosxkwvq7KQdLS2Wiw1TuWxlzas=", + "exports/recipes/text-field/README.md": "sha256-IBA7Qgs31PqUxOZM9Pvcdfrq6E0ccMpSHeNnSTvZ1y4=", "exports/recipes/text-field/template.html": "sha256-IlSlLS7sPC3MLqIdxMRQUP4sFnn/58lwM3AFALtdY3c=", "exports/recipes/text-field/tokens.css": "sha256-EqSdsrQqs1NJVLFBDmxFtT0mbcjOiUeAx1G9cTcdpIY=", "exports/recipes/text-field/two-instances.html": "sha256-Abep8m5/si0kuUu3cVGEVzcHqMN1pHkPazmjloND8J0=", - "exports/theme.compact.md": "sha256-scHwaXnCWxW392O05sqziYlTLymSaro4g5hSNijAwoo=", - "exports/tokens.resolved.json": "sha256-zFvYCG+sRacSRpLqVjVsMUNxxfakWzjnJrCN7WOgQYY=", + "exports/theme.compact.md": "sha256-jrEVDKhdwd24OJBek75+xuGzGoxkykr4U1pjkI5sadQ=", + "exports/tokens.resolved.json": "sha256-3KBrfmIiz4L6Qyqvi99TdTe4+5NeuA0ZWZe3Am4sRo4=", "LICENSE.md": "sha256-Ih5+DpqcNXGWJX6BbYgpt6psmJi9lGcXGJzuiU7elE0=", "schemas/json/theme.lock.schema.json": "sha256-y6m+IekX0jzgI6Rhel1Vx33fgz8RIT5A2OPyBL0qlXw=", "spec/accessibility.md": "sha256-XHd+Z74KRN/ftw9YeaZwfrjsI84HmeZJ/3gcllztxnM=", diff --git a/exports/theme.compact.md b/exports/theme.compact.md index 510926461..e183cab59 100644 --- a/exports/theme.compact.md +++ b/exports/theme.compact.md @@ -1,5 +1,5 @@ # j3w1 UI Theme Spec — compact (4.0.0, profile: default) - + Read this first; it is the smallest complete statement of the approved contract. Pin a tag or commit and fetch every file at that revision (see `agents/consume.md`). Values marked PROPOSED are not approved. @@ -137,6 +137,8 @@ Surfaces, text, borders, interaction, actions and status. The code, diagnostic, | `font.size.reading` | `15px` | | | `font.size.code` | `13px` | | | `font.size.terminal` | `13px` | URxvt pixelsize 13. | +| `font.size.display` | `32px` | Page heroes and metric figures on the portal (D-037). | +| `font.size.title` | `24px` | Page titles above h1 on the portal (D-037). | | `font.size.h1` | `20px` | | | `font.size.h2` | `16px` | | | `font.size.h3` | `13px` | | diff --git a/exports/theme.full.md b/exports/theme.full.md index 2a5c84678..8deb5f799 100644 --- a/exports/theme.full.md +++ b/exports/theme.full.md @@ -1,5 +1,5 @@ # j3w1 UI Theme Spec — full (4.0.0) - + Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens. Everything in one document: identity, foundations, every profile's resolved tokens, accessibility with the contrast report, portability, every component specification, the coverage ledger, the support table, the decision log and the references catalogue. @@ -583,6 +583,8 @@ role audit in `docs/rose-typography-migration.md`; measure the actual state pair | `font.size.reading` | `15px` | | | `font.size.code` | `13px` | | | `font.size.terminal` | `13px` | URxvt pixelsize 13. | +| `font.size.display` | `32px` | Page heroes and metric figures on the portal (D-037). | +| `font.size.title` | `24px` | Page titles above h1 on the portal (D-037). | | `font.size.h1` | `20px` | | | `font.size.h2` | `16px` | | | `font.size.h3` | `13px` | | @@ -593,6 +595,8 @@ role audit in `docs/rose-typography-migration.md`; measure the actual state pair | `font.line-height.reading` | `24px` | | | `font.line-height.code` | `19px` | | | `font.line-height.terminal` | `19px` | | +| `font.line-height.display` | `40px` | | +| `font.line-height.title` | `32px` | | | `font.line-height.h1` | `28px` | | | `font.line-height.h2` | `24px` | | | `font.line-height.h3` | `18px` | | @@ -8084,6 +8088,7 @@ apply. | D-034 | Versioned Windows native and Windhawk adapters | accepted | 2026-09-28 | owner (explicit implementation plan) | | D-035 | An accent surface for the user's own content | accepted | 2026-10-06 | owner (Telegram acceptance: own and other people's messages too similar; chose #3d0c0a from a side-by-side comparison) | | D-036 | A translucent text-selection tint | accepted | 2026-10-06 | owner (Telegram acceptance: Android text selection barely visible; chose 50% from a side-by-side comparison) | +| D-037 | Display and title type sizes | proposed | 2026-10-14 | — | ### D-000 Responsibility split @@ -8981,6 +8986,23 @@ visible in the message field. Android's text-selection keys had the 12% chose 50% from the side-by-side comparison after the review rejected the opaque fill. +### D-037 Display and title type sizes + +**Decision.** Two type roles join the scale: `font.size.display` with +`font.line-height.display` (32/40) for page heroes and metric figures, and +`font.size.title` with `font.line-height.title` (24/32) for page titles above +h1. Portal pages use them instead of literal sizes; components keep h1–h3. + +**Why.** The portal set 48, 32, 24, 22 and 18px outside the token scale. The +owner chose token sizes over shrinking every heading to h1 (planning, +2026-10-14). + +**Alternatives.** The existing scale only (portal headings shrink to 20px), or +page-local literal sizes. + +**Status.** proposed · 2026-10-14. The owner asked for display type tokens in +planning; the owner sets the status. + ## References | Reference | Kind | Where | What it does not prove | diff --git a/exports/token-usage.json b/exports/token-usage.json index 4c4daa771..80271b4da 100644 --- a/exports/token-usage.json +++ b/exports/token-usage.json @@ -176,7 +176,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/breakpoint/lg", - "line": 459 + "line": 485 }, "provenance": null, "aliases": [], @@ -186,11 +186,11 @@ {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/breakpoint.lg","line":134}}, {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/breakpoint.lg","line":75}}, {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/breakpoint.lg","line":75}}, - {"port":"obsidian","reason":"breakpoint.lg: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/breakpoint.lg","line":694}}, + {"port":"obsidian","reason":"breakpoint.lg: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/breakpoint.lg","line":698}}, {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/breakpoint.lg","line":81}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/breakpoint.lg","line":1587}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/breakpoint.lg","line":1591}}, {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/breakpoint.lg","line":68}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/breakpoint.lg","line":2505}} + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/breakpoint.lg","line":2509}} ], "uses": [], "contrast": [] @@ -211,7 +211,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/breakpoint/md", - "line": 453 + "line": 479 }, "provenance": null, "aliases": [], @@ -221,11 +221,11 @@ {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/breakpoint.md","line":135}}, {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/breakpoint.md","line":76}}, {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/breakpoint.md","line":76}}, - {"port":"obsidian","reason":"breakpoint.md: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/breakpoint.md","line":693}}, + {"port":"obsidian","reason":"breakpoint.md: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/breakpoint.md","line":697}}, {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/breakpoint.md","line":82}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/breakpoint.md","line":1586}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/breakpoint.md","line":1590}}, {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/breakpoint.md","line":69}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/breakpoint.md","line":2504}} + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/breakpoint.md","line":2508}} ], "uses": [], "contrast": [] @@ -246,7 +246,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/breakpoint/sm", - "line": 447 + "line": 473 }, "provenance": null, "aliases": [], @@ -256,11 +256,11 @@ {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/breakpoint.sm","line":136}}, {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/breakpoint.sm","line":77}}, {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/breakpoint.sm","line":77}}, - {"port":"obsidian","reason":"breakpoint.sm: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/breakpoint.sm","line":692}}, + {"port":"obsidian","reason":"breakpoint.sm: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/breakpoint.sm","line":696}}, {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/breakpoint.sm","line":83}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/breakpoint.sm","line":1585}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/breakpoint.sm","line":1589}}, {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/breakpoint.sm","line":70}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/breakpoint.sm","line":2503}} + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/breakpoint.sm","line":2507}} ], "uses": [], "contrast": [] @@ -281,7 +281,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/breakpoint/xs", - "line": 440 + "line": 466 }, "provenance": null, "aliases": [], @@ -291,11 +291,11 @@ {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/breakpoint.xs","line":137}}, {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/breakpoint.xs","line":78}}, {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/breakpoint.xs","line":78}}, - {"port":"obsidian","reason":"breakpoint.xs: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/breakpoint.xs","line":691}}, + {"port":"obsidian","reason":"breakpoint.xs: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/breakpoint.xs","line":695}}, {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/breakpoint.xs","line":84}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/breakpoint.xs","line":1584}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/breakpoint.xs","line":1588}}, {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/breakpoint.xs","line":71}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/breakpoint.xs","line":2502}} + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/breakpoint.xs","line":2506}} ], "uses": [], "contrast": [] @@ -373,7 +373,7 @@ {"port":"claude-code","reason":"Interface colour role that no Claude Code theme key takes.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/color.action.destructive.filled-bg","line":139}}, {"port":"codex","reason":"Interface colour role; a Codex tmTheme colours code only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/color.action.destructive.filled-bg","line":80}}, {"port":"ghostty","reason":"Interface colour role; a terminal theme file carries terminal colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/color.action.destructive.filled-bg","line":80}}, - {"port":"obsidian","reason":"Native desktop warning/confirmation fills and their hover/mobile-tap variants consume background-modifier-error/error-hover, owned by status.danger.fill; mobile warning uses interactive-normal. No independent filled-bg assignment is claimed.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/color.action.destructive.filled-bg","line":706}}, + {"port":"obsidian","reason":"Native desktop warning/confirmation fills and their hover/mobile-tap variants consume background-modifier-error/error-hover, owned by status.danger.fill; mobile warning uses interactive-normal. No independent filled-bg assignment is claimed.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/color.action.destructive.filled-bg","line":710}}, {"port":"orca","reason":"Interface colour role; a terminal theme file carries terminal colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/color.action.destructive.filled-bg","line":86}}, {"port":"telegram","reason":"color.action.destructive.filled-bg has no separate native hook in this projection; related controls share the declared canonical role instead.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/color.action.destructive.filled-bg","line":1418}}, {"port":"warp","reason":"Interface colour role; a terminal theme file carries terminal colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/color.action.destructive.filled-bg","line":73}}, @@ -8442,14 +8442,14 @@ ], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Focus, hover, pressed and selection colours are derived by ChatGPT from the accent and contrast; only the accent is set.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/color.interaction.text-selection.tint","line":376}}, - {"port":"claude-code","reason":"Interface colour role that no Claude Code theme key takes.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/color.interaction.text-selection.tint","line":453}}, - {"port":"codex","reason":"Interface colour role; a Codex tmTheme colours code only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/color.interaction.text-selection.tint","line":399}}, - {"port":"ghostty","reason":"Interface colour role; a terminal theme file carries terminal colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/color.interaction.text-selection.tint","line":399}}, - {"port":"obsidian","reason":"Obsidian keeps the text colour inside a selection (rose 3.96:1 on --text-selection, IMPLEMENTATION.md), so the tint fits it; adopting it changes the Obsidian artifact and needs its own import check, so --text-selection keeps text-selection.bg for now.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/color.interaction.text-selection.tint","line":711}}, - {"port":"orca","reason":"Interface colour role; a terminal theme file carries terminal colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/color.interaction.text-selection.tint","line":403}}, - {"port":"warp","reason":"Interface colour role; a terminal theme file carries terminal colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/color.interaction.text-selection.tint","line":394}}, - {"port":"windows","reason":"The Windows adapters retain native selection foregrounds and their existing opaque selection or marquee mappings; no host requiring this tint is admitted.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/color.interaction.text-selection.tint","line":2520}} + {"port":"chatgpt","reason":"Focus, hover, pressed and selection colours are derived by ChatGPT from the accent and contrast; only the accent is set.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/color.interaction.text-selection.tint","line":380}}, + {"port":"claude-code","reason":"Interface colour role that no Claude Code theme key takes.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/color.interaction.text-selection.tint","line":457}}, + {"port":"codex","reason":"Interface colour role; a Codex tmTheme colours code only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/color.interaction.text-selection.tint","line":403}}, + {"port":"ghostty","reason":"Interface colour role; a terminal theme file carries terminal colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/color.interaction.text-selection.tint","line":403}}, + {"port":"obsidian","reason":"Obsidian keeps the text colour inside a selection (rose 3.96:1 on --text-selection, IMPLEMENTATION.md), so the tint fits it; adopting it changes the Obsidian artifact and needs its own import check, so --text-selection keeps text-selection.bg for now.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/color.interaction.text-selection.tint","line":715}}, + {"port":"orca","reason":"Interface colour role; a terminal theme file carries terminal colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/color.interaction.text-selection.tint","line":407}}, + {"port":"warp","reason":"Interface colour role; a terminal theme file carries terminal colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/color.interaction.text-selection.tint","line":398}}, + {"port":"windows","reason":"The Windows adapters retain native selection foregrounds and their existing opaque selection or marquee mappings; no host requiring this tint is admitted.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/color.interaction.text-selection.tint","line":2524}} ], "uses": [ {"kind":"contrast","component":null,"part":null,"state":null,"variant":null,"surface":"color.interaction.text-selection.tint","nativeKey":null,"port":null,"source":{"file":"spec/contrast.json","pointer":"/pairs/74","line":78}}, @@ -8630,15 +8630,15 @@ "color.interaction.text-selection.tint" ], "unmappedPorts": [ - {"port":"chatgpt","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/color.primitive.alpha.red-50","line":377}}, - {"port":"claude-code","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/color.primitive.alpha.red-50","line":454}}, - {"port":"codex","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/color.primitive.alpha.red-50","line":400}}, - {"port":"ghostty","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/color.primitive.alpha.red-50","line":400}}, - {"port":"obsidian","reason":"Inspection-only primitive; Obsidian consumes semantic roles, never primitives.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/color.primitive.alpha.red-50","line":710}}, - {"port":"orca","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/color.primitive.alpha.red-50","line":404}}, + {"port":"chatgpt","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/color.primitive.alpha.red-50","line":381}}, + {"port":"claude-code","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/color.primitive.alpha.red-50","line":458}}, + {"port":"codex","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/color.primitive.alpha.red-50","line":404}}, + {"port":"ghostty","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/color.primitive.alpha.red-50","line":404}}, + {"port":"obsidian","reason":"Inspection-only primitive; Obsidian consumes semantic roles, never primitives.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/color.primitive.alpha.red-50","line":714}}, + {"port":"orca","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/color.primitive.alpha.red-50","line":408}}, {"port":"telegram","reason":"Primitives are blocked inspection values; Telegram consumes semantic roles only.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/color.primitive.alpha.red-50","line":1357}}, - {"port":"warp","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/color.primitive.alpha.red-50","line":395}}, - {"port":"windows","reason":"Primitive inspection value; Windows consumes canonical semantic roles only.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/color.primitive.alpha.red-50","line":2518}} + {"port":"warp","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/color.primitive.alpha.red-50","line":399}}, + {"port":"windows","reason":"Primitive inspection value; Windows consumes canonical semantic roles only.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/color.primitive.alpha.red-50","line":2522}} ], "uses": [], "contrast": [] @@ -11130,15 +11130,15 @@ "color.surface.accent" ], "unmappedPorts": [ - {"port":"chatgpt","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/color.primitive.red.40","line":378}}, - {"port":"claude-code","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/color.primitive.red.40","line":455}}, - {"port":"codex","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/color.primitive.red.40","line":401}}, - {"port":"ghostty","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/color.primitive.red.40","line":401}}, - {"port":"obsidian","reason":"Inspection-only primitive; Obsidian consumes semantic roles, never primitives.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/color.primitive.red.40","line":709}}, - {"port":"orca","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/color.primitive.red.40","line":405}}, + {"port":"chatgpt","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/color.primitive.red.40","line":382}}, + {"port":"claude-code","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/color.primitive.red.40","line":459}}, + {"port":"codex","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/color.primitive.red.40","line":405}}, + {"port":"ghostty","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/color.primitive.red.40","line":405}}, + {"port":"obsidian","reason":"Inspection-only primitive; Obsidian consumes semantic roles, never primitives.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/color.primitive.red.40","line":713}}, + {"port":"orca","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/color.primitive.red.40","line":409}}, {"port":"telegram","reason":"Primitives are blocked inspection values; Telegram consumes semantic roles only.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/color.primitive.red.40","line":1311}}, - {"port":"warp","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/color.primitive.red.40","line":396}}, - {"port":"windows","reason":"Primitive inspection value; Windows consumes canonical semantic roles only.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/color.primitive.red.40","line":2517}} + {"port":"warp","reason":"Primitive; ports consume roles, never primitives.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/color.primitive.red.40","line":400}}, + {"port":"windows","reason":"Primitive inspection value; Windows consumes canonical semantic roles only.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/color.primitive.red.40","line":2521}} ], "uses": [], "contrast": [] @@ -13721,7 +13721,7 @@ {"port":"claude-code","reason":"Interface colour role that no Claude Code theme key takes.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/color.status.warning.tint","line":342}}, {"port":"codex","reason":"Interface colour role; a Codex tmTheme colours code only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/color.status.warning.tint","line":278}}, {"port":"ghostty","reason":"Interface colour role; a terminal theme file carries terminal colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/color.status.warning.tint","line":297}}, - {"port":"obsidian","reason":"No consumer for background-modifier-warning/warning-hover in audited Obsidian 1.13.4/1.13.7; warning callouts compute their tint from callout-warning, not this exact tint role.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/color.status.warning.tint","line":707}}, + {"port":"obsidian","reason":"No consumer for background-modifier-warning/warning-hover in audited Obsidian 1.13.4/1.13.7; warning callouts compute their tint from callout-warning, not this exact tint role.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/color.status.warning.tint","line":711}}, {"port":"orca","reason":"Interface colour role; a terminal theme file carries terminal colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/color.status.warning.tint","line":303}}, {"port":"telegram","reason":"color.status.warning.tint has no separate native hook in this projection; related controls share the declared canonical role instead.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/color.status.warning.tint","line":1425}}, {"port":"warp","reason":"Interface colour role; a terminal theme file carries terminal colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/color.status.warning.tint","line":291}}, @@ -13777,14 +13777,14 @@ ], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"ChatGPT has one background and no separate surface for the user's own messages.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/color.surface.accent","line":379}}, - {"port":"claude-code","reason":"Claude Code's userMessageBackground keeps color.interaction.selection.bg; adopting color.surface.accent there is a separate change for this port.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/color.surface.accent","line":456}}, - {"port":"codex","reason":"Interface colour role; a Codex tmTheme colours code only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/color.surface.accent","line":402}}, - {"port":"ghostty","reason":"Interface colour role; a terminal theme file carries terminal colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/color.surface.accent","line":402}}, - {"port":"obsidian","reason":"Obsidian has no surface for the user's own messages.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/color.surface.accent","line":712}}, - {"port":"orca","reason":"Interface colour role; a terminal theme file carries terminal colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/color.surface.accent","line":406}}, - {"port":"warp","reason":"Interface colour role; a terminal theme file carries terminal colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/color.surface.accent","line":397}}, - {"port":"windows","reason":"Outgoing-message surfaces are outside the Windows visual adapter scope; native application content remains unchanged.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/color.surface.accent","line":2519}} + {"port":"chatgpt","reason":"ChatGPT has one background and no separate surface for the user's own messages.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/color.surface.accent","line":383}}, + {"port":"claude-code","reason":"Claude Code's userMessageBackground keeps color.interaction.selection.bg; adopting color.surface.accent there is a separate change for this port.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/color.surface.accent","line":460}}, + {"port":"codex","reason":"Interface colour role; a Codex tmTheme colours code only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/color.surface.accent","line":406}}, + {"port":"ghostty","reason":"Interface colour role; a terminal theme file carries terminal colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/color.surface.accent","line":406}}, + {"port":"obsidian","reason":"Obsidian has no surface for the user's own messages.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/color.surface.accent","line":716}}, + {"port":"orca","reason":"Interface colour role; a terminal theme file carries terminal colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/color.surface.accent","line":410}}, + {"port":"warp","reason":"Interface colour role; a terminal theme file carries terminal colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/color.surface.accent","line":401}}, + {"port":"windows","reason":"Outgoing-message surfaces are outside the Windows visual adapter scope; native application content remains unchanged.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/color.surface.accent","line":2523}} ], "uses": [ {"kind":"contrast","component":null,"part":null,"state":null,"variant":null,"surface":"color.surface.accent","nativeKey":null,"port":null,"source":{"file":"spec/contrast.json","pointer":"/pairs/70","line":74}}, @@ -18916,13 +18916,13 @@ ], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/color.text.heading","line":374}}, - {"port":"claude-code","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/color.text.heading","line":451}}, - {"port":"codex","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/color.text.heading","line":397}}, - {"port":"ghostty","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/color.text.heading","line":397}}, - {"port":"orca","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/color.text.heading","line":401}}, - {"port":"telegram","reason":"The pinned Telegram theme formats expose shared names and chrome titles, but no independent content-heading foreground; UI titles remain canonical bright rose under D-033.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/color.text.heading","line":1600}}, - {"port":"warp","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/color.text.heading","line":392}} + {"port":"chatgpt","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/color.text.heading","line":378}}, + {"port":"claude-code","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/color.text.heading","line":455}}, + {"port":"codex","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/color.text.heading","line":401}}, + {"port":"ghostty","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/color.text.heading","line":401}}, + {"port":"orca","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/color.text.heading","line":405}}, + {"port":"telegram","reason":"The pinned Telegram theme formats expose shared names and chrome titles, but no independent content-heading foreground; UI titles remain canonical bright rose under D-033.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/color.text.heading","line":1604}}, + {"port":"warp","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/color.text.heading","line":396}} ], "uses": [ {"kind":"contrast","component":null,"part":null,"state":null,"variant":null,"surface":"color.surface.default","nativeKey":null,"port":null,"source":{"file":"spec/contrast.json","pointer":"/pairs/65","line":69}}, @@ -18971,13 +18971,13 @@ ], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/color.text.highlight","line":375}}, - {"port":"claude-code","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/color.text.highlight","line":452}}, - {"port":"codex","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/color.text.highlight","line":398}}, - {"port":"ghostty","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/color.text.highlight","line":398}}, - {"port":"obsidian","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/color.text.highlight","line":708}}, - {"port":"orca","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/color.text.highlight","line":402}}, - {"port":"warp","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/color.text.highlight","line":393}} + {"port":"chatgpt","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/color.text.highlight","line":379}}, + {"port":"claude-code","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/color.text.highlight","line":456}}, + {"port":"codex","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/color.text.highlight","line":402}}, + {"port":"ghostty","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/color.text.highlight","line":402}}, + {"port":"obsidian","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/color.text.highlight","line":712}}, + {"port":"orca","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/color.text.highlight","line":406}}, + {"port":"warp","reason":"Host exposes no separately mapped content heading/highlight foreground in this port.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/color.text.highlight","line":397}} ], "uses": [ {"kind":"contrast","component":null,"part":null,"state":null,"variant":null,"surface":"color.surface.default","nativeKey":null,"port":null,"source":{"file":"spec/contrast.json","pointer":"/pairs/67","line":71}}, @@ -19019,7 +19019,7 @@ {"port":"ghostty","reason":"Interface colour role; a terminal theme file carries terminal colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/color.text.inverse","line":317}}, {"port":"obsidian","reason":"No inverse-surface widget is installed in this dark-only port.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/color.text.inverse","line":541}}, {"port":"orca","reason":"Interface colour role; a terminal theme file carries terminal colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/color.text.inverse","line":323}}, - {"port":"telegram","reason":"color.text.inverse has no separate native hook in this projection; related controls share the declared canonical role instead.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/color.text.inverse","line":1599}}, + {"port":"telegram","reason":"color.text.inverse has no separate native hook in this projection; related controls share the declared canonical role instead.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/color.text.inverse","line":1603}}, {"port":"warp","reason":"Interface colour role; a terminal theme file carries terminal colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/color.text.inverse","line":312}}, {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/color.text.inverse","line":2358}} ], @@ -20076,7 +20076,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/comfortable/control-height", - "line": 295 + "line": 321 }, "provenance": null, "aliases": [], @@ -20087,9 +20087,9 @@ {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/density.comfortable.control-height","line":329}}, {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/density.comfortable.control-height","line":329}}, {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/density.comfortable.control-height","line":335}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/density.comfortable.control-height","line":1567}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/density.comfortable.control-height","line":1571}}, {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/density.comfortable.control-height","line":324}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/density.comfortable.control-height","line":2489}} + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/density.comfortable.control-height","line":2493}} ], "uses": [ {"kind":"part","component":"button-group","part":"dependency.role-density-comfortable-control-height","state":null,"variant":null,"surface":null,"nativeKey":null,"port":null,"source":{"file":"spec/components/button-group.md","pointer":"/tokens/dependency.role-density-comfortable-control-height","line":35}}, @@ -20125,7 +20125,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/comfortable/control-padding-x", - "line": 307 + "line": 333 }, "provenance": null, "aliases": [], @@ -20135,11 +20135,11 @@ {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/density.comfortable.control-padding-x","line":384}}, {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/density.comfortable.control-padding-x","line":330}}, {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/density.comfortable.control-padding-x","line":330}}, - {"port":"obsidian","reason":"density.comfortable.control-padding-x: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/density.comfortable.control-padding-x","line":678}}, + {"port":"obsidian","reason":"density.comfortable.control-padding-x: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/density.comfortable.control-padding-x","line":682}}, {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/density.comfortable.control-padding-x","line":336}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/density.comfortable.control-padding-x","line":1569}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/density.comfortable.control-padding-x","line":1573}}, {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/density.comfortable.control-padding-x","line":325}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/density.comfortable.control-padding-x","line":2491}} + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/density.comfortable.control-padding-x","line":2495}} ], "uses": [], "contrast": [] @@ -20160,7 +20160,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/comfortable/gap", - "line": 319 + "line": 345 }, "provenance": null, "aliases": [], @@ -20170,11 +20170,11 @@ {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/density.comfortable.gap","line":385}}, {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/density.comfortable.gap","line":331}}, {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/density.comfortable.gap","line":331}}, - {"port":"obsidian","reason":"density.comfortable.gap: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/density.comfortable.gap","line":680}}, + {"port":"obsidian","reason":"density.comfortable.gap: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/density.comfortable.gap","line":684}}, {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/density.comfortable.gap","line":337}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/density.comfortable.gap","line":1571}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/density.comfortable.gap","line":1575}}, {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/density.comfortable.gap","line":326}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/density.comfortable.gap","line":2493}} + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/density.comfortable.gap","line":2497}} ], "uses": [], "contrast": [] @@ -20195,7 +20195,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/comfortable/icon", - "line": 313 + "line": 339 }, "provenance": null, "aliases": [], @@ -20205,11 +20205,11 @@ {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/density.comfortable.icon","line":386}}, {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/density.comfortable.icon","line":332}}, {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/density.comfortable.icon","line":332}}, - {"port":"obsidian","reason":"density.comfortable.icon: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/density.comfortable.icon","line":679}}, + {"port":"obsidian","reason":"density.comfortable.icon: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/density.comfortable.icon","line":683}}, {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/density.comfortable.icon","line":338}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/density.comfortable.icon","line":1570}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/density.comfortable.icon","line":1574}}, {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/density.comfortable.icon","line":327}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/density.comfortable.icon","line":2492}} + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/density.comfortable.icon","line":2496}} ], "uses": [], "contrast": [] @@ -20230,7 +20230,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/comfortable/row-height", - "line": 301 + "line": 327 }, "provenance": null, "aliases": [], @@ -20240,11 +20240,11 @@ {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/density.comfortable.row-height","line":387}}, {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/density.comfortable.row-height","line":333}}, {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/density.comfortable.row-height","line":333}}, - {"port":"obsidian","reason":"density.comfortable.row-height: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/density.comfortable.row-height","line":677}}, + {"port":"obsidian","reason":"density.comfortable.row-height: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/density.comfortable.row-height","line":681}}, {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/density.comfortable.row-height","line":339}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/density.comfortable.row-height","line":1568}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/density.comfortable.row-height","line":1572}}, {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/density.comfortable.row-height","line":328}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/density.comfortable.row-height","line":2490}} + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/density.comfortable.row-height","line":2494}} ], "uses": [], "contrast": [] @@ -20265,7 +20265,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/compact/control-height", - "line": 263 + "line": 289 }, "provenance": null, "aliases": [], @@ -20275,11 +20275,11 @@ {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/density.compact.control-height","line":388}}, {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/density.compact.control-height","line":334}}, {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/density.compact.control-height","line":334}}, - {"port":"obsidian","reason":"density.compact.control-height: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/density.compact.control-height","line":674}}, + {"port":"obsidian","reason":"density.compact.control-height: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/density.compact.control-height","line":678}}, {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/density.compact.control-height","line":340}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/density.compact.control-height","line":1562}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/density.compact.control-height","line":1566}}, {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/density.compact.control-height","line":329}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/density.compact.control-height","line":2484}} + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/density.compact.control-height","line":2488}} ], "uses": [ {"kind":"part","component":"button-group","part":"dependency.role-density-compact-control-height","state":null,"variant":null,"surface":null,"nativeKey":null,"port":null,"source":{"file":"spec/components/button-group.md","pointer":"/tokens/dependency.role-density-compact-control-height","line":36}}, @@ -20314,7 +20314,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/compact/control-padding-x", - "line": 275 + "line": 301 }, "provenance": null, "aliases": [], @@ -20325,9 +20325,9 @@ {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/density.compact.control-padding-x","line":335}}, {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/density.compact.control-padding-x","line":335}}, {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/density.compact.control-padding-x","line":341}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/density.compact.control-padding-x","line":1564}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/density.compact.control-padding-x","line":1568}}, {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/density.compact.control-padding-x","line":330}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/density.compact.control-padding-x","line":2486}} + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/density.compact.control-padding-x","line":2490}} ], "uses": [ {"kind":"port","component":null,"part":null,"state":null,"variant":null,"surface":null,"nativeKey":".theme-dark .prompt .suggestion-item | padding-inline","port":"obsidian","source":{"file":"ports/obsidian/mapping.json","pointer":"/mappings/density.compact.control-padding-x/1","line":346}}, @@ -20351,7 +20351,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/compact/gap", - "line": 287 + "line": 313 }, "provenance": null, "aliases": [], @@ -20361,11 +20361,11 @@ {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/density.compact.gap","line":390}}, {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/density.compact.gap","line":336}}, {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/density.compact.gap","line":336}}, - {"port":"obsidian","reason":"density.compact.gap: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/density.compact.gap","line":676}}, + {"port":"obsidian","reason":"density.compact.gap: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/density.compact.gap","line":680}}, {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/density.compact.gap","line":342}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/density.compact.gap","line":1566}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/density.compact.gap","line":1570}}, {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/density.compact.gap","line":331}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/density.compact.gap","line":2488}} + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/density.compact.gap","line":2492}} ], "uses": [], "contrast": [] @@ -20386,7 +20386,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/compact/icon", - "line": 281 + "line": 307 }, "provenance": null, "aliases": [], @@ -20396,11 +20396,11 @@ {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/density.compact.icon","line":391}}, {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/density.compact.icon","line":337}}, {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/density.compact.icon","line":337}}, - {"port":"obsidian","reason":"density.compact.icon: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/density.compact.icon","line":675}}, + {"port":"obsidian","reason":"density.compact.icon: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/density.compact.icon","line":679}}, {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/density.compact.icon","line":343}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/density.compact.icon","line":1565}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/density.compact.icon","line":1569}}, {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/density.compact.icon","line":332}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/density.compact.icon","line":2487}} + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/density.compact.icon","line":2491}} ], "uses": [], "contrast": [] @@ -20421,7 +20421,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/compact/row-height", - "line": 269 + "line": 295 }, "provenance": null, "aliases": [], @@ -20432,9 +20432,9 @@ {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/density.compact.row-height","line":338}}, {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/density.compact.row-height","line":338}}, {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/density.compact.row-height","line":344}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/density.compact.row-height","line":1563}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/density.compact.row-height","line":1567}}, {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/density.compact.row-height","line":333}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/density.compact.row-height","line":2485}} + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/density.compact.row-height","line":2489}} ], "uses": [ {"kind":"port","component":null,"part":null,"state":null,"variant":null,"surface":null,"nativeKey":".theme-dark .prompt .suggestion-item | min-height","port":"obsidian","source":{"file":"ports/obsidian/mapping.json","pointer":"/mappings/density.compact.row-height/0","line":358}} @@ -20457,7 +20457,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/focus/offset", - "line": 347 + "line": 373 }, "provenance": null, "aliases": [], @@ -20468,7 +20468,7 @@ {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/focus.offset","line":339}}, {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/focus.offset","line":339}}, {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/focus.offset","line":345}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/focus.offset","line":1574}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/focus.offset","line":1578}}, {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/focus.offset","line":334}} ], "uses": [ @@ -20495,7 +20495,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/focus/offset-container", - "line": 355 + "line": 381 }, "provenance": null, "aliases": [], @@ -20505,9 +20505,9 @@ {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/focus.offset-container","line":394}}, {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/focus.offset-container","line":340}}, {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/focus.offset-container","line":340}}, - {"port":"obsidian","reason":"focus.offset-container: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/focus.offset-container","line":682}}, + {"port":"obsidian","reason":"focus.offset-container: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/focus.offset-container","line":686}}, {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/focus.offset-container","line":346}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/focus.offset-container","line":1575}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/focus.offset-container","line":1579}}, {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/focus.offset-container","line":335}} ], "uses": [ @@ -20531,7 +20531,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/focus/offset-invalid", - "line": 363 + "line": 389 }, "provenance": null, "aliases": [], @@ -20541,11 +20541,11 @@ {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/focus.offset-invalid","line":395}}, {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/focus.offset-invalid","line":341}}, {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/focus.offset-invalid","line":341}}, - {"port":"obsidian","reason":"focus.offset-invalid: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/focus.offset-invalid","line":683}}, + {"port":"obsidian","reason":"focus.offset-invalid: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/focus.offset-invalid","line":687}}, {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/focus.offset-invalid","line":347}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/focus.offset-invalid","line":1576}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/focus.offset-invalid","line":1580}}, {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/focus.offset-invalid","line":336}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/focus.offset-invalid","line":2496}} + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/focus.offset-invalid","line":2500}} ], "uses": [], "contrast": [] @@ -20566,7 +20566,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/focus/ring", - "line": 329 + "line": 355 }, "provenance": null, "aliases": [ @@ -20580,9 +20580,9 @@ {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/focus.ring","line":342}}, {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/focus.ring","line":342}}, {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/focus.ring","line":348}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/focus.ring","line":1572}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/focus.ring","line":1576}}, {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/focus.ring","line":337}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/focus.ring","line":2494}} + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/focus.ring","line":2498}} ], "uses": [ {"kind":"part","component":"multiselect","part":"dependency.role-focus-ring","state":null,"variant":null,"surface":null,"nativeKey":null,"port":null,"source":{"file":"spec/components/multiselect.md","pointer":"/tokens/dependency.role-focus-ring","line":49}}, @@ -20607,7 +20607,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/focus/ring-container", - "line": 338 + "line": 364 }, "provenance": null, "aliases": [ @@ -20620,11 +20620,11 @@ {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/focus.ring-container","line":397}}, {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/focus.ring-container","line":343}}, {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/focus.ring-container","line":343}}, - {"port":"obsidian","reason":"focus.ring-container: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/focus.ring-container","line":681}}, + {"port":"obsidian","reason":"focus.ring-container: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/focus.ring-container","line":685}}, {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/focus.ring-container","line":349}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/focus.ring-container","line":1573}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/focus.ring-container","line":1577}}, {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/focus.ring-container","line":338}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/focus.ring-container","line":2495}} + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/focus.ring-container","line":2499}} ], "uses": [], "contrast": [] @@ -20694,7 +20694,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/letter-spacing/terminal", - "line": 250 + "line": 276 }, "provenance": null, "aliases": [], @@ -20704,11 +20704,11 @@ {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.letter-spacing.terminal","line":399}}, {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.letter-spacing.terminal","line":345}}, {"port":"ghostty","reason":"A Ghostty theme carries colours; Ghostty has no letter-spacing key.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.letter-spacing.terminal","line":345}}, - {"port":"obsidian","reason":"font.letter-spacing.terminal: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.letter-spacing.terminal","line":673}}, + {"port":"obsidian","reason":"font.letter-spacing.terminal: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.letter-spacing.terminal","line":677}}, {"port":"orca","reason":"Neither the Ghostty config nor Orca's import has a letter-spacing key.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.letter-spacing.terminal","line":350}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.letter-spacing.terminal","line":1561}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.letter-spacing.terminal","line":1565}}, {"port":"warp","reason":"The application's own terminal font setting.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.letter-spacing.terminal","line":340}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.letter-spacing.terminal","line":2483}} + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.letter-spacing.terminal","line":2487}} ], "uses": [], "contrast": [] @@ -20729,7 +20729,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/caption", - "line": 241 + "line": 267 }, "provenance": null, "aliases": [], @@ -20739,11 +20739,11 @@ {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.line-height.caption","line":400}}, {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.line-height.caption","line":346}}, {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.line-height.caption","line":346}}, - {"port":"obsidian","reason":"font.line-height.caption: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.caption","line":672}}, + {"port":"obsidian","reason":"font.line-height.caption: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.caption","line":676}}, {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.line-height.caption","line":351}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.caption","line":1560}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.caption","line":1564}}, {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.line-height.caption","line":341}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.line-height.caption","line":2482}} + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.line-height.caption","line":2486}} ], "uses": [], "contrast": [] @@ -20764,7 +20764,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/code", - "line": 211 + "line": 225 }, "provenance": null, "aliases": [], @@ -20774,9 +20774,9 @@ {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.line-height.code","line":401}}, {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.line-height.code","line":347}}, {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.line-height.code","line":347}}, - {"port":"obsidian","reason":"font.line-height.code: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.code","line":667}}, + {"port":"obsidian","reason":"font.line-height.code: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.code","line":669}}, {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.line-height.code","line":352}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.code","line":1555}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.code","line":1557}}, {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.line-height.code","line":342}} ], "uses": [ @@ -20784,6 +20784,41 @@ ], "contrast": [] }, + "font.line-height.display": { + "path": "font.line-height.display", + "group": "font", + "css": "40px", + "variable": "--font-line-height-display", + "description": null, + "status": "observed", + "deprecated": false, + "eligibility": { + "action": "use", + "reason": "Use within the role's documented scope and restrictions.", + "decisionIds": [] + }, + "source": { + "file": "tokens/foundations.tokens.json", + "pointer": "/font/line-height/display", + "line": 237 + }, + "provenance": null, + "aliases": [], + "usedByAliases": [], + "unmappedPorts": [ + {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.line-height.display","line":327}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.line-height.display","line":402}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.line-height.display","line":348}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.line-height.display","line":348}}, + {"port":"obsidian","reason":"font.line-height.display: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.display","line":671}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.line-height.display","line":353}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.display","line":1559}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.line-height.display","line":343}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.line-height.display","line":2484}} + ], + "uses": [], + "contrast": [] + }, "font.line-height.h1": { "path": "font.line-height.h1", "group": "font", @@ -20800,20 +20835,20 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/h1", - "line": 223 + "line": 249 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.line-height.h1","line":327}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.line-height.h1","line":402}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.line-height.h1","line":348}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.line-height.h1","line":348}}, - {"port":"obsidian","reason":"font.line-height.h1: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.h1","line":669}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.line-height.h1","line":353}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.h1","line":1557}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.line-height.h1","line":343}} + {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.line-height.h1","line":329}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.line-height.h1","line":404}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.line-height.h1","line":350}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.line-height.h1","line":350}}, + {"port":"obsidian","reason":"font.line-height.h1: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.h1","line":673}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.line-height.h1","line":355}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.h1","line":1561}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.line-height.h1","line":345}} ], "uses": [ {"kind":"port","component":null,"part":null,"state":null,"variant":null,"surface":null,"nativeKey":"powertoys.markdown.H1_LINE","port":"windows","source":{"file":"ports/windows/mapping.json","pointer":"/mappings/font.line-height.h1/0","line":2092}} @@ -20836,20 +20871,20 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/h2", - "line": 229 + "line": 255 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.line-height.h2","line":328}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.line-height.h2","line":403}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.line-height.h2","line":349}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.line-height.h2","line":349}}, - {"port":"obsidian","reason":"font.line-height.h2: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.h2","line":670}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.line-height.h2","line":354}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.h2","line":1558}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.line-height.h2","line":344}} + {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.line-height.h2","line":330}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.line-height.h2","line":405}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.line-height.h2","line":351}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.line-height.h2","line":351}}, + {"port":"obsidian","reason":"font.line-height.h2: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.h2","line":674}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.line-height.h2","line":356}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.h2","line":1562}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.line-height.h2","line":346}} ], "uses": [ {"kind":"port","component":null,"part":null,"state":null,"variant":null,"surface":null,"nativeKey":"powertoys.markdown.H2_LINE","port":"windows","source":{"file":"ports/windows/mapping.json","pointer":"/mappings/font.line-height.h2/0","line":2098}} @@ -20872,20 +20907,20 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/h3", - "line": 235 + "line": 261 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.line-height.h3","line":329}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.line-height.h3","line":404}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.line-height.h3","line":350}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.line-height.h3","line":350}}, - {"port":"obsidian","reason":"font.line-height.h3: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.h3","line":671}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.line-height.h3","line":355}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.h3","line":1559}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.line-height.h3","line":345}} + {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.line-height.h3","line":331}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.line-height.h3","line":406}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.line-height.h3","line":352}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.line-height.h3","line":352}}, + {"port":"obsidian","reason":"font.line-height.h3: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.h3","line":675}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.line-height.h3","line":357}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.h3","line":1563}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.line-height.h3","line":347}} ], "uses": [ {"kind":"port","component":null,"part":null,"state":null,"variant":null,"surface":null,"nativeKey":"powertoys.markdown.H3_LINE","port":"windows","source":{"file":"ports/windows/mapping.json","pointer":"/mappings/font.line-height.h3/0","line":2125}} @@ -20908,20 +20943,20 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/reading", - "line": 205 + "line": 219 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.line-height.reading","line":330}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.line-height.reading","line":405}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.line-height.reading","line":351}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.line-height.reading","line":351}}, - {"port":"obsidian","reason":"font.line-height.reading: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.reading","line":666}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.line-height.reading","line":356}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.reading","line":1554}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.line-height.reading","line":346}} + {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.line-height.reading","line":332}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.line-height.reading","line":407}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.line-height.reading","line":353}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.line-height.reading","line":353}}, + {"port":"obsidian","reason":"font.line-height.reading: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.reading","line":668}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.line-height.reading","line":358}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.reading","line":1556}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.line-height.reading","line":348}} ], "uses": [ {"kind":"port","component":null,"part":null,"state":null,"variant":null,"surface":null,"nativeKey":"powertoys.markdown.READING_LINE","port":"windows","source":{"file":"ports/windows/mapping.json","pointer":"/mappings/font.line-height.reading/0","line":2080}} @@ -20944,21 +20979,56 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/terminal", - "line": 217 + "line": 231 + }, + "provenance": null, + "aliases": [], + "usedByAliases": [], + "unmappedPorts": [ + {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.line-height.terminal","line":333}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.line-height.terminal","line":408}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.line-height.terminal","line":354}}, + {"port":"ghostty","reason":"A Ghostty theme carries colours; adjust-cell-height has no exact conversion from a pixel line height.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.line-height.terminal","line":354}}, + {"port":"obsidian","reason":"font.line-height.terminal: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.terminal","line":670}}, + {"port":"orca","reason":"Ghostty's adjust-cell-height, which Orca imports, is relative to the font's own cell height; a pixel line height has no exact conversion. Orca keeps its line-height setting.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.line-height.terminal","line":359}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.terminal","line":1558}}, + {"port":"warp","reason":"The application's own terminal font setting.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.line-height.terminal","line":349}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.line-height.terminal","line":2483}} + ], + "uses": [], + "contrast": [] + }, + "font.line-height.title": { + "path": "font.line-height.title", + "group": "font", + "css": "32px", + "variable": "--font-line-height-title", + "description": null, + "status": "observed", + "deprecated": false, + "eligibility": { + "action": "use", + "reason": "Use within the role's documented scope and restrictions.", + "decisionIds": [] + }, + "source": { + "file": "tokens/foundations.tokens.json", + "pointer": "/font/line-height/title", + "line": 243 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.line-height.terminal","line":331}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.line-height.terminal","line":406}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.line-height.terminal","line":352}}, - {"port":"ghostty","reason":"A Ghostty theme carries colours; adjust-cell-height has no exact conversion from a pixel line height.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.line-height.terminal","line":352}}, - {"port":"obsidian","reason":"font.line-height.terminal: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.terminal","line":668}}, - {"port":"orca","reason":"Ghostty's adjust-cell-height, which Orca imports, is relative to the font's own cell height; a pixel line height has no exact conversion. Orca keeps its line-height setting.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.line-height.terminal","line":357}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.terminal","line":1556}}, - {"port":"warp","reason":"The application's own terminal font setting.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.line-height.terminal","line":347}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.line-height.terminal","line":2481}} + {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.line-height.title","line":328}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.line-height.title","line":403}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.line-height.title","line":349}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.line-height.title","line":349}}, + {"port":"obsidian","reason":"font.line-height.title: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.title","line":672}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.line-height.title","line":354}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.title","line":1560}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.line-height.title","line":344}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.line-height.title","line":2485}} ], "uses": [], "contrast": [] @@ -20979,21 +21049,21 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/ui-lg", - "line": 199 + "line": 213 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.line-height.ui-lg","line":332}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.line-height.ui-lg","line":407}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.line-height.ui-lg","line":353}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.line-height.ui-lg","line":353}}, - {"port":"obsidian","reason":"font.line-height.ui-lg: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.ui-lg","line":665}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.line-height.ui-lg","line":358}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.ui-lg","line":1553}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.line-height.ui-lg","line":348}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.line-height.ui-lg","line":2480}} + {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.line-height.ui-lg","line":334}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.line-height.ui-lg","line":409}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.line-height.ui-lg","line":355}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.line-height.ui-lg","line":355}}, + {"port":"obsidian","reason":"font.line-height.ui-lg: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.ui-lg","line":667}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.line-height.ui-lg","line":360}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.ui-lg","line":1555}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.line-height.ui-lg","line":350}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.line-height.ui-lg","line":2482}} ], "uses": [], "contrast": [] @@ -21014,21 +21084,21 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/ui-md", - "line": 193 + "line": 207 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.line-height.ui-md","line":333}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.line-height.ui-md","line":408}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.line-height.ui-md","line":354}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.line-height.ui-md","line":354}}, - {"port":"obsidian","reason":"font.line-height.ui-md: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.ui-md","line":664}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.line-height.ui-md","line":359}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.ui-md","line":1552}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.line-height.ui-md","line":349}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.line-height.ui-md","line":2479}} + {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.line-height.ui-md","line":335}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.line-height.ui-md","line":410}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.line-height.ui-md","line":356}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.line-height.ui-md","line":356}}, + {"port":"obsidian","reason":"font.line-height.ui-md: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.ui-md","line":666}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.line-height.ui-md","line":361}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.ui-md","line":1554}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.line-height.ui-md","line":351}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.line-height.ui-md","line":2481}} ], "uses": [ {"kind":"part","component":"multiselect","part":"dependency.role-font-line-height-ui-md","state":null,"variant":null,"surface":null,"nativeKey":null,"port":null,"source":{"file":"spec/components/multiselect.md","pointer":"/tokens/dependency.role-font-line-height-ui-md","line":50}}, @@ -21052,21 +21122,21 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/ui-sm", - "line": 187 + "line": 201 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.line-height.ui-sm","line":334}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.line-height.ui-sm","line":409}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.line-height.ui-sm","line":355}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.line-height.ui-sm","line":355}}, - {"port":"obsidian","reason":"font.line-height.ui-sm: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.ui-sm","line":663}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.line-height.ui-sm","line":360}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.ui-sm","line":1551}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.line-height.ui-sm","line":350}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.line-height.ui-sm","line":2478}} + {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.line-height.ui-sm","line":336}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.line-height.ui-sm","line":411}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.line-height.ui-sm","line":357}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.line-height.ui-sm","line":357}}, + {"port":"obsidian","reason":"font.line-height.ui-sm: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.line-height.ui-sm","line":665}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.line-height.ui-sm","line":362}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.line-height.ui-sm","line":1553}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.line-height.ui-sm","line":352}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.line-height.ui-sm","line":2480}} ], "uses": [ {"kind":"part","component":"multiselect","part":"dependency.role-font-line-height-ui-sm","state":null,"variant":null,"surface":null,"nativeKey":null,"port":null,"source":{"file":"spec/components/multiselect.md","pointer":"/tokens/dependency.role-font-line-height-ui-sm","line":51}}, @@ -21090,21 +21160,21 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/size/caption", - "line": 177 + "line": 191 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"ChatGPT has only a UI size and a code size.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.size.caption","line":335}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.caption","line":410}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.caption","line":356}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.caption","line":356}}, - {"port":"obsidian","reason":"font.size.caption: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.size.caption","line":662}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.size.caption","line":361}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.size.caption","line":1550}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.caption","line":351}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.size.caption","line":2477}} + {"port":"chatgpt","reason":"ChatGPT has only a UI size and a code size.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.size.caption","line":337}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.caption","line":412}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.caption","line":358}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.caption","line":358}}, + {"port":"obsidian","reason":"font.size.caption: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.size.caption","line":664}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.size.caption","line":363}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.size.caption","line":1552}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.caption","line":353}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.size.caption","line":2479}} ], "uses": [], "contrast": [] @@ -21131,13 +21201,13 @@ "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.code","line":411}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.code","line":357}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.code","line":357}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.code","line":413}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.code","line":359}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.code","line":359}}, {"port":"obsidian","reason":"font.size.code: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.size.code","line":657}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.size.code","line":362}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.size.code","line":364}}, {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.size.code","line":1545}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.code","line":352}} + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.code","line":354}} ], "uses": [ {"kind":"port","component":null,"part":null,"state":null,"variant":null,"surface":null,"nativeKey":"Code font size","port":"chatgpt","source":{"file":"ports/chatgpt/mapping.json","pointer":"/mappings/font.size.code/0","line":16}}, @@ -21145,6 +21215,41 @@ ], "contrast": [] }, + "font.size.display": { + "path": "font.size.display", + "group": "font", + "css": "32px", + "variable": "--font-size-display", + "description": "Page heroes and metric figures on the portal (D-037).", + "status": "observed", + "deprecated": false, + "eligibility": { + "action": "use", + "reason": "Use within the role's documented scope and restrictions.", + "decisionIds": [] + }, + "source": { + "file": "tokens/foundations.tokens.json", + "pointer": "/font/size/display", + "line": 159 + }, + "provenance": null, + "aliases": [], + "usedByAliases": [], + "unmappedPorts": [ + {"port":"chatgpt","reason":"ChatGPT has only a UI size and a code size.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.size.display","line":338}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.display","line":414}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.display","line":360}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.display","line":360}}, + {"port":"obsidian","reason":"font.size.display: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.size.display","line":659}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.size.display","line":365}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.size.display","line":1547}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.display","line":355}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.size.display","line":2477}} + ], + "uses": [], + "contrast": [] + }, "font.size.h1": { "path": "font.size.h1", "group": "font", @@ -21161,20 +21266,20 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/size/h1", - "line": 159 + "line": 173 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"ChatGPT has only a UI size and a code size.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.size.h1","line":336}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.h1","line":412}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.h1","line":358}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.h1","line":358}}, - {"port":"obsidian","reason":"font.size.h1: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.size.h1","line":659}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.size.h1","line":363}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.size.h1","line":1547}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.h1","line":353}} + {"port":"chatgpt","reason":"ChatGPT has only a UI size and a code size.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.size.h1","line":340}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.h1","line":416}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.h1","line":362}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.h1","line":362}}, + {"port":"obsidian","reason":"font.size.h1: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.size.h1","line":661}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.size.h1","line":367}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.size.h1","line":1549}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.h1","line":357}} ], "uses": [ {"kind":"port","component":null,"part":null,"state":null,"variant":null,"surface":null,"nativeKey":"powertoys.markdown.H1_SIZE","port":"windows","source":{"file":"ports/windows/mapping.json","pointer":"/mappings/font.size.h1/0","line":2089}} @@ -21197,20 +21302,20 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/size/h2", - "line": 165 + "line": 179 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"ChatGPT has only a UI size and a code size.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.size.h2","line":337}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.h2","line":413}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.h2","line":359}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.h2","line":359}}, - {"port":"obsidian","reason":"font.size.h2: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.size.h2","line":660}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.size.h2","line":364}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.size.h2","line":1548}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.h2","line":354}} + {"port":"chatgpt","reason":"ChatGPT has only a UI size and a code size.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.size.h2","line":341}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.h2","line":417}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.h2","line":363}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.h2","line":363}}, + {"port":"obsidian","reason":"font.size.h2: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.size.h2","line":662}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.size.h2","line":368}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.size.h2","line":1550}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.h2","line":358}} ], "uses": [ {"kind":"part","component":"compact-dashboard","part":"dependency.role-font-size-h2","state":null,"variant":null,"surface":null,"nativeKey":null,"port":null,"source":{"file":"spec/components/compact-dashboard.md","pointer":"/tokens/dependency.role-font-size-h2","line":38}}, @@ -21234,20 +21339,20 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/size/h3", - "line": 171 + "line": 185 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"ChatGPT has only a UI size and a code size.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.size.h3","line":338}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.h3","line":414}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.h3","line":360}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.h3","line":360}}, - {"port":"obsidian","reason":"font.size.h3: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.size.h3","line":661}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.size.h3","line":365}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.size.h3","line":1549}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.h3","line":355}} + {"port":"chatgpt","reason":"ChatGPT has only a UI size and a code size.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.size.h3","line":342}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.h3","line":418}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.h3","line":364}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.h3","line":364}}, + {"port":"obsidian","reason":"font.size.h3: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.size.h3","line":663}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.size.h3","line":369}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.size.h3","line":1551}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.h3","line":359}} ], "uses": [ {"kind":"port","component":null,"part":null,"state":null,"variant":null,"surface":null,"nativeKey":"powertoys.markdown.H3_SIZE","port":"windows","source":{"file":"ports/windows/mapping.json","pointer":"/mappings/font.size.h3/0","line":2122}} @@ -21276,13 +21381,13 @@ "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.reading","line":415}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.reading","line":361}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.reading","line":361}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.reading","line":419}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.reading","line":365}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.reading","line":365}}, {"port":"obsidian","reason":"font.size.reading: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.size.reading","line":656}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.size.reading","line":366}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.size.reading","line":370}}, {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.size.reading","line":1544}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.reading","line":356}} + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.reading","line":360}} ], "uses": [ {"kind":"port","component":null,"part":null,"state":null,"variant":null,"surface":null,"nativeKey":"powertoys.markdown.READING_SIZE","port":"windows","source":{"file":"ports/windows/mapping.json","pointer":"/mappings/font.size.reading/0","line":2077}}, @@ -21312,13 +21417,13 @@ "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"ChatGPT has only a UI size and a code size.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.size.terminal","line":339}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.terminal","line":416}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.terminal","line":362}}, - {"port":"ghostty","reason":"A Ghostty theme carries colours; set font-size in your own config.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.terminal","line":362}}, + {"port":"chatgpt","reason":"ChatGPT has only a UI size and a code size.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.size.terminal","line":343}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.terminal","line":420}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.terminal","line":366}}, + {"port":"ghostty","reason":"A Ghostty theme carries colours; set font-size in your own config.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.terminal","line":366}}, {"port":"obsidian","reason":"font.size.terminal: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.size.terminal","line":658}}, {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.size.terminal","line":1546}}, - {"port":"warp","reason":"The application's own terminal font setting.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.terminal","line":357}}, + {"port":"warp","reason":"The application's own terminal font setting.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.terminal","line":361}}, {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.size.terminal","line":2476}} ], "uses": [ @@ -21326,6 +21431,41 @@ ], "contrast": [] }, + "font.size.title": { + "path": "font.size.title", + "group": "font", + "css": "24px", + "variable": "--font-size-title", + "description": "Page titles above h1 on the portal (D-037).", + "status": "observed", + "deprecated": false, + "eligibility": { + "action": "use", + "reason": "Use within the role's documented scope and restrictions.", + "decisionIds": [] + }, + "source": { + "file": "tokens/foundations.tokens.json", + "pointer": "/font/size/title", + "line": 166 + }, + "provenance": null, + "aliases": [], + "usedByAliases": [], + "unmappedPorts": [ + {"port":"chatgpt","reason":"ChatGPT has only a UI size and a code size.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.size.title","line":339}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.title","line":415}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.title","line":361}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.title","line":361}}, + {"port":"obsidian","reason":"font.size.title: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.size.title","line":660}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.size.title","line":366}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.size.title","line":1548}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.title","line":356}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.size.title","line":2478}} + ], + "uses": [], + "contrast": [] + }, "font.size.ui-lg": { "path": "font.size.ui-lg", "group": "font", @@ -21348,14 +21488,14 @@ "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"ChatGPT has only a UI size and a code size.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.size.ui-lg","line":340}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.ui-lg","line":417}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.ui-lg","line":363}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.ui-lg","line":363}}, + {"port":"chatgpt","reason":"ChatGPT has only a UI size and a code size.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.size.ui-lg","line":344}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.ui-lg","line":421}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.ui-lg","line":367}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.ui-lg","line":367}}, {"port":"obsidian","reason":"font.size.ui-lg: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.size.ui-lg","line":655}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.size.ui-lg","line":367}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.size.ui-lg","line":371}}, {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.size.ui-lg","line":1543}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.ui-lg","line":358}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.ui-lg","line":362}}, {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.size.ui-lg","line":2475}} ], "uses": [], @@ -21383,14 +21523,14 @@ "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"ChatGPT has only a UI size and a code size.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.size.ui-md","line":341}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.ui-md","line":418}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.ui-md","line":364}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.ui-md","line":364}}, + {"port":"chatgpt","reason":"ChatGPT has only a UI size and a code size.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.size.ui-md","line":345}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.ui-md","line":422}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.ui-md","line":368}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.ui-md","line":368}}, {"port":"obsidian","reason":"font.size.ui-md: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.size.ui-md","line":654}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.size.ui-md","line":368}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.size.ui-md","line":372}}, {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.size.ui-md","line":1542}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.ui-md","line":359}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.ui-md","line":363}}, {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.size.ui-md","line":2474}} ], "uses": [ @@ -21421,14 +21561,14 @@ "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"ChatGPT has only a UI size and a code size.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.size.ui-sm","line":342}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.ui-sm","line":419}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.ui-sm","line":365}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.ui-sm","line":365}}, + {"port":"chatgpt","reason":"ChatGPT has only a UI size and a code size.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.size.ui-sm","line":346}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.size.ui-sm","line":423}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.size.ui-sm","line":369}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.size.ui-sm","line":369}}, {"port":"obsidian","reason":"font.size.ui-sm: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/font.size.ui-sm","line":653}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.size.ui-sm","line":369}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.size.ui-sm","line":373}}, {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.size.ui-sm","line":1541}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.ui-sm","line":360}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.size.ui-sm","line":364}}, {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.size.ui-sm","line":2473}} ], "uses": [ @@ -21459,13 +21599,13 @@ "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.weight.bold","line":343}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.weight.bold","line":420}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.weight.bold","line":366}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.weight.bold","line":366}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.weight.bold","line":370}}, + {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.weight.bold","line":347}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.weight.bold","line":424}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.weight.bold","line":370}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.weight.bold","line":370}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.weight.bold","line":374}}, {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.weight.bold","line":1540}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.weight.bold","line":361}} + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.weight.bold","line":365}} ], "uses": [ {"kind":"part","component":"avatar","part":"dependency.role-font-weight-bold","state":null,"variant":null,"surface":null,"nativeKey":null,"port":null,"source":{"file":"spec/components/avatar.md","pointer":"/tokens/dependency.role-font-weight-bold","line":32}}, @@ -21496,13 +21636,13 @@ "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.weight.regular","line":344}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.weight.regular","line":421}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.weight.regular","line":367}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.weight.regular","line":367}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.weight.regular","line":371}}, + {"port":"chatgpt","reason":"ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/font.weight.regular","line":348}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/font.weight.regular","line":425}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/font.weight.regular","line":371}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/font.weight.regular","line":371}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/font.weight.regular","line":375}}, {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/font.weight.regular","line":1539}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.weight.regular","line":362}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/font.weight.regular","line":366}}, {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/font.weight.regular","line":2472}} ], "uses": [ @@ -21526,21 +21666,21 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/icon/size/lg", - "line": 482 + "line": 508 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/icon.size.lg","line":345}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/icon.size.lg","line":422}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/icon.size.lg","line":368}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/icon.size.lg","line":368}}, - {"port":"obsidian","reason":"icon.size.lg: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/icon.size.lg","line":697}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/icon.size.lg","line":372}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/icon.size.lg","line":1590}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/icon.size.lg","line":363}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/icon.size.lg","line":2508}} + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/icon.size.lg","line":349}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/icon.size.lg","line":426}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/icon.size.lg","line":372}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/icon.size.lg","line":372}}, + {"port":"obsidian","reason":"icon.size.lg: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/icon.size.lg","line":701}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/icon.size.lg","line":376}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/icon.size.lg","line":1594}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/icon.size.lg","line":367}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/icon.size.lg","line":2512}} ], "uses": [], "contrast": [] @@ -21561,21 +21701,21 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/icon/size/md", - "line": 476 + "line": 502 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/icon.size.md","line":346}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/icon.size.md","line":423}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/icon.size.md","line":369}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/icon.size.md","line":369}}, - {"port":"obsidian","reason":"icon.size.md: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/icon.size.md","line":696}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/icon.size.md","line":373}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/icon.size.md","line":1589}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/icon.size.md","line":364}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/icon.size.md","line":2507}} + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/icon.size.md","line":350}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/icon.size.md","line":427}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/icon.size.md","line":373}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/icon.size.md","line":373}}, + {"port":"obsidian","reason":"icon.size.md: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/icon.size.md","line":700}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/icon.size.md","line":377}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/icon.size.md","line":1593}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/icon.size.md","line":368}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/icon.size.md","line":2511}} ], "uses": [ {"kind":"part","component":"multiselect","part":"dependency.role-icon-size-md","state":null,"variant":null,"surface":null,"nativeKey":null,"port":null,"source":{"file":"spec/components/multiselect.md","pointer":"/tokens/dependency.role-icon-size-md","line":54}}, @@ -21599,21 +21739,21 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/icon/size/sm", - "line": 470 + "line": 496 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/icon.size.sm","line":347}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/icon.size.sm","line":424}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/icon.size.sm","line":370}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/icon.size.sm","line":370}}, - {"port":"obsidian","reason":"icon.size.sm: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/icon.size.sm","line":695}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/icon.size.sm","line":374}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/icon.size.sm","line":1588}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/icon.size.sm","line":365}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/icon.size.sm","line":2506}} + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/icon.size.sm","line":351}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/icon.size.sm","line":428}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/icon.size.sm","line":374}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/icon.size.sm","line":374}}, + {"port":"obsidian","reason":"icon.size.sm: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/icon.size.sm","line":699}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/icon.size.sm","line":378}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/icon.size.sm","line":1592}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/icon.size.sm","line":369}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/icon.size.sm","line":2510}} ], "uses": [], "contrast": [] @@ -21634,21 +21774,21 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/icon/stroke", - "line": 489 + "line": 515 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/icon.stroke","line":348}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/icon.stroke","line":425}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/icon.stroke","line":371}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/icon.stroke","line":371}}, - {"port":"obsidian","reason":"icon.stroke: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/icon.stroke","line":698}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/icon.stroke","line":375}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/icon.stroke","line":1591}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/icon.stroke","line":366}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/icon.stroke","line":2509}} + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/icon.stroke","line":352}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/icon.stroke","line":429}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/icon.stroke","line":375}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/icon.stroke","line":375}}, + {"port":"obsidian","reason":"icon.stroke: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/icon.stroke","line":702}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/icon.stroke","line":379}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/icon.stroke","line":1595}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/icon.stroke","line":370}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/icon.stroke","line":2513}} ], "uses": [], "contrast": [] @@ -21669,21 +21809,21 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/layout/app-max", - "line": 429 + "line": 455 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/layout.app-max","line":349}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/layout.app-max","line":426}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/layout.app-max","line":372}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/layout.app-max","line":372}}, - {"port":"obsidian","reason":"layout.app-max: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/layout.app-max","line":690}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/layout.app-max","line":376}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/layout.app-max","line":1583}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/layout.app-max","line":367}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/layout.app-max","line":2501}} + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/layout.app-max","line":353}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/layout.app-max","line":430}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/layout.app-max","line":376}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/layout.app-max","line":376}}, + {"port":"obsidian","reason":"layout.app-max: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/layout.app-max","line":694}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/layout.app-max","line":380}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/layout.app-max","line":1587}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/layout.app-max","line":371}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/layout.app-max","line":2505}} ], "uses": [], "contrast": [] @@ -21704,20 +21844,20 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/layout/content-max", - "line": 421 + "line": 447 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/layout.content-max","line":350}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/layout.content-max","line":427}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/layout.content-max","line":373}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/layout.content-max","line":373}}, - {"port":"obsidian","reason":"layout.content-max: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/layout.content-max","line":689}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/layout.content-max","line":377}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/layout.content-max","line":1582}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/layout.content-max","line":368}} + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/layout.content-max","line":354}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/layout.content-max","line":431}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/layout.content-max","line":377}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/layout.content-max","line":377}}, + {"port":"obsidian","reason":"layout.content-max: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/layout.content-max","line":693}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/layout.content-max","line":381}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/layout.content-max","line":1586}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/layout.content-max","line":372}} ], "uses": [ {"kind":"port","component":null,"part":null,"state":null,"variant":null,"surface":null,"nativeKey":"powertoys.markdown.CONTENT_MAX","port":"windows","source":{"file":"ports/windows/mapping.json","pointer":"/mappings/layout.content-max/0","line":2131}} @@ -21740,20 +21880,20 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/layout/measure", - "line": 416 + "line": 442 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/layout.measure","line":351}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/layout.measure","line":428}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/layout.measure","line":374}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/layout.measure","line":374}}, - {"port":"obsidian","reason":"layout.measure: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/layout.measure","line":688}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/layout.measure","line":378}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/layout.measure","line":1581}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/layout.measure","line":369}} + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/layout.measure","line":355}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/layout.measure","line":432}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/layout.measure","line":378}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/layout.measure","line":378}}, + {"port":"obsidian","reason":"layout.measure: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/layout.measure","line":692}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/layout.measure","line":382}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/layout.measure","line":1585}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/layout.measure","line":373}} ], "uses": [ {"kind":"port","component":null,"part":null,"state":null,"variant":null,"surface":null,"nativeKey":"powertoys.markdown.MEASURE","port":"windows","source":{"file":"ports/windows/mapping.json","pointer":"/mappings/layout.measure/0","line":2128}} @@ -21776,21 +21916,21 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/motion/duration/base", - "line": 381 + "line": 407 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/motion.duration.base","line":352}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/motion.duration.base","line":429}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/motion.duration.base","line":375}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/motion.duration.base","line":375}}, - {"port":"obsidian","reason":"motion.duration.base: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/motion.duration.base","line":685}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/motion.duration.base","line":379}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/motion.duration.base","line":1578}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/motion.duration.base","line":370}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/motion.duration.base","line":2498}} + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/motion.duration.base","line":356}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/motion.duration.base","line":433}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/motion.duration.base","line":379}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/motion.duration.base","line":379}}, + {"port":"obsidian","reason":"motion.duration.base: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/motion.duration.base","line":689}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/motion.duration.base","line":383}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/motion.duration.base","line":1582}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/motion.duration.base","line":374}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/motion.duration.base","line":2502}} ], "uses": [], "contrast": [] @@ -21811,21 +21951,21 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/motion/duration/fast", - "line": 375 + "line": 401 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/motion.duration.fast","line":353}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/motion.duration.fast","line":430}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/motion.duration.fast","line":376}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/motion.duration.fast","line":376}}, - {"port":"obsidian","reason":"motion.duration.fast: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/motion.duration.fast","line":684}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/motion.duration.fast","line":380}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/motion.duration.fast","line":1577}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/motion.duration.fast","line":371}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/motion.duration.fast","line":2497}} + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/motion.duration.fast","line":357}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/motion.duration.fast","line":434}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/motion.duration.fast","line":380}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/motion.duration.fast","line":380}}, + {"port":"obsidian","reason":"motion.duration.fast: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/motion.duration.fast","line":688}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/motion.duration.fast","line":384}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/motion.duration.fast","line":1581}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/motion.duration.fast","line":375}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/motion.duration.fast","line":2501}} ], "uses": [], "contrast": [] @@ -21846,21 +21986,21 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/motion/duration/slow", - "line": 387 + "line": 413 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/motion.duration.slow","line":354}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/motion.duration.slow","line":431}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/motion.duration.slow","line":377}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/motion.duration.slow","line":377}}, - {"port":"obsidian","reason":"motion.duration.slow: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/motion.duration.slow","line":686}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/motion.duration.slow","line":381}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/motion.duration.slow","line":1579}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/motion.duration.slow","line":372}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/motion.duration.slow","line":2499}} + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/motion.duration.slow","line":358}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/motion.duration.slow","line":435}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/motion.duration.slow","line":381}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/motion.duration.slow","line":381}}, + {"port":"obsidian","reason":"motion.duration.slow: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/motion.duration.slow","line":690}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/motion.duration.slow","line":385}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/motion.duration.slow","line":1583}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/motion.duration.slow","line":376}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/motion.duration.slow","line":2503}} ], "uses": [], "contrast": [] @@ -21887,13 +22027,13 @@ "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"ChatGPT keeps its own geometry; this j3w1 value cannot be set.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/radius.none","line":355}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/radius.none","line":432}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/radius.none","line":378}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/radius.none","line":378}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/radius.none","line":382}}, + {"port":"chatgpt","reason":"ChatGPT keeps its own geometry; this j3w1 value cannot be set.","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/radius.none","line":359}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/radius.none","line":436}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/radius.none","line":382}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/radius.none","line":382}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/radius.none","line":386}}, {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/radius.none","line":1537}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/radius.none","line":373}} + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/radius.none","line":377}} ], "uses": [ {"kind":"part","component":"avatar","part":"dependency.role-radius-none","state":null,"variant":null,"surface":null,"nativeKey":null,"port":null,"source":{"file":"spec/components/avatar.md","pointer":"/tokens/dependency.role-radius-none","line":33}}, @@ -22073,7 +22213,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/shadow/floating", - "line": 398 + "line": 424 }, "provenance": null, "aliases": [ @@ -22082,15 +22222,15 @@ ], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/shadow.floating","line":356}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/shadow.floating","line":433}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/shadow.floating","line":379}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/shadow.floating","line":379}}, - {"port":"obsidian","reason":"shadow.floating: terminal, diff, chart, hued syntax or desktop specimen semantics are outside this Markdown/application port.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/shadow.floating","line":687}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/shadow.floating","line":383}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/shadow.floating","line":1580}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/shadow.floating","line":374}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/shadow.floating","line":2500}} + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/shadow.floating","line":360}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/shadow.floating","line":437}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/shadow.floating","line":383}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/shadow.floating","line":383}}, + {"port":"obsidian","reason":"shadow.floating: terminal, diff, chart, hued syntax or desktop specimen semantics are outside this Markdown/application port.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/shadow.floating","line":691}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/shadow.floating","line":387}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/shadow.floating","line":1584}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/shadow.floating","line":378}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/shadow.floating","line":2504}} ], "uses": [ {"kind":"part","component":"i3-window-frame","part":"floating.shadow","state":null,"variant":"floating","surface":null,"nativeKey":null,"port":null,"source":{"file":"spec/components/i3-window-frame.md","pointer":"/tokens/floating.shadow","line":60}} @@ -22121,14 +22261,14 @@ "shadow.floating" ], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/space.0","line":357}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/space.0","line":434}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/space.0","line":380}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/space.0","line":380}}, + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/space.0","line":361}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/space.0","line":438}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/space.0","line":384}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/space.0","line":384}}, {"port":"obsidian","reason":"space.0: native spacing retained except the explicitly mapped compact prompt padding.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/space.0","line":644}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/space.0","line":384}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/space.0","line":388}}, {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/space.0","line":1525}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/space.0","line":375}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/space.0","line":379}}, {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/space.0","line":2468}} ], "uses": [], @@ -22156,14 +22296,14 @@ "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/space.1","line":358}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/space.1","line":435}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/space.1","line":381}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/space.1","line":381}}, + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/space.1","line":362}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/space.1","line":439}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/space.1","line":385}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/space.1","line":385}}, {"port":"obsidian","reason":"space.1: native spacing retained except the explicitly mapped compact prompt padding.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/space.1","line":645}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/space.1","line":385}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/space.1","line":389}}, {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/space.1","line":1526}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/space.1","line":376}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/space.1","line":380}}, {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/space.1","line":2469}} ], "uses": [], @@ -22191,14 +22331,14 @@ "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/space.12","line":359}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/space.12","line":436}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/space.12","line":382}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/space.12","line":382}}, + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/space.12","line":363}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/space.12","line":440}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/space.12","line":386}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/space.12","line":386}}, {"port":"obsidian","reason":"space.12: native spacing retained except the explicitly mapped compact prompt padding.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/space.12","line":648}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/space.12","line":386}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/space.12","line":390}}, {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/space.12","line":1530}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/space.12","line":377}} + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/space.12","line":381}} ], "uses": [ {"kind":"part","component":"avatar","part":"dependency.role-space-12","state":null,"variant":null,"surface":null,"nativeKey":null,"port":null,"source":{"file":"spec/components/avatar.md","pointer":"/tokens/dependency.role-space-12","line":34}}, @@ -22246,14 +22386,14 @@ "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/space.16","line":360}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/space.16","line":437}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/space.16","line":383}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/space.16","line":383}}, + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/space.16","line":364}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/space.16","line":441}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/space.16","line":387}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/space.16","line":387}}, {"port":"obsidian","reason":"space.16: native spacing retained except the explicitly mapped compact prompt padding.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/space.16","line":649}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/space.16","line":387}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/space.16","line":391}}, {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/space.16","line":1531}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/space.16","line":378}} + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/space.16","line":382}} ], "uses": [ {"kind":"part","component":"command-palette","part":"dependency.role-space-16","state":null,"variant":null,"surface":null,"nativeKey":null,"port":null,"source":{"file":"spec/components/command-palette.md","pointer":"/tokens/dependency.role-space-16","line":46}}, @@ -22288,14 +22428,14 @@ "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/space.2","line":361}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/space.2","line":438}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/space.2","line":384}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/space.2","line":384}}, + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/space.2","line":365}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/space.2","line":442}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/space.2","line":388}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/space.2","line":388}}, {"port":"obsidian","reason":"space.2: native spacing retained except the explicitly mapped compact prompt padding.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/space.2","line":646}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/space.2","line":388}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/space.2","line":392}}, {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/space.2","line":1527}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/space.2","line":379}} + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/space.2","line":383}} ], "uses": [ {"kind":"part","component":"avatar","part":"dependency.role-space-2","state":null,"variant":null,"surface":null,"nativeKey":null,"port":null,"source":{"file":"spec/components/avatar.md","pointer":"/tokens/dependency.role-space-2","line":35}}, @@ -22343,14 +22483,14 @@ "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/space.24","line":362}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/space.24","line":439}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/space.24","line":385}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/space.24","line":385}}, + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/space.24","line":366}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/space.24","line":443}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/space.24","line":389}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/space.24","line":389}}, {"port":"obsidian","reason":"space.24: native spacing retained except the explicitly mapped compact prompt padding.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/space.24","line":650}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/space.24","line":389}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/space.24","line":393}}, {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/space.24","line":1532}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/space.24","line":380}} + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/space.24","line":384}} ], "uses": [ {"kind":"part","component":"multiselect","part":"dependency.role-space-24","state":null,"variant":null,"surface":null,"nativeKey":null,"port":null,"source":{"file":"spec/components/multiselect.md","pointer":"/tokens/dependency.role-space-24","line":58}}, @@ -22382,14 +22522,14 @@ "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/space.32","line":363}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/space.32","line":440}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/space.32","line":386}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/space.32","line":386}}, + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/space.32","line":367}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/space.32","line":444}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/space.32","line":390}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/space.32","line":390}}, {"port":"obsidian","reason":"space.32: native spacing retained except the explicitly mapped compact prompt padding.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/space.32","line":651}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/space.32","line":390}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/space.32","line":394}}, {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/space.32","line":1533}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/space.32","line":381}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/space.32","line":385}}, {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/space.32","line":2470}} ], "uses": [ @@ -22419,13 +22559,13 @@ "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/space.4","line":364}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/space.4","line":441}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/space.4","line":387}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/space.4","line":387}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/space.4","line":391}}, + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/space.4","line":368}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/space.4","line":445}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/space.4","line":391}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/space.4","line":391}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/space.4","line":395}}, {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/space.4","line":1528}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/space.4","line":382}} + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/space.4","line":386}} ], "uses": [ {"kind":"part","component":"button-group","part":"dependency.role-space-4","state":null,"variant":null,"surface":null,"nativeKey":null,"port":null,"source":{"file":"spec/components/button-group.md","pointer":"/tokens/dependency.role-space-4","line":40}}, @@ -22462,14 +22602,14 @@ "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/space.48","line":365}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/space.48","line":442}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/space.48","line":388}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/space.48","line":388}}, + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/space.48","line":369}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/space.48","line":446}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/space.48","line":392}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/space.48","line":392}}, {"port":"obsidian","reason":"space.48: native spacing retained except the explicitly mapped compact prompt padding.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/space.48","line":652}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/space.48","line":392}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/space.48","line":396}}, {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/space.48","line":1534}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/space.48","line":383}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/space.48","line":387}}, {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/space.48","line":2471}} ], "uses": [], @@ -22497,14 +22637,14 @@ "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/space.8","line":366}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/space.8","line":443}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/space.8","line":389}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/space.8","line":389}}, + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/space.8","line":370}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/space.8","line":447}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/space.8","line":393}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/space.8","line":393}}, {"port":"obsidian","reason":"space.8: native spacing retained except the explicitly mapped compact prompt padding.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/space.8","line":647}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/space.8","line":393}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/space.8","line":397}}, {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/space.8","line":1529}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/space.8","line":384}} + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/space.8","line":388}} ], "uses": [ {"kind":"part","component":"button-group","part":"dependency.role-space-8","state":null,"variant":null,"surface":null,"nativeKey":null,"port":null,"source":{"file":"spec/components/button-group.md","pointer":"/tokens/dependency.role-space-8","line":41}}, @@ -22542,21 +22682,21 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/z/canvas", - "line": 500 + "line": 526 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/z.canvas","line":367}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/z.canvas","line":444}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/z.canvas","line":390}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/z.canvas","line":390}}, - {"port":"obsidian","reason":"z.canvas: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/z.canvas","line":699}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/z.canvas","line":394}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/z.canvas","line":1592}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/z.canvas","line":385}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/z.canvas","line":2510}} + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/z.canvas","line":371}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/z.canvas","line":448}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/z.canvas","line":394}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/z.canvas","line":394}}, + {"port":"obsidian","reason":"z.canvas: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/z.canvas","line":703}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/z.canvas","line":398}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/z.canvas","line":1596}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/z.canvas","line":389}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/z.canvas","line":2514}} ], "uses": [], "contrast": [] @@ -22577,21 +22717,21 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/z/dialog", - "line": 512 + "line": 538 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/z.dialog","line":368}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/z.dialog","line":445}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/z.dialog","line":391}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/z.dialog","line":391}}, - {"port":"obsidian","reason":"z.dialog: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/z.dialog","line":703}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/z.dialog","line":395}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/z.dialog","line":1596}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/z.dialog","line":386}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/z.dialog","line":2514}} + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/z.dialog","line":372}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/z.dialog","line":449}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/z.dialog","line":395}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/z.dialog","line":395}}, + {"port":"obsidian","reason":"z.dialog: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/z.dialog","line":707}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/z.dialog","line":399}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/z.dialog","line":1600}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/z.dialog","line":390}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/z.dialog","line":2518}} ], "uses": [ {"kind":"part","component":"dialog","part":"root.z","state":null,"variant":null,"surface":null,"nativeKey":null,"port":null,"source":{"file":"spec/components/dialog.md","pointer":"/tokens/root.z","line":35}} @@ -22614,21 +22754,21 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/z/drawer", - "line": 509 + "line": 535 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/z.drawer","line":369}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/z.drawer","line":446}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/z.drawer","line":392}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/z.drawer","line":392}}, - {"port":"obsidian","reason":"z.drawer: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/z.drawer","line":702}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/z.drawer","line":396}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/z.drawer","line":1595}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/z.drawer","line":387}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/z.drawer","line":2513}} + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/z.drawer","line":373}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/z.drawer","line":450}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/z.drawer","line":396}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/z.drawer","line":396}}, + {"port":"obsidian","reason":"z.drawer: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/z.drawer","line":706}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/z.drawer","line":400}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/z.drawer","line":1599}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/z.drawer","line":391}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/z.drawer","line":2517}} ], "uses": [ {"kind":"part","component":"drawer","part":"root.z","state":null,"variant":null,"surface":null,"nativeKey":null,"port":null,"source":{"file":"spec/components/drawer.md","pointer":"/tokens/root.z","line":31}} @@ -22651,21 +22791,21 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/z/popover", - "line": 506 + "line": 532 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/z.popover","line":370}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/z.popover","line":447}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/z.popover","line":393}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/z.popover","line":393}}, - {"port":"obsidian","reason":"z.popover: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/z.popover","line":701}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/z.popover","line":397}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/z.popover","line":1594}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/z.popover","line":388}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/z.popover","line":2512}} + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/z.popover","line":374}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/z.popover","line":451}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/z.popover","line":397}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/z.popover","line":397}}, + {"port":"obsidian","reason":"z.popover: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/z.popover","line":705}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/z.popover","line":401}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/z.popover","line":1598}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/z.popover","line":392}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/z.popover","line":2516}} ], "uses": [ {"kind":"part","component":"tooltip","part":"popup.z","state":null,"variant":null,"surface":null,"nativeKey":null,"port":null,"source":{"file":"spec/components/tooltip.md","pointer":"/tokens/popup.z","line":36}} @@ -22688,21 +22828,21 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/z/raised", - "line": 503 + "line": 529 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/z.raised","line":371}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/z.raised","line":448}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/z.raised","line":394}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/z.raised","line":394}}, - {"port":"obsidian","reason":"z.raised: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/z.raised","line":700}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/z.raised","line":398}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/z.raised","line":1593}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/z.raised","line":389}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/z.raised","line":2511}} + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/z.raised","line":375}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/z.raised","line":452}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/z.raised","line":398}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/z.raised","line":398}}, + {"port":"obsidian","reason":"z.raised: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/z.raised","line":704}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/z.raised","line":402}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/z.raised","line":1597}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/z.raised","line":393}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/z.raised","line":2515}} ], "uses": [], "contrast": [] @@ -22723,21 +22863,21 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/z/skip-link", - "line": 518 + "line": 544 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/z.skip-link","line":372}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/z.skip-link","line":449}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/z.skip-link","line":395}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/z.skip-link","line":395}}, - {"port":"obsidian","reason":"z.skip-link: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/z.skip-link","line":705}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/z.skip-link","line":399}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/z.skip-link","line":1598}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/z.skip-link","line":390}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/z.skip-link","line":2516}} + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/z.skip-link","line":376}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/z.skip-link","line":453}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/z.skip-link","line":399}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/z.skip-link","line":399}}, + {"port":"obsidian","reason":"z.skip-link: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/z.skip-link","line":709}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/z.skip-link","line":403}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/z.skip-link","line":1602}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/z.skip-link","line":394}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/z.skip-link","line":2520}} ], "uses": [], "contrast": [] @@ -22758,21 +22898,21 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/z/toast", - "line": 515 + "line": 541 }, "provenance": null, "aliases": [], "usedByAliases": [], "unmappedPorts": [ - {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/z.toast","line":373}}, - {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/z.toast","line":450}}, - {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/z.toast","line":396}}, - {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/z.toast","line":396}}, - {"port":"obsidian","reason":"z.toast: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/z.toast","line":704}}, - {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/z.toast","line":400}}, - {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/z.toast","line":1597}}, - {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/z.toast","line":391}}, - {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/z.toast","line":2515}} + {"port":"chatgpt","reason":"Not an appearance setting ChatGPT exposes (geometry, spacing, motion, layout or breakpoints).","source":{"file":"ports/chatgpt/mapping.json","pointer":"/unmapped/z.toast","line":377}}, + {"port":"claude-code","reason":"Not a colour; a Claude Code theme carries colours only.","source":{"file":"ports/claude-code/mapping.json","pointer":"/unmapped/z.toast","line":454}}, + {"port":"codex","reason":"Not a colour; a tmTheme carries colours only.","source":{"file":"ports/codex/mapping.json","pointer":"/unmapped/z.toast","line":400}}, + {"port":"ghostty","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/ghostty/mapping.json","pointer":"/unmapped/z.toast","line":400}}, + {"port":"obsidian","reason":"z.toast: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.","source":{"file":"ports/obsidian/mapping.json","pointer":"/unmapped/z.toast","line":708}}, + {"port":"orca","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/orca/mapping.json","pointer":"/unmapped/z.toast","line":404}}, + {"port":"telegram","reason":"Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.","source":{"file":"ports/telegram/mapping.json","pointer":"/unmapped/z.toast","line":1601}}, + {"port":"warp","reason":"Not a colour; a terminal theme file carries colours only.","source":{"file":"ports/warp/mapping.json","pointer":"/unmapped/z.toast","line":395}}, + {"port":"windows","reason":"Outside Windows visual adapter scope; preserve host semantics.","source":{"file":"ports/windows/mapping.json","pointer":"/unmapped/z.toast","line":2519}} ], "uses": [ {"kind":"part","component":"toast","part":"stack.z","state":null,"variant":null,"surface":null,"nativeKey":null,"port":null,"source":{"file":"spec/components/toast.md","pointer":"/tokens/stack.z","line":55}} @@ -22884,7 +23024,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/breakpoint/lg", - "line": 459 + "line": 485 }, "provenance": null, "aliases": [], @@ -22909,7 +23049,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/breakpoint/md", - "line": 453 + "line": 479 }, "provenance": null, "aliases": [], @@ -22934,7 +23074,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/breakpoint/sm", - "line": 447 + "line": 473 }, "provenance": null, "aliases": [], @@ -22959,7 +23099,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/breakpoint/xs", - "line": 440 + "line": 466 }, "provenance": null, "aliases": [], @@ -36763,7 +36903,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/comfortable/control-height", - "line": 295 + "line": 321 }, "provenance": null, "aliases": [], @@ -36802,7 +36942,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/comfortable/control-padding-x", - "line": 307 + "line": 333 }, "provenance": null, "aliases": [], @@ -36827,7 +36967,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/comfortable/gap", - "line": 319 + "line": 345 }, "provenance": null, "aliases": [], @@ -36852,7 +36992,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/comfortable/icon", - "line": 313 + "line": 339 }, "provenance": null, "aliases": [], @@ -36877,7 +37017,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/comfortable/row-height", - "line": 301 + "line": 327 }, "provenance": null, "aliases": [], @@ -36902,7 +37042,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/compact/control-height", - "line": 263 + "line": 289 }, "provenance": null, "aliases": [], @@ -36941,7 +37081,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/compact/control-padding-x", - "line": 275 + "line": 301 }, "provenance": null, "aliases": [], @@ -36966,7 +37106,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/compact/gap", - "line": 287 + "line": 313 }, "provenance": null, "aliases": [], @@ -36991,7 +37131,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/compact/icon", - "line": 281 + "line": 307 }, "provenance": null, "aliases": [], @@ -37016,7 +37156,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/compact/row-height", - "line": 269 + "line": 295 }, "provenance": null, "aliases": [], @@ -37041,7 +37181,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/focus/offset", - "line": 347 + "line": 373 }, "provenance": null, "aliases": [], @@ -37069,7 +37209,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/focus/offset-container", - "line": 355 + "line": 381 }, "provenance": null, "aliases": [], @@ -37094,7 +37234,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/focus/offset-invalid", - "line": 363 + "line": 389 }, "provenance": null, "aliases": [], @@ -37119,7 +37259,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/focus/ring", - "line": 329 + "line": 355 }, "provenance": null, "aliases": [ @@ -37150,7 +37290,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/focus/ring-container", - "line": 338 + "line": 364 }, "provenance": null, "aliases": [ @@ -37203,7 +37343,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/letter-spacing/terminal", - "line": 250 + "line": 276 }, "provenance": null, "aliases": [], @@ -37228,7 +37368,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/caption", - "line": 241 + "line": 267 }, "provenance": null, "aliases": [], @@ -37253,7 +37393,32 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/code", - "line": 211 + "line": 225 + }, + "provenance": null, + "aliases": [], + "usedByAliases": [], + "unmappedPorts": [], + "uses": [], + "contrast": [] + }, + "font.line-height.display": { + "path": "font.line-height.display", + "group": "font", + "css": "40px", + "variable": "--font-line-height-display", + "description": null, + "status": "observed", + "deprecated": false, + "eligibility": { + "action": "historical-only", + "reason": "Historical fidelity only; preserve all documented limitations and deprecations.", + "decisionIds": [] + }, + "source": { + "file": "tokens/foundations.tokens.json", + "pointer": "/font/line-height/display", + "line": 237 }, "provenance": null, "aliases": [], @@ -37278,7 +37443,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/h1", - "line": 223 + "line": 249 }, "provenance": null, "aliases": [], @@ -37303,7 +37468,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/h2", - "line": 229 + "line": 255 }, "provenance": null, "aliases": [], @@ -37328,7 +37493,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/h3", - "line": 235 + "line": 261 }, "provenance": null, "aliases": [], @@ -37353,7 +37518,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/reading", - "line": 205 + "line": 219 }, "provenance": null, "aliases": [], @@ -37378,7 +37543,32 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/terminal", - "line": 217 + "line": 231 + }, + "provenance": null, + "aliases": [], + "usedByAliases": [], + "unmappedPorts": [], + "uses": [], + "contrast": [] + }, + "font.line-height.title": { + "path": "font.line-height.title", + "group": "font", + "css": "32px", + "variable": "--font-line-height-title", + "description": null, + "status": "observed", + "deprecated": false, + "eligibility": { + "action": "historical-only", + "reason": "Historical fidelity only; preserve all documented limitations and deprecations.", + "decisionIds": [] + }, + "source": { + "file": "tokens/foundations.tokens.json", + "pointer": "/font/line-height/title", + "line": 243 }, "provenance": null, "aliases": [], @@ -37403,7 +37593,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/ui-lg", - "line": 199 + "line": 213 }, "provenance": null, "aliases": [], @@ -37428,7 +37618,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/ui-md", - "line": 193 + "line": 207 }, "provenance": null, "aliases": [], @@ -37456,7 +37646,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/ui-sm", - "line": 187 + "line": 201 }, "provenance": null, "aliases": [], @@ -37484,7 +37674,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/size/caption", - "line": 177 + "line": 191 }, "provenance": null, "aliases": [], @@ -37518,6 +37708,31 @@ "uses": [], "contrast": [] }, + "font.size.display": { + "path": "font.size.display", + "group": "font", + "css": "32px", + "variable": "--font-size-display", + "description": "Page heroes and metric figures on the portal (D-037).", + "status": "observed", + "deprecated": false, + "eligibility": { + "action": "historical-only", + "reason": "Historical fidelity only; preserve all documented limitations and deprecations.", + "decisionIds": [] + }, + "source": { + "file": "tokens/foundations.tokens.json", + "pointer": "/font/size/display", + "line": 159 + }, + "provenance": null, + "aliases": [], + "usedByAliases": [], + "unmappedPorts": [], + "uses": [], + "contrast": [] + }, "font.size.h1": { "path": "font.size.h1", "group": "font", @@ -37534,7 +37749,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/size/h1", - "line": 159 + "line": 173 }, "provenance": null, "aliases": [], @@ -37559,7 +37774,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/size/h2", - "line": 165 + "line": 179 }, "provenance": null, "aliases": [], @@ -37586,7 +37801,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/size/h3", - "line": 171 + "line": 185 }, "provenance": null, "aliases": [], @@ -37645,6 +37860,31 @@ "uses": [], "contrast": [] }, + "font.size.title": { + "path": "font.size.title", + "group": "font", + "css": "24px", + "variable": "--font-size-title", + "description": "Page titles above h1 on the portal (D-037).", + "status": "observed", + "deprecated": false, + "eligibility": { + "action": "historical-only", + "reason": "Historical fidelity only; preserve all documented limitations and deprecations.", + "decisionIds": [] + }, + "source": { + "file": "tokens/foundations.tokens.json", + "pointer": "/font/size/title", + "line": 166 + }, + "provenance": null, + "aliases": [], + "usedByAliases": [], + "unmappedPorts": [], + "uses": [], + "contrast": [] + }, "font.size.ui-lg": { "path": "font.size.ui-lg", "group": "font", @@ -37794,7 +38034,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/icon/size/lg", - "line": 482 + "line": 508 }, "provenance": null, "aliases": [], @@ -37819,7 +38059,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/icon/size/md", - "line": 476 + "line": 502 }, "provenance": null, "aliases": [], @@ -37847,7 +38087,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/icon/size/sm", - "line": 470 + "line": 496 }, "provenance": null, "aliases": [], @@ -37872,7 +38112,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/icon/stroke", - "line": 489 + "line": 515 }, "provenance": null, "aliases": [], @@ -37897,7 +38137,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/layout/app-max", - "line": 429 + "line": 455 }, "provenance": null, "aliases": [], @@ -37922,7 +38162,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/layout/content-max", - "line": 421 + "line": 447 }, "provenance": null, "aliases": [], @@ -37947,7 +38187,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/layout/measure", - "line": 416 + "line": 442 }, "provenance": null, "aliases": [], @@ -37972,7 +38212,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/motion/duration/base", - "line": 381 + "line": 407 }, "provenance": null, "aliases": [], @@ -37997,7 +38237,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/motion/duration/fast", - "line": 375 + "line": 401 }, "provenance": null, "aliases": [], @@ -38022,7 +38262,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/motion/duration/slow", - "line": 387 + "line": 413 }, "provenance": null, "aliases": [], @@ -38092,7 +38332,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/shadow/floating", - "line": 398 + "line": 424 }, "provenance": null, "aliases": [ @@ -38450,7 +38690,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/z/canvas", - "line": 500 + "line": 526 }, "provenance": null, "aliases": [], @@ -38475,7 +38715,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/z/dialog", - "line": 512 + "line": 538 }, "provenance": null, "aliases": [], @@ -38502,7 +38742,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/z/drawer", - "line": 509 + "line": 535 }, "provenance": null, "aliases": [], @@ -38529,7 +38769,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/z/popover", - "line": 506 + "line": 532 }, "provenance": null, "aliases": [], @@ -38556,7 +38796,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/z/raised", - "line": 503 + "line": 529 }, "provenance": null, "aliases": [], @@ -38581,7 +38821,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/z/skip-link", - "line": 518 + "line": 544 }, "provenance": null, "aliases": [], @@ -38606,7 +38846,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/z/toast", - "line": 515 + "line": 541 }, "provenance": null, "aliases": [], @@ -38722,7 +38962,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/breakpoint/lg", - "line": 459 + "line": 485 }, "provenance": null, "aliases": [], @@ -38747,7 +38987,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/breakpoint/md", - "line": 453 + "line": 479 }, "provenance": null, "aliases": [], @@ -38772,7 +39012,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/breakpoint/sm", - "line": 447 + "line": 473 }, "provenance": null, "aliases": [], @@ -38797,7 +39037,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/breakpoint/xs", - "line": 440 + "line": 466 }, "provenance": null, "aliases": [], @@ -52784,7 +53024,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/comfortable/control-height", - "line": 295 + "line": 321 }, "provenance": null, "aliases": [], @@ -52823,7 +53063,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/comfortable/control-padding-x", - "line": 307 + "line": 333 }, "provenance": null, "aliases": [], @@ -52848,7 +53088,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/comfortable/gap", - "line": 319 + "line": 345 }, "provenance": null, "aliases": [], @@ -52873,7 +53113,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/comfortable/icon", - "line": 313 + "line": 339 }, "provenance": null, "aliases": [], @@ -52898,7 +53138,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/comfortable/row-height", - "line": 301 + "line": 327 }, "provenance": null, "aliases": [], @@ -52923,7 +53163,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/compact/control-height", - "line": 263 + "line": 289 }, "provenance": null, "aliases": [], @@ -52962,7 +53202,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/compact/control-padding-x", - "line": 275 + "line": 301 }, "provenance": null, "aliases": [], @@ -52987,7 +53227,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/compact/gap", - "line": 287 + "line": 313 }, "provenance": null, "aliases": [], @@ -53012,7 +53252,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/compact/icon", - "line": 281 + "line": 307 }, "provenance": null, "aliases": [], @@ -53037,7 +53277,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/density/compact/row-height", - "line": 269 + "line": 295 }, "provenance": null, "aliases": [], @@ -53062,7 +53302,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/focus/offset", - "line": 347 + "line": 373 }, "provenance": null, "aliases": [], @@ -53090,7 +53330,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/focus/offset-container", - "line": 355 + "line": 381 }, "provenance": null, "aliases": [], @@ -53115,7 +53355,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/focus/offset-invalid", - "line": 363 + "line": 389 }, "provenance": null, "aliases": [], @@ -53140,7 +53380,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/focus/ring", - "line": 329 + "line": 355 }, "provenance": null, "aliases": [ @@ -53171,7 +53411,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/focus/ring-container", - "line": 338 + "line": 364 }, "provenance": null, "aliases": [ @@ -53224,7 +53464,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/letter-spacing/terminal", - "line": 250 + "line": 276 }, "provenance": null, "aliases": [], @@ -53249,7 +53489,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/caption", - "line": 241 + "line": 267 }, "provenance": null, "aliases": [], @@ -53274,7 +53514,32 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/code", - "line": 211 + "line": 225 + }, + "provenance": null, + "aliases": [], + "usedByAliases": [], + "unmappedPorts": [], + "uses": [], + "contrast": [] + }, + "font.line-height.display": { + "path": "font.line-height.display", + "group": "font", + "css": "40px", + "variable": "--font-line-height-display", + "description": null, + "status": "observed", + "deprecated": false, + "eligibility": { + "action": "blocked", + "reason": "Proposed profile: preview only, not downstream delivery.", + "decisionIds": [] + }, + "source": { + "file": "tokens/foundations.tokens.json", + "pointer": "/font/line-height/display", + "line": 237 }, "provenance": null, "aliases": [], @@ -53299,7 +53564,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/h1", - "line": 223 + "line": 249 }, "provenance": null, "aliases": [], @@ -53324,7 +53589,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/h2", - "line": 229 + "line": 255 }, "provenance": null, "aliases": [], @@ -53349,7 +53614,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/h3", - "line": 235 + "line": 261 }, "provenance": null, "aliases": [], @@ -53374,7 +53639,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/reading", - "line": 205 + "line": 219 }, "provenance": null, "aliases": [], @@ -53399,7 +53664,32 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/terminal", - "line": 217 + "line": 231 + }, + "provenance": null, + "aliases": [], + "usedByAliases": [], + "unmappedPorts": [], + "uses": [], + "contrast": [] + }, + "font.line-height.title": { + "path": "font.line-height.title", + "group": "font", + "css": "32px", + "variable": "--font-line-height-title", + "description": null, + "status": "observed", + "deprecated": false, + "eligibility": { + "action": "blocked", + "reason": "Proposed profile: preview only, not downstream delivery.", + "decisionIds": [] + }, + "source": { + "file": "tokens/foundations.tokens.json", + "pointer": "/font/line-height/title", + "line": 243 }, "provenance": null, "aliases": [], @@ -53424,7 +53714,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/ui-lg", - "line": 199 + "line": 213 }, "provenance": null, "aliases": [], @@ -53449,7 +53739,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/ui-md", - "line": 193 + "line": 207 }, "provenance": null, "aliases": [], @@ -53477,7 +53767,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/line-height/ui-sm", - "line": 187 + "line": 201 }, "provenance": null, "aliases": [], @@ -53505,7 +53795,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/size/caption", - "line": 177 + "line": 191 }, "provenance": null, "aliases": [], @@ -53539,6 +53829,31 @@ "uses": [], "contrast": [] }, + "font.size.display": { + "path": "font.size.display", + "group": "font", + "css": "32px", + "variable": "--font-size-display", + "description": "Page heroes and metric figures on the portal (D-037).", + "status": "observed", + "deprecated": false, + "eligibility": { + "action": "blocked", + "reason": "Proposed profile: preview only, not downstream delivery.", + "decisionIds": [] + }, + "source": { + "file": "tokens/foundations.tokens.json", + "pointer": "/font/size/display", + "line": 159 + }, + "provenance": null, + "aliases": [], + "usedByAliases": [], + "unmappedPorts": [], + "uses": [], + "contrast": [] + }, "font.size.h1": { "path": "font.size.h1", "group": "font", @@ -53555,7 +53870,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/size/h1", - "line": 159 + "line": 173 }, "provenance": null, "aliases": [], @@ -53580,7 +53895,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/size/h2", - "line": 165 + "line": 179 }, "provenance": null, "aliases": [], @@ -53607,7 +53922,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/font/size/h3", - "line": 171 + "line": 185 }, "provenance": null, "aliases": [], @@ -53666,6 +53981,31 @@ "uses": [], "contrast": [] }, + "font.size.title": { + "path": "font.size.title", + "group": "font", + "css": "24px", + "variable": "--font-size-title", + "description": "Page titles above h1 on the portal (D-037).", + "status": "observed", + "deprecated": false, + "eligibility": { + "action": "blocked", + "reason": "Proposed profile: preview only, not downstream delivery.", + "decisionIds": [] + }, + "source": { + "file": "tokens/foundations.tokens.json", + "pointer": "/font/size/title", + "line": 166 + }, + "provenance": null, + "aliases": [], + "usedByAliases": [], + "unmappedPorts": [], + "uses": [], + "contrast": [] + }, "font.size.ui-lg": { "path": "font.size.ui-lg", "group": "font", @@ -53815,7 +54155,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/icon/size/lg", - "line": 482 + "line": 508 }, "provenance": null, "aliases": [], @@ -53840,7 +54180,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/icon/size/md", - "line": 476 + "line": 502 }, "provenance": null, "aliases": [], @@ -53868,7 +54208,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/icon/size/sm", - "line": 470 + "line": 496 }, "provenance": null, "aliases": [], @@ -53893,7 +54233,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/icon/stroke", - "line": 489 + "line": 515 }, "provenance": null, "aliases": [], @@ -53918,7 +54258,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/layout/app-max", - "line": 429 + "line": 455 }, "provenance": null, "aliases": [], @@ -53943,7 +54283,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/layout/content-max", - "line": 421 + "line": 447 }, "provenance": null, "aliases": [], @@ -53968,7 +54308,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/layout/measure", - "line": 416 + "line": 442 }, "provenance": null, "aliases": [], @@ -53993,7 +54333,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/motion/duration/base", - "line": 381 + "line": 407 }, "provenance": null, "aliases": [], @@ -54018,7 +54358,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/motion/duration/fast", - "line": 375 + "line": 401 }, "provenance": null, "aliases": [], @@ -54043,7 +54383,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/motion/duration/slow", - "line": 387 + "line": 413 }, "provenance": null, "aliases": [], @@ -54113,7 +54453,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/shadow/floating", - "line": 398 + "line": 424 }, "provenance": null, "aliases": [ @@ -54471,7 +54811,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/z/canvas", - "line": 500 + "line": 526 }, "provenance": null, "aliases": [], @@ -54496,7 +54836,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/z/dialog", - "line": 512 + "line": 538 }, "provenance": null, "aliases": [], @@ -54523,7 +54863,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/z/drawer", - "line": 509 + "line": 535 }, "provenance": null, "aliases": [], @@ -54550,7 +54890,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/z/popover", - "line": 506 + "line": 532 }, "provenance": null, "aliases": [], @@ -54577,7 +54917,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/z/raised", - "line": 503 + "line": 529 }, "provenance": null, "aliases": [], @@ -54602,7 +54942,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/z/skip-link", - "line": 518 + "line": 544 }, "provenance": null, "aliases": [], @@ -54627,7 +54967,7 @@ "source": { "file": "tokens/foundations.tokens.json", "pointer": "/z/toast", - "line": 515 + "line": 541 }, "provenance": null, "aliases": [], diff --git a/exports/tokens.css b/exports/tokens.css index 0d0600c1b..c42ff00ae 100644 --- a/exports/tokens.css +++ b/exports/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/exports/tokens.resolved.json b/exports/tokens.resolved.json index 0c68c73b6..8b6a1052f 100644 --- a/exports/tokens.resolved.json +++ b/exports/tokens.resolved.json @@ -7090,6 +7090,42 @@ "decisionIds": [] } }, + "font.size.display": { + "type": "dimension", + "value": { + "value": 32, + "unit": "px" + }, + "css": "32px", + "aliasOf": null, + "description": "Page heroes and metric figures on the portal (D-037).", + "status": "observed", + "deprecated": false, + "decisionId": null, + "eligibility": { + "action": "use", + "reason": "Use within the role's documented scope and restrictions.", + "decisionIds": [] + } + }, + "font.size.title": { + "type": "dimension", + "value": { + "value": 24, + "unit": "px" + }, + "css": "24px", + "aliasOf": null, + "description": "Page titles above h1 on the portal (D-037).", + "status": "observed", + "deprecated": false, + "decisionId": null, + "eligibility": { + "action": "use", + "reason": "Use within the role's documented scope and restrictions.", + "decisionIds": [] + } + }, "font.size.h1": { "type": "dimension", "value": { @@ -7270,6 +7306,42 @@ "decisionIds": [] } }, + "font.line-height.display": { + "type": "dimension", + "value": { + "value": 40, + "unit": "px" + }, + "css": "40px", + "aliasOf": null, + "description": null, + "status": "observed", + "deprecated": false, + "decisionId": null, + "eligibility": { + "action": "use", + "reason": "Use within the role's documented scope and restrictions.", + "decisionIds": [] + } + }, + "font.line-height.title": { + "type": "dimension", + "value": { + "value": 32, + "unit": "px" + }, + "css": "32px", + "aliasOf": null, + "description": null, + "status": "observed", + "deprecated": false, + "decisionId": null, + "eligibility": { + "action": "use", + "reason": "Use within the role's documented scope and restrictions.", + "decisionIds": [] + } + }, "font.line-height.h1": { "type": "dimension", "value": { @@ -15132,6 +15204,42 @@ "decisionIds": [] } }, + "font.size.display": { + "type": "dimension", + "value": { + "value": 32, + "unit": "px" + }, + "css": "32px", + "aliasOf": null, + "description": "Page heroes and metric figures on the portal (D-037).", + "status": "observed", + "deprecated": false, + "decisionId": null, + "eligibility": { + "action": "historical-only", + "reason": "Historical fidelity only; preserve all documented limitations and deprecations.", + "decisionIds": [] + } + }, + "font.size.title": { + "type": "dimension", + "value": { + "value": 24, + "unit": "px" + }, + "css": "24px", + "aliasOf": null, + "description": "Page titles above h1 on the portal (D-037).", + "status": "observed", + "deprecated": false, + "decisionId": null, + "eligibility": { + "action": "historical-only", + "reason": "Historical fidelity only; preserve all documented limitations and deprecations.", + "decisionIds": [] + } + }, "font.size.h1": { "type": "dimension", "value": { @@ -15312,6 +15420,42 @@ "decisionIds": [] } }, + "font.line-height.display": { + "type": "dimension", + "value": { + "value": 40, + "unit": "px" + }, + "css": "40px", + "aliasOf": null, + "description": null, + "status": "observed", + "deprecated": false, + "decisionId": null, + "eligibility": { + "action": "historical-only", + "reason": "Historical fidelity only; preserve all documented limitations and deprecations.", + "decisionIds": [] + } + }, + "font.line-height.title": { + "type": "dimension", + "value": { + "value": 32, + "unit": "px" + }, + "css": "32px", + "aliasOf": null, + "description": null, + "status": "observed", + "deprecated": false, + "decisionId": null, + "eligibility": { + "action": "historical-only", + "reason": "Historical fidelity only; preserve all documented limitations and deprecations.", + "decisionIds": [] + } + }, "font.line-height.h1": { "type": "dimension", "value": { @@ -23234,6 +23378,42 @@ "decisionIds": [] } }, + "font.size.display": { + "type": "dimension", + "value": { + "value": 32, + "unit": "px" + }, + "css": "32px", + "aliasOf": null, + "description": "Page heroes and metric figures on the portal (D-037).", + "status": "observed", + "deprecated": false, + "decisionId": null, + "eligibility": { + "action": "blocked", + "reason": "Proposed profile: preview only, not downstream delivery.", + "decisionIds": [] + } + }, + "font.size.title": { + "type": "dimension", + "value": { + "value": 24, + "unit": "px" + }, + "css": "24px", + "aliasOf": null, + "description": "Page titles above h1 on the portal (D-037).", + "status": "observed", + "deprecated": false, + "decisionId": null, + "eligibility": { + "action": "blocked", + "reason": "Proposed profile: preview only, not downstream delivery.", + "decisionIds": [] + } + }, "font.size.h1": { "type": "dimension", "value": { @@ -23414,6 +23594,42 @@ "decisionIds": [] } }, + "font.line-height.display": { + "type": "dimension", + "value": { + "value": 40, + "unit": "px" + }, + "css": "40px", + "aliasOf": null, + "description": null, + "status": "observed", + "deprecated": false, + "decisionId": null, + "eligibility": { + "action": "blocked", + "reason": "Proposed profile: preview only, not downstream delivery.", + "decisionIds": [] + } + }, + "font.line-height.title": { + "type": "dimension", + "value": { + "value": 32, + "unit": "px" + }, + "css": "32px", + "aliasOf": null, + "description": null, + "status": "observed", + "deprecated": false, + "decisionId": null, + "eligibility": { + "action": "blocked", + "reason": "Proposed profile: preview only, not downstream delivery.", + "decisionIds": [] + } + }, "font.line-height.h1": { "type": "dimension", "value": { diff --git a/packages/ui/dist/canonical/admin-form.json b/packages/ui/dist/canonical/admin-form.json index 2a405a80e..d9c2f0098 100644 --- a/packages/ui/dist/canonical/admin-form.json +++ b/packages/ui/dist/canonical/admin-form.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "admin-form", "family": "composed", "maturity": "stable", diff --git a/packages/ui/dist/canonical/alert.json b/packages/ui/dist/canonical/alert.json index 734c00f1d..b89f74eb8 100644 --- a/packages/ui/dist/canonical/alert.json +++ b/packages/ui/dist/canonical/alert.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "alert", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/avatar.json b/packages/ui/dist/canonical/avatar.json index 4ad490b36..b87bc4ba6 100644 --- a/packages/ui/dist/canonical/avatar.json +++ b/packages/ui/dist/canonical/avatar.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "avatar", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/badge.json b/packages/ui/dist/canonical/badge.json index 76242649a..e8fb3f1d9 100644 --- a/packages/ui/dist/canonical/badge.json +++ b/packages/ui/dist/canonical/badge.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "badge", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/breadcrumbs.json b/packages/ui/dist/canonical/breadcrumbs.json index d8c3b7b70..4ad9f0157 100644 --- a/packages/ui/dist/canonical/breadcrumbs.json +++ b/packages/ui/dist/canonical/breadcrumbs.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "breadcrumbs", "family": "navigation", "maturity": "stable", diff --git a/packages/ui/dist/canonical/button-group.json b/packages/ui/dist/canonical/button-group.json index 0528fea7b..c9ff24fe3 100644 --- a/packages/ui/dist/canonical/button-group.json +++ b/packages/ui/dist/canonical/button-group.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "button-group", "family": "actions", "maturity": "stable", diff --git a/packages/ui/dist/canonical/button.json b/packages/ui/dist/canonical/button.json index 7dfe1b679..09365a973 100644 --- a/packages/ui/dist/canonical/button.json +++ b/packages/ui/dist/canonical/button.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "button", "family": "actions", "maturity": "stable", diff --git a/packages/ui/dist/canonical/card.json b/packages/ui/dist/canonical/card.json index 9609b314d..32e6c7b3b 100644 --- a/packages/ui/dist/canonical/card.json +++ b/packages/ui/dist/canonical/card.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "card", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/chart.json b/packages/ui/dist/canonical/chart.json index d1b842613..c9589d641 100644 --- a/packages/ui/dist/canonical/chart.json +++ b/packages/ui/dist/canonical/chart.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "chart", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/checkbox.json b/packages/ui/dist/canonical/checkbox.json index 85a51bebb..062776314 100644 --- a/packages/ui/dist/canonical/checkbox.json +++ b/packages/ui/dist/canonical/checkbox.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "checkbox", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/chip.json b/packages/ui/dist/canonical/chip.json index 9bcff6220..e3455073c 100644 --- a/packages/ui/dist/canonical/chip.json +++ b/packages/ui/dist/canonical/chip.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "chip", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/code-editor.json b/packages/ui/dist/canonical/code-editor.json index 42dfd20e2..e9dfeed82 100644 --- a/packages/ui/dist/canonical/code-editor.json +++ b/packages/ui/dist/canonical/code-editor.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "code-editor", "family": "developer", "maturity": "stable", diff --git a/packages/ui/dist/canonical/combobox.json b/packages/ui/dist/canonical/combobox.json index 500aa3312..853b48f08 100644 --- a/packages/ui/dist/canonical/combobox.json +++ b/packages/ui/dist/canonical/combobox.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "combobox", "family": "forms-advanced", "maturity": "stable", diff --git a/packages/ui/dist/canonical/command-palette.json b/packages/ui/dist/canonical/command-palette.json index df74f683e..43037bcb9 100644 --- a/packages/ui/dist/canonical/command-palette.json +++ b/packages/ui/dist/canonical/command-palette.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "command-palette", "family": "navigation", "maturity": "stable", diff --git a/packages/ui/dist/canonical/compact-dashboard.json b/packages/ui/dist/canonical/compact-dashboard.json index 0d40b822a..a4a93d2d4 100644 --- a/packages/ui/dist/canonical/compact-dashboard.json +++ b/packages/ui/dist/canonical/compact-dashboard.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "compact-dashboard", "family": "composed", "maturity": "stable", diff --git a/packages/ui/dist/canonical/data-table.json b/packages/ui/dist/canonical/data-table.json index 9624af95a..cfb7375ef 100644 --- a/packages/ui/dist/canonical/data-table.json +++ b/packages/ui/dist/canonical/data-table.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "data-table", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/date-picker.json b/packages/ui/dist/canonical/date-picker.json index 6cc8aa696..66f885ab6 100644 --- a/packages/ui/dist/canonical/date-picker.json +++ b/packages/ui/dist/canonical/date-picker.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "date-picker", "family": "forms-advanced", "maturity": "stable", diff --git a/packages/ui/dist/canonical/description-list.json b/packages/ui/dist/canonical/description-list.json index ccc501ae9..3cfa86b3f 100644 --- a/packages/ui/dist/canonical/description-list.json +++ b/packages/ui/dist/canonical/description-list.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "description-list", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/diagnostics.json b/packages/ui/dist/canonical/diagnostics.json index 1d594ef38..ad8d2b2a6 100644 --- a/packages/ui/dist/canonical/diagnostics.json +++ b/packages/ui/dist/canonical/diagnostics.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "diagnostics", "family": "developer", "maturity": "stable", diff --git a/packages/ui/dist/canonical/dialog.json b/packages/ui/dist/canonical/dialog.json index e6f229c3e..e08cffa9e 100644 --- a/packages/ui/dist/canonical/dialog.json +++ b/packages/ui/dist/canonical/dialog.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "dialog", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/diff-view.json b/packages/ui/dist/canonical/diff-view.json index fd541c692..b6b685ce3 100644 --- a/packages/ui/dist/canonical/diff-view.json +++ b/packages/ui/dist/canonical/diff-view.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "diff-view", "family": "developer", "maturity": "stable", diff --git a/packages/ui/dist/canonical/disclosure.json b/packages/ui/dist/canonical/disclosure.json index f1675afc8..b283693d6 100644 --- a/packages/ui/dist/canonical/disclosure.json +++ b/packages/ui/dist/canonical/disclosure.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "disclosure", "family": "navigation", "maturity": "stable", diff --git a/packages/ui/dist/canonical/drawer.json b/packages/ui/dist/canonical/drawer.json index 1dce4cf16..2da96c96d 100644 --- a/packages/ui/dist/canonical/drawer.json +++ b/packages/ui/dist/canonical/drawer.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "drawer", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/editor-search.json b/packages/ui/dist/canonical/editor-search.json index da485e0ae..c20a77318 100644 --- a/packages/ui/dist/canonical/editor-search.json +++ b/packages/ui/dist/canonical/editor-search.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "editor-search", "family": "developer", "maturity": "stable", diff --git a/packages/ui/dist/canonical/empty-state.json b/packages/ui/dist/canonical/empty-state.json index 3576b5fe9..73066fccb 100644 --- a/packages/ui/dist/canonical/empty-state.json +++ b/packages/ui/dist/canonical/empty-state.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "empty-state", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/error-state.json b/packages/ui/dist/canonical/error-state.json index 67597b5e9..d3e8aa202 100644 --- a/packages/ui/dist/canonical/error-state.json +++ b/packages/ui/dist/canonical/error-state.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "error-state", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/field.json b/packages/ui/dist/canonical/field.json index b73218f9d..422db0182 100644 --- a/packages/ui/dist/canonical/field.json +++ b/packages/ui/dist/canonical/field.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "field", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/fieldset.json b/packages/ui/dist/canonical/fieldset.json index bd73b8c84..e4207c56e 100644 --- a/packages/ui/dist/canonical/fieldset.json +++ b/packages/ui/dist/canonical/fieldset.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "fieldset", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/file-browser.json b/packages/ui/dist/canonical/file-browser.json index 434033e11..3a2728dc5 100644 --- a/packages/ui/dist/canonical/file-browser.json +++ b/packages/ui/dist/canonical/file-browser.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "file-browser", "family": "composed", "maturity": "stable", diff --git a/packages/ui/dist/canonical/file-input.json b/packages/ui/dist/canonical/file-input.json index 7d2a4a833..ef0ebdf9d 100644 --- a/packages/ui/dist/canonical/file-input.json +++ b/packages/ui/dist/canonical/file-input.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "file-input", "family": "forms-advanced", "maturity": "stable", diff --git a/packages/ui/dist/canonical/filterable-table.json b/packages/ui/dist/canonical/filterable-table.json index 7bfb6a3fc..4f4972eb9 100644 --- a/packages/ui/dist/canonical/filterable-table.json +++ b/packages/ui/dist/canonical/filterable-table.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "filterable-table", "family": "composed", "maturity": "stable", diff --git a/packages/ui/dist/canonical/form-builder.json b/packages/ui/dist/canonical/form-builder.json index 0dedf2bd2..05f599f70 100644 --- a/packages/ui/dist/canonical/form-builder.json +++ b/packages/ui/dist/canonical/form-builder.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "form-builder", "family": "forms-advanced", "maturity": "draft", diff --git a/packages/ui/dist/canonical/i3-window-frame.json b/packages/ui/dist/canonical/i3-window-frame.json index eb42a5106..5f97c9ab6 100644 --- a/packages/ui/dist/canonical/i3-window-frame.json +++ b/packages/ui/dist/canonical/i3-window-frame.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "i3-window-frame", "family": "composed", "maturity": "stable", diff --git a/packages/ui/dist/canonical/icon-button.json b/packages/ui/dist/canonical/icon-button.json index 251daf19e..a531d358a 100644 --- a/packages/ui/dist/canonical/icon-button.json +++ b/packages/ui/dist/canonical/icon-button.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "icon-button", "family": "actions", "maturity": "stable", diff --git a/packages/ui/dist/canonical/kbd.json b/packages/ui/dist/canonical/kbd.json index c7de78e55..f95f82cec 100644 --- a/packages/ui/dist/canonical/kbd.json +++ b/packages/ui/dist/canonical/kbd.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "kbd", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/link.json b/packages/ui/dist/canonical/link.json index 644a18354..4432d9d60 100644 --- a/packages/ui/dist/canonical/link.json +++ b/packages/ui/dist/canonical/link.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "link", "family": "actions", "maturity": "stable", diff --git a/packages/ui/dist/canonical/list.json b/packages/ui/dist/canonical/list.json index dc0863550..ee36d4e78 100644 --- a/packages/ui/dist/canonical/list.json +++ b/packages/ui/dist/canonical/list.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "list", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/loading-indicator.json b/packages/ui/dist/canonical/loading-indicator.json index 104d2579b..4fd9e2a5c 100644 --- a/packages/ui/dist/canonical/loading-indicator.json +++ b/packages/ui/dist/canonical/loading-indicator.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "loading-indicator", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/menu.json b/packages/ui/dist/canonical/menu.json index 347454645..01aa7ef1d 100644 --- a/packages/ui/dist/canonical/menu.json +++ b/packages/ui/dist/canonical/menu.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "menu", "family": "navigation", "maturity": "stable", diff --git a/packages/ui/dist/canonical/multiselect.json b/packages/ui/dist/canonical/multiselect.json index a8ba1ce29..978d31ad5 100644 --- a/packages/ui/dist/canonical/multiselect.json +++ b/packages/ui/dist/canonical/multiselect.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "multiselect", "family": "forms-advanced", "maturity": "stable", diff --git a/packages/ui/dist/canonical/number-field.json b/packages/ui/dist/canonical/number-field.json index bfb33549d..bfe51d25a 100644 --- a/packages/ui/dist/canonical/number-field.json +++ b/packages/ui/dist/canonical/number-field.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "number-field", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/pagination.json b/packages/ui/dist/canonical/pagination.json index ff123f954..597aae01a 100644 --- a/packages/ui/dist/canonical/pagination.json +++ b/packages/ui/dist/canonical/pagination.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "pagination", "family": "navigation", "maturity": "stable", diff --git a/packages/ui/dist/canonical/popover.json b/packages/ui/dist/canonical/popover.json index dcf6bad54..f675faca6 100644 --- a/packages/ui/dist/canonical/popover.json +++ b/packages/ui/dist/canonical/popover.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "popover", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/progress.json b/packages/ui/dist/canonical/progress.json index 7c6daa591..590a3996a 100644 --- a/packages/ui/dist/canonical/progress.json +++ b/packages/ui/dist/canonical/progress.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "progress", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/radio-group.json b/packages/ui/dist/canonical/radio-group.json index 4a9111e7a..af3e3f65d 100644 --- a/packages/ui/dist/canonical/radio-group.json +++ b/packages/ui/dist/canonical/radio-group.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "radio-group", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/range.json b/packages/ui/dist/canonical/range.json index 81b7ed980..b29548f1a 100644 --- a/packages/ui/dist/canonical/range.json +++ b/packages/ui/dist/canonical/range.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "range", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/repeater.json b/packages/ui/dist/canonical/repeater.json index f3d24afd9..92632a4bb 100644 --- a/packages/ui/dist/canonical/repeater.json +++ b/packages/ui/dist/canonical/repeater.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "repeater", "family": "forms-advanced", "maturity": "stable", diff --git a/packages/ui/dist/canonical/search-field.json b/packages/ui/dist/canonical/search-field.json index 1dcb56e9c..4ce060cc1 100644 --- a/packages/ui/dist/canonical/search-field.json +++ b/packages/ui/dist/canonical/search-field.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "search-field", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/segmented-control.json b/packages/ui/dist/canonical/segmented-control.json index b157ecc0c..e08fc9601 100644 --- a/packages/ui/dist/canonical/segmented-control.json +++ b/packages/ui/dist/canonical/segmented-control.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "segmented-control", "family": "actions", "maturity": "stable", diff --git a/packages/ui/dist/canonical/select.json b/packages/ui/dist/canonical/select.json index 012098b94..715260847 100644 --- a/packages/ui/dist/canonical/select.json +++ b/packages/ui/dist/canonical/select.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "select", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/settings-panel.json b/packages/ui/dist/canonical/settings-panel.json index 611a3f401..0d365f760 100644 --- a/packages/ui/dist/canonical/settings-panel.json +++ b/packages/ui/dist/canonical/settings-panel.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "settings-panel", "family": "composed", "maturity": "stable", diff --git a/packages/ui/dist/canonical/sidebar-nav.json b/packages/ui/dist/canonical/sidebar-nav.json index 6865d49fa..fb4dad9bf 100644 --- a/packages/ui/dist/canonical/sidebar-nav.json +++ b/packages/ui/dist/canonical/sidebar-nav.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "sidebar-nav", "family": "navigation", "maturity": "stable", diff --git a/packages/ui/dist/canonical/skeleton.json b/packages/ui/dist/canonical/skeleton.json index 63dd2a064..e9101ab3e 100644 --- a/packages/ui/dist/canonical/skeleton.json +++ b/packages/ui/dist/canonical/skeleton.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "skeleton", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/skip-link.json b/packages/ui/dist/canonical/skip-link.json index 0ee9a6759..eb5f58930 100644 --- a/packages/ui/dist/canonical/skip-link.json +++ b/packages/ui/dist/canonical/skip-link.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "skip-link", "family": "navigation", "maturity": "stable", diff --git a/packages/ui/dist/canonical/switch.json b/packages/ui/dist/canonical/switch.json index e9672d2d0..3e5bb8974 100644 --- a/packages/ui/dist/canonical/switch.json +++ b/packages/ui/dist/canonical/switch.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "switch", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/table.json b/packages/ui/dist/canonical/table.json index 43b389639..a4ff2f9d6 100644 --- a/packages/ui/dist/canonical/table.json +++ b/packages/ui/dist/canonical/table.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "table", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/tabs.json b/packages/ui/dist/canonical/tabs.json index 58485f204..865b1b258 100644 --- a/packages/ui/dist/canonical/tabs.json +++ b/packages/ui/dist/canonical/tabs.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "tabs", "family": "navigation", "maturity": "stable", diff --git a/packages/ui/dist/canonical/terminal.json b/packages/ui/dist/canonical/terminal.json index ea4d0847a..f7e9bba1a 100644 --- a/packages/ui/dist/canonical/terminal.json +++ b/packages/ui/dist/canonical/terminal.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "terminal", "family": "developer", "maturity": "stable", diff --git a/packages/ui/dist/canonical/text-field.json b/packages/ui/dist/canonical/text-field.json index 739cfa09b..719e1ea0c 100644 --- a/packages/ui/dist/canonical/text-field.json +++ b/packages/ui/dist/canonical/text-field.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "text-field", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/textarea.json b/packages/ui/dist/canonical/textarea.json index 78d7dacfc..e28cba603 100644 --- a/packages/ui/dist/canonical/textarea.json +++ b/packages/ui/dist/canonical/textarea.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "textarea", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/time-picker.json b/packages/ui/dist/canonical/time-picker.json index 0587e84cf..9621c6b91 100644 --- a/packages/ui/dist/canonical/time-picker.json +++ b/packages/ui/dist/canonical/time-picker.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "time-picker", "family": "forms-advanced", "maturity": "stable", diff --git a/packages/ui/dist/canonical/timeline.json b/packages/ui/dist/canonical/timeline.json index 83ff40778..65d07dcf2 100644 --- a/packages/ui/dist/canonical/timeline.json +++ b/packages/ui/dist/canonical/timeline.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "timeline", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/toast.json b/packages/ui/dist/canonical/toast.json index cfe4f70b4..e628b3eb1 100644 --- a/packages/ui/dist/canonical/toast.json +++ b/packages/ui/dist/canonical/toast.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "toast", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/toolbar.json b/packages/ui/dist/canonical/toolbar.json index 91e767555..4ce267549 100644 --- a/packages/ui/dist/canonical/toolbar.json +++ b/packages/ui/dist/canonical/toolbar.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "toolbar", "family": "navigation", "maturity": "stable", diff --git a/packages/ui/dist/canonical/tooltip.json b/packages/ui/dist/canonical/tooltip.json index ddb21e5a0..0037674f6 100644 --- a/packages/ui/dist/canonical/tooltip.json +++ b/packages/ui/dist/canonical/tooltip.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "tooltip", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/tree.json b/packages/ui/dist/canonical/tree.json index 0a8264775..f84767084 100644 --- a/packages/ui/dist/canonical/tree.json +++ b/packages/ui/dist/canonical/tree.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "tree", "family": "navigation", "maturity": "stable", diff --git a/packages/ui/dist/canonical/wizard.json b/packages/ui/dist/canonical/wizard.json index ba5a2363b..54bce18a8 100644 --- a/packages/ui/dist/canonical/wizard.json +++ b/packages/ui/dist/canonical/wizard.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-fztdpeuj8EtGHpEoSbDrK6kta336ucIVK4lrRKrlasc=", + "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", "id": "wizard", "family": "forms-advanced", "maturity": "stable", diff --git a/packages/ui/dist/chunks/form-builder-EQnl1AaR.js b/packages/ui/dist/chunks/form-builder-C5Kx5G9b.js similarity index 99% rename from packages/ui/dist/chunks/form-builder-EQnl1AaR.js rename to packages/ui/dist/chunks/form-builder-C5Kx5G9b.js index bb6438b9f..28f2bf5b9 100644 --- a/packages/ui/dist/chunks/form-builder-EQnl1AaR.js +++ b/packages/ui/dist/chunks/form-builder-C5Kx5G9b.js @@ -69,7 +69,7 @@ var identity_default = { name: "j3w1-theme", version: "4.0.0", profile: "default", - sourceDigest: "sha256-0pGYzXZFMWkGlbzNIlyxfInXr3Pog+Q6PuQTyO1Rbu0=" + sourceDigest: "sha256-KNf9QNXsLy6MzEixJdv+LTT8TglJJgE7H0JwMdzpjfA=" }; //#endregion //#region packages/ui/src/internal/form-builder.js diff --git a/packages/ui/dist/chunks/form-builder-Dkweb1xD.js b/packages/ui/dist/chunks/form-builder-C6Rhfsz6.js similarity index 92% rename from packages/ui/dist/chunks/form-builder-Dkweb1xD.js rename to packages/ui/dist/chunks/form-builder-C6Rhfsz6.js index 18dfbad3c..2daa2e07f 100644 --- a/packages/ui/dist/chunks/form-builder-Dkweb1xD.js +++ b/packages/ui/dist/chunks/form-builder-C6Rhfsz6.js @@ -1,5 +1,5 @@ import { t as J3w1Element } from "./element-C1XeXVYC.js"; -import { t as mountBuilder } from "./form-builder-EQnl1AaR.js"; +import { t as mountBuilder } from "./form-builder-C5Kx5G9b.js"; //#region packages/ui/src/behaviors/form-builder.js function formBuilder(root, { signal }) { const editor = root.querySelector("[data-builder]"); @@ -22,7 +22,7 @@ function formBuilder(root, { signal }) { var J3w1FormBuilder = class extends J3w1Element { static componentId = "form-builder"; static version = "4.0.0"; - static implementationId = "sha256-QcTsnt2RqgWKuYJuM/x0uqMUtYY2cGEONH+jVvm2nuY="; + static implementationId = "sha256-uXS+kL7KbvfhlApDhEsvMY+pFsX9bHFlaTF/qUH94mE="; static connect = formBuilder; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/form-builder.js b/packages/ui/dist/components/form-builder.js index 24c141d5f..a3969b6cb 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-Dkweb1xD.js"; +export { t as J3w1FormBuilder } from "../chunks/form-builder-C6Rhfsz6.js"; diff --git a/packages/ui/dist/contracts/admin-form.json b/packages/ui/dist/contracts/admin-form.json index cd14eff71..84cac0e3d 100644 --- a/packages/ui/dist/contracts/admin-form.json +++ b/packages/ui/dist/contracts/admin-form.json @@ -909,6 +909,6 @@ "copy": { "directory": "copy/admin-form/", "manifest": "copy/admin-form/manifest.json", - "digest": "sha256-HtST9X/UpiRDsFEMo7i1ElwMpiALSDf/MyJKLw0Dk90=" + "digest": "sha256-nYS8jMsuxKEj8F3dOHKvnVCccydqs1Pp3Z6SsTCUoOU=" } } diff --git a/packages/ui/dist/contracts/alert.json b/packages/ui/dist/contracts/alert.json index 89dc91e3d..5c2fa2f3f 100644 --- a/packages/ui/dist/contracts/alert.json +++ b/packages/ui/dist/contracts/alert.json @@ -445,6 +445,6 @@ "copy": { "directory": "copy/alert/", "manifest": "copy/alert/manifest.json", - "digest": "sha256-f/+taezEaLxGwimv58Q/I0IZhOlgqScdKlt4tv+J4js=" + "digest": "sha256-2ZbWfxl+0O3OjPAuMynLSs9Kp25QuUMiwXSpMKBlxQ0=" } } diff --git a/packages/ui/dist/contracts/avatar.json b/packages/ui/dist/contracts/avatar.json index d0b680565..f1304f356 100644 --- a/packages/ui/dist/contracts/avatar.json +++ b/packages/ui/dist/contracts/avatar.json @@ -274,6 +274,6 @@ "copy": { "directory": "copy/avatar/", "manifest": "copy/avatar/manifest.json", - "digest": "sha256-RRx0kD6cBwLeZFpZWYUl397tEaCFc8+hAq4Iul/dLR4=" + "digest": "sha256-c6GiHt1iB6I4HICzh/PnoN9D4wm4omp6h7bp2vBfftg=" } } diff --git a/packages/ui/dist/contracts/badge.json b/packages/ui/dist/contracts/badge.json index a78c345d8..004d71f97 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-raQq7vv7/AES3cx9gip/td/yODbpi3TvQ6minqOTVqg=" + "digest": "sha256-dYqinOxtXZZbvC2MgSv3k1KR+2WgDw7MIWYvM1syecw=" } } diff --git a/packages/ui/dist/contracts/breadcrumbs.json b/packages/ui/dist/contracts/breadcrumbs.json index 5c912d3a1..3a582e963 100644 --- a/packages/ui/dist/contracts/breadcrumbs.json +++ b/packages/ui/dist/contracts/breadcrumbs.json @@ -340,6 +340,6 @@ "copy": { "directory": "copy/breadcrumbs/", "manifest": "copy/breadcrumbs/manifest.json", - "digest": "sha256-/aBGJEdE5pG/blq4jU0tuQHrHU7s37pK/hbNdI+bRL8=" + "digest": "sha256-EalDQFcoOagLdF+WFVS1L0RqDU9zG7P6zi6BdvHcFFM=" } } diff --git a/packages/ui/dist/contracts/button-group.json b/packages/ui/dist/contracts/button-group.json index 5f1f07733..227505894 100644 --- a/packages/ui/dist/contracts/button-group.json +++ b/packages/ui/dist/contracts/button-group.json @@ -323,6 +323,6 @@ "copy": { "directory": "copy/button-group/", "manifest": "copy/button-group/manifest.json", - "digest": "sha256-YKE2o9BZmy5u6eQtlL6F7qjaDs3StPobS7MNVotT0KI=" + "digest": "sha256-vwsYAxmno4/3Uq0+30v3izOHgMpzwUEntDgsiFb/uAE=" } } diff --git a/packages/ui/dist/contracts/button.json b/packages/ui/dist/contracts/button.json index c0860b429..fb68cc281 100644 --- a/packages/ui/dist/contracts/button.json +++ b/packages/ui/dist/contracts/button.json @@ -510,6 +510,6 @@ "copy": { "directory": "copy/button/", "manifest": "copy/button/manifest.json", - "digest": "sha256-Bat7CbXli1BVcEmYLAyJ42OAFKhWDW0Y3N9ebMbsR+k=" + "digest": "sha256-c6TgjUcOcYCt67r5dMnrTmZpgv9LuAg3v1JdKvlJv+I=" } } diff --git a/packages/ui/dist/contracts/card.json b/packages/ui/dist/contracts/card.json index e4e06ace5..5d67877f7 100644 --- a/packages/ui/dist/contracts/card.json +++ b/packages/ui/dist/contracts/card.json @@ -362,6 +362,6 @@ "copy": { "directory": "copy/card/", "manifest": "copy/card/manifest.json", - "digest": "sha256-uCrS1zqZdZJERPpycHAm2jRonQ5KvUciSZZ0GDG/r2c=" + "digest": "sha256-i+pJofI3U2yKMpy/iUtg9GQYpMJuhdXqk8eQsj/fFsk=" } } diff --git a/packages/ui/dist/contracts/chart.json b/packages/ui/dist/contracts/chart.json index 26e4974c7..3e76b0c29 100644 --- a/packages/ui/dist/contracts/chart.json +++ b/packages/ui/dist/contracts/chart.json @@ -336,6 +336,6 @@ "copy": { "directory": "copy/chart/", "manifest": "copy/chart/manifest.json", - "digest": "sha256-vN7Sze32H790CZumX+te7Ju/JDPFYxXOYbJyBD+Fl34=" + "digest": "sha256-lm2ZxifbDt5iYTAwiLkbvEREqGAmkeGkqLeoqfgfbLw=" } } diff --git a/packages/ui/dist/contracts/checkbox.json b/packages/ui/dist/contracts/checkbox.json index 9c7e504db..22c821986 100644 --- a/packages/ui/dist/contracts/checkbox.json +++ b/packages/ui/dist/contracts/checkbox.json @@ -491,6 +491,6 @@ "copy": { "directory": "copy/checkbox/", "manifest": "copy/checkbox/manifest.json", - "digest": "sha256-hJd553Ef33h7Ny4ruLLSL8+BmSTVMIt41aCWwR9Kavc=" + "digest": "sha256-kFFpTffP1dDIr9wzNmLVN7foHnf/nRwRbekip3C4oYY=" } } diff --git a/packages/ui/dist/contracts/chip.json b/packages/ui/dist/contracts/chip.json index 2c39fc3c0..e01495c21 100644 --- a/packages/ui/dist/contracts/chip.json +++ b/packages/ui/dist/contracts/chip.json @@ -386,6 +386,6 @@ "copy": { "directory": "copy/chip/", "manifest": "copy/chip/manifest.json", - "digest": "sha256-CDpgsi4gq8pm3VmaExEHAIHIro+79mdFp7dhVprq6XE=" + "digest": "sha256-yT0JmPG1bG7dWQAeyCEaG9vmhKJg43cR+dngTQc3ToY=" } } diff --git a/packages/ui/dist/contracts/code-editor.json b/packages/ui/dist/contracts/code-editor.json index 5647ae682..6ed98eb06 100644 --- a/packages/ui/dist/contracts/code-editor.json +++ b/packages/ui/dist/contracts/code-editor.json @@ -531,6 +531,6 @@ "copy": { "directory": "copy/code-editor/", "manifest": "copy/code-editor/manifest.json", - "digest": "sha256-AZOed+UbhiUZzGPeg4XOfbQaDtbSuEA5oe+y2k51vjI=" + "digest": "sha256-ilcy8XyaIxDvpFx8RrzkFJhHJ6uot99rm2kBpXxBYBI=" } } diff --git a/packages/ui/dist/contracts/combobox.json b/packages/ui/dist/contracts/combobox.json index da173a548..29d23c77a 100644 --- a/packages/ui/dist/contracts/combobox.json +++ b/packages/ui/dist/contracts/combobox.json @@ -548,6 +548,6 @@ "copy": { "directory": "copy/combobox/", "manifest": "copy/combobox/manifest.json", - "digest": "sha256-Z6FLAAQ/vWunhYlUN5k67m7KZO/GNkn0b+T8HAGYFis=" + "digest": "sha256-rdA+FV9dwxEdykFLa7tzZnjl+60iBGTXLBwm5cfXOnE=" } } diff --git a/packages/ui/dist/contracts/command-palette.json b/packages/ui/dist/contracts/command-palette.json index 7e064cb8b..970446129 100644 --- a/packages/ui/dist/contracts/command-palette.json +++ b/packages/ui/dist/contracts/command-palette.json @@ -407,6 +407,6 @@ "copy": { "directory": "copy/command-palette/", "manifest": "copy/command-palette/manifest.json", - "digest": "sha256-sjwZw/AW7vcseMQ1l9pbcq/hDRYxIdZs2DOV5595GV4=" + "digest": "sha256-RxOWXeniso+hvwGsCJGdxMEfsQnCjBbPcgMkNi70XEY=" } } diff --git a/packages/ui/dist/contracts/compact-dashboard.json b/packages/ui/dist/contracts/compact-dashboard.json index a39bb6f87..82dd23a38 100644 --- a/packages/ui/dist/contracts/compact-dashboard.json +++ b/packages/ui/dist/contracts/compact-dashboard.json @@ -479,6 +479,6 @@ "copy": { "directory": "copy/compact-dashboard/", "manifest": "copy/compact-dashboard/manifest.json", - "digest": "sha256-8Tz2CHZNJCFbdxv2h7ms7Dvyie84SceiClcFGjQ4iT0=" + "digest": "sha256-6VcljZV/ScZZHBdlliiCRDKmNJun1WvkMSswT57Yue4=" } } diff --git a/packages/ui/dist/contracts/data-table.json b/packages/ui/dist/contracts/data-table.json index 3e19031af..de5c63d9b 100644 --- a/packages/ui/dist/contracts/data-table.json +++ b/packages/ui/dist/contracts/data-table.json @@ -607,6 +607,6 @@ "copy": { "directory": "copy/data-table/", "manifest": "copy/data-table/manifest.json", - "digest": "sha256-HPNF+mZXjuU3YIozdl2drk3Led2FIYYUMYaIgdU5O68=" + "digest": "sha256-2ou/6/GgNuGgAaCssLJwSinsCUqepjlg+x2p8l6YANI=" } } diff --git a/packages/ui/dist/contracts/date-picker.json b/packages/ui/dist/contracts/date-picker.json index 35fd49e45..70f622404 100644 --- a/packages/ui/dist/contracts/date-picker.json +++ b/packages/ui/dist/contracts/date-picker.json @@ -583,6 +583,6 @@ "copy": { "directory": "copy/date-picker/", "manifest": "copy/date-picker/manifest.json", - "digest": "sha256-7BRpb4bMBn6h5aixxc8Fb+OE71//nfE+Rlqox36UEek=" + "digest": "sha256-48K6bsVp7ch78EFmIyDgXpAaLzUWaLgA1nfjOo2NwZo=" } } diff --git a/packages/ui/dist/contracts/description-list.json b/packages/ui/dist/contracts/description-list.json index 5ee4c57d7..dc9e3d4ce 100644 --- a/packages/ui/dist/contracts/description-list.json +++ b/packages/ui/dist/contracts/description-list.json @@ -281,6 +281,6 @@ "copy": { "directory": "copy/description-list/", "manifest": "copy/description-list/manifest.json", - "digest": "sha256-HW+ZJFxBuqoK3d8KJlYivtpz6Ql2Fa89enziCfIyg1Y=" + "digest": "sha256-X4Ucl253TcuE6dHaVe7snooGjXH6qNADSDI8KIVB11A=" } } diff --git a/packages/ui/dist/contracts/diagnostics.json b/packages/ui/dist/contracts/diagnostics.json index 470802652..ba09ee29a 100644 --- a/packages/ui/dist/contracts/diagnostics.json +++ b/packages/ui/dist/contracts/diagnostics.json @@ -568,6 +568,6 @@ "copy": { "directory": "copy/diagnostics/", "manifest": "copy/diagnostics/manifest.json", - "digest": "sha256-Pxd8jPIYkeRwMC2E/I0DzzxVoxnL9iQ6p2cvAWl7Qkk=" + "digest": "sha256-UpdG5YWwniZZMmaHLoJEtfjfHyOOvfgh9kwW7yzjGME=" } } diff --git a/packages/ui/dist/contracts/dialog.json b/packages/ui/dist/contracts/dialog.json index 37a290e73..ed7478b23 100644 --- a/packages/ui/dist/contracts/dialog.json +++ b/packages/ui/dist/contracts/dialog.json @@ -695,6 +695,6 @@ "copy": { "directory": "copy/dialog/", "manifest": "copy/dialog/manifest.json", - "digest": "sha256-AJuEfuBHZb4d3lOAX/LxDDfwsCCYi6i4YdV+9O78IPY=" + "digest": "sha256-ffV0ZOGvzK4N5REfOqb5SopYFtk70wS5so3vIH5qUHc=" } } diff --git a/packages/ui/dist/contracts/diff-view.json b/packages/ui/dist/contracts/diff-view.json index e21693111..38d0866a3 100644 --- a/packages/ui/dist/contracts/diff-view.json +++ b/packages/ui/dist/contracts/diff-view.json @@ -516,6 +516,6 @@ "copy": { "directory": "copy/diff-view/", "manifest": "copy/diff-view/manifest.json", - "digest": "sha256-cIqnQO+bVVoaU28MWcHfPoVhXheewGMtTBcDUDs8vxU=" + "digest": "sha256-kxUgBrJ5pugX+Rn/YdpdeR3lTLsYCBlHWGv/+4xyeGY=" } } diff --git a/packages/ui/dist/contracts/disclosure.json b/packages/ui/dist/contracts/disclosure.json index f7b696eac..ff5eaf816 100644 --- a/packages/ui/dist/contracts/disclosure.json +++ b/packages/ui/dist/contracts/disclosure.json @@ -335,6 +335,6 @@ "copy": { "directory": "copy/disclosure/", "manifest": "copy/disclosure/manifest.json", - "digest": "sha256-pUsMYVXWCYN1EVfwL18klJsWytxWbWsJ5ZCkon4Ohb4=" + "digest": "sha256-srtw0ECNjqeIbiyT88LWtptOK+3TJpxgjEzBwafyhBE=" } } diff --git a/packages/ui/dist/contracts/drawer.json b/packages/ui/dist/contracts/drawer.json index 50fd2a95f..5fff7e534 100644 --- a/packages/ui/dist/contracts/drawer.json +++ b/packages/ui/dist/contracts/drawer.json @@ -696,6 +696,6 @@ "copy": { "directory": "copy/drawer/", "manifest": "copy/drawer/manifest.json", - "digest": "sha256-sVEeq/PKuPmVSBR72cingvVcslqWxp/7MiJZtdMTaT0=" + "digest": "sha256-4F6UZloyQg8I7wVtudpN0GlasZZCpflUeQnezTwqvss=" } } diff --git a/packages/ui/dist/contracts/editor-search.json b/packages/ui/dist/contracts/editor-search.json index f90790738..053b7ef79 100644 --- a/packages/ui/dist/contracts/editor-search.json +++ b/packages/ui/dist/contracts/editor-search.json @@ -363,6 +363,6 @@ "copy": { "directory": "copy/editor-search/", "manifest": "copy/editor-search/manifest.json", - "digest": "sha256-oRjcQaiNJcbQgPckQh0vjN6z83eBEU7mtbesGoE5HGk=" + "digest": "sha256-tzETVZ5wEm/wqmqM6Gu3ONUNlEVtbZUiPneNH2sbPZ8=" } } diff --git a/packages/ui/dist/contracts/empty-state.json b/packages/ui/dist/contracts/empty-state.json index 9678b5f92..6e9a3d5ad 100644 --- a/packages/ui/dist/contracts/empty-state.json +++ b/packages/ui/dist/contracts/empty-state.json @@ -429,6 +429,6 @@ "copy": { "directory": "copy/empty-state/", "manifest": "copy/empty-state/manifest.json", - "digest": "sha256-h6FDAg6a5sS+S1za92hKQI46WLnC4dZBTi2eTWdOP+A=" + "digest": "sha256-75nIi6f/Ht0GN4W2P39d86rZv1OvN/aduq/2EcG1HB4=" } } diff --git a/packages/ui/dist/contracts/error-state.json b/packages/ui/dist/contracts/error-state.json index 970298326..1d1df2d73 100644 --- a/packages/ui/dist/contracts/error-state.json +++ b/packages/ui/dist/contracts/error-state.json @@ -353,6 +353,6 @@ "copy": { "directory": "copy/error-state/", "manifest": "copy/error-state/manifest.json", - "digest": "sha256-tmU/T4Skbf9Eu3//L9hqqYCXoJofZolyF9xBuaRZ/fM=" + "digest": "sha256-gv+zrrKBwqknOREXPEz57rKP+7GJco38FRkXeXQqAbU=" } } diff --git a/packages/ui/dist/contracts/field.json b/packages/ui/dist/contracts/field.json index 1ed5fcb00..57757f7a0 100644 --- a/packages/ui/dist/contracts/field.json +++ b/packages/ui/dist/contracts/field.json @@ -374,6 +374,6 @@ "copy": { "directory": "copy/field/", "manifest": "copy/field/manifest.json", - "digest": "sha256-GQ3tkXxmRfI41HNyehqJhHunv4ftTZccXD8irv00Nxo=" + "digest": "sha256-w3/ZZLfNarfyG9UY8KNfqo/QA/4ufORLVSWeIwS/iYY=" } } diff --git a/packages/ui/dist/contracts/fieldset.json b/packages/ui/dist/contracts/fieldset.json index 7e9baab91..4c842e176 100644 --- a/packages/ui/dist/contracts/fieldset.json +++ b/packages/ui/dist/contracts/fieldset.json @@ -366,6 +366,6 @@ "copy": { "directory": "copy/fieldset/", "manifest": "copy/fieldset/manifest.json", - "digest": "sha256-2Z7hETSoJn6L/hHgchT0vJnPEZyrqjO6/vefg/ENXPk=" + "digest": "sha256-uljFodRq8xH/+kpic5mcTdwYRi6D8uRATY8/65tRHSA=" } } diff --git a/packages/ui/dist/contracts/file-browser.json b/packages/ui/dist/contracts/file-browser.json index 574dd6219..5ffed937e 100644 --- a/packages/ui/dist/contracts/file-browser.json +++ b/packages/ui/dist/contracts/file-browser.json @@ -459,6 +459,6 @@ "copy": { "directory": "copy/file-browser/", "manifest": "copy/file-browser/manifest.json", - "digest": "sha256-ega8f7vafG5gKtOcw4Aole+jb7E5C7xB7jZhdJWN0bQ=" + "digest": "sha256-dumD1CMdclQzMmPsrLn3Denb28aFPOcd34uk/ZtbEgI=" } } diff --git a/packages/ui/dist/contracts/file-input.json b/packages/ui/dist/contracts/file-input.json index c876c0085..6c612ba34 100644 --- a/packages/ui/dist/contracts/file-input.json +++ b/packages/ui/dist/contracts/file-input.json @@ -522,6 +522,6 @@ "copy": { "directory": "copy/file-input/", "manifest": "copy/file-input/manifest.json", - "digest": "sha256-TKiC1mhiYH8D1y50C5ACpP4Lz10Z3xCa4GxvUdkDEnw=" + "digest": "sha256-PCFjtc+DwT+gaXF4ED4ra/J3ypLKXVDF9kT/4IXn4No=" } } diff --git a/packages/ui/dist/contracts/filterable-table.json b/packages/ui/dist/contracts/filterable-table.json index 1b45785bd..c0179624f 100644 --- a/packages/ui/dist/contracts/filterable-table.json +++ b/packages/ui/dist/contracts/filterable-table.json @@ -756,6 +756,6 @@ "copy": { "directory": "copy/filterable-table/", "manifest": "copy/filterable-table/manifest.json", - "digest": "sha256-tE2lTsJjQH6ZBaYTO4TyapuKMSc19KHg0ode/N3j828=" + "digest": "sha256-6e9ro37teOmSFrYcAJ7t+PP1FQ9FEb9GhcBjA3Ah5iw=" } } diff --git a/packages/ui/dist/contracts/form-builder.json b/packages/ui/dist/contracts/form-builder.json index f0edbd340..2215d7496 100644 --- a/packages/ui/dist/contracts/form-builder.json +++ b/packages/ui/dist/contracts/form-builder.json @@ -878,6 +878,6 @@ "copy": { "directory": "copy/form-builder/", "manifest": "copy/form-builder/manifest.json", - "digest": "sha256-aoSpEA6qVQhF0JI5HP7ycm4UbGmG+ya3B7tt1wA5RnE=" + "digest": "sha256-/AJpK7InIcUrx5C6r4HWc3McmNfuSvcN0bFFLRwFx7s=" } } diff --git a/packages/ui/dist/contracts/i3-window-frame.json b/packages/ui/dist/contracts/i3-window-frame.json index 9aacc3053..2dd58c36a 100644 --- a/packages/ui/dist/contracts/i3-window-frame.json +++ b/packages/ui/dist/contracts/i3-window-frame.json @@ -962,6 +962,6 @@ "copy": { "directory": "copy/i3-window-frame/", "manifest": "copy/i3-window-frame/manifest.json", - "digest": "sha256-SQObA3CbBJSibf9fY3JRlURdH9FXLA7SfbAElKJ+pPs=" + "digest": "sha256-U0UgHnHKVp5XKkj1fNN5b+MOeYjoFSjDI5MDm6KE5Qw=" } } diff --git a/packages/ui/dist/contracts/icon-button.json b/packages/ui/dist/contracts/icon-button.json index cccb03bf9..3be2a5fb9 100644 --- a/packages/ui/dist/contracts/icon-button.json +++ b/packages/ui/dist/contracts/icon-button.json @@ -365,6 +365,6 @@ "copy": { "directory": "copy/icon-button/", "manifest": "copy/icon-button/manifest.json", - "digest": "sha256-Yq0utAFthUSAFiDa7lcg55cQhUdK+H2LnBgt5a/6/C0=" + "digest": "sha256-ySWwdGJTFvqUPfIPiE//EF2SBXqYn8iDa05Ljnz5WmE=" } } diff --git a/packages/ui/dist/contracts/kbd.json b/packages/ui/dist/contracts/kbd.json index 2120df11a..70e32d764 100644 --- a/packages/ui/dist/contracts/kbd.json +++ b/packages/ui/dist/contracts/kbd.json @@ -254,6 +254,6 @@ "copy": { "directory": "copy/kbd/", "manifest": "copy/kbd/manifest.json", - "digest": "sha256-T+bUtWMpGiYAfACd3t+B2UJX8FK3BzlfN5i/tTOryoY=" + "digest": "sha256-N3o7jonx7ZxjgaydH4c9BuaHiyHBNtfdwvsGJReVWvc=" } } diff --git a/packages/ui/dist/contracts/link.json b/packages/ui/dist/contracts/link.json index 48544b8d3..94c828f42 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-VtFCGcmp+kAitC5o4ewjNT824WaoxY3/igfHlJhH0uA=" + "digest": "sha256-9RCBHV2eK/OPYH+iLaWZUBLLRL/3/Db67A/AA/gLtVA=" } } diff --git a/packages/ui/dist/contracts/list.json b/packages/ui/dist/contracts/list.json index b34a4fd75..9a843cc0a 100644 --- a/packages/ui/dist/contracts/list.json +++ b/packages/ui/dist/contracts/list.json @@ -407,6 +407,6 @@ "copy": { "directory": "copy/list/", "manifest": "copy/list/manifest.json", - "digest": "sha256-QvzckZWIiDE/ImHAN4r4S19GgKtTUSk1eHxUqy+pyXQ=" + "digest": "sha256-SbBbbXQ5+Bc1H2Pt8GwTLH1s6pniel+amh1L4cKgwss=" } } diff --git a/packages/ui/dist/contracts/loading-indicator.json b/packages/ui/dist/contracts/loading-indicator.json index b65fec11e..076c8bb80 100644 --- a/packages/ui/dist/contracts/loading-indicator.json +++ b/packages/ui/dist/contracts/loading-indicator.json @@ -286,6 +286,6 @@ "copy": { "directory": "copy/loading-indicator/", "manifest": "copy/loading-indicator/manifest.json", - "digest": "sha256-Z6/RoN7WPNcBLssWQ87bGJZ78aTSUa9ZuXMYDROZNus=" + "digest": "sha256-E5QH4rXH0Q8cEQtr0bOGShuzZQlv5Y0cZ76Um3cCKCg=" } } diff --git a/packages/ui/dist/contracts/menu.json b/packages/ui/dist/contracts/menu.json index d8ea3a223..49237e3f2 100644 --- a/packages/ui/dist/contracts/menu.json +++ b/packages/ui/dist/contracts/menu.json @@ -534,6 +534,6 @@ "copy": { "directory": "copy/menu/", "manifest": "copy/menu/manifest.json", - "digest": "sha256-YWF7LtF4Y/ZgN5otpkiIBHeQDPn8kKw129WvyZSELhs=" + "digest": "sha256-Ud+V3UiG+NGVSscSNIvn3E4AuJOFFvDO/8r2oe1R9sw=" } } diff --git a/packages/ui/dist/contracts/multiselect.json b/packages/ui/dist/contracts/multiselect.json index df0ae73c3..cde64e1ee 100644 --- a/packages/ui/dist/contracts/multiselect.json +++ b/packages/ui/dist/contracts/multiselect.json @@ -490,6 +490,6 @@ "copy": { "directory": "copy/multiselect/", "manifest": "copy/multiselect/manifest.json", - "digest": "sha256-O1IjRfwEZvhLWVLk3LK9TIML1tL3gVj3my8BX/zwegw=" + "digest": "sha256-vXlR0srvz+KDPAaPbWuMQCTQmQGqocNNjF2ccKGVUeA=" } } diff --git a/packages/ui/dist/contracts/number-field.json b/packages/ui/dist/contracts/number-field.json index 5989cfddd..b0f340db2 100644 --- a/packages/ui/dist/contracts/number-field.json +++ b/packages/ui/dist/contracts/number-field.json @@ -608,6 +608,6 @@ "copy": { "directory": "copy/number-field/", "manifest": "copy/number-field/manifest.json", - "digest": "sha256-hegLu++sUwG/DMW8Hg7cZrcebrq4rTNvBxMl75+x2dQ=" + "digest": "sha256-p6h3APhk2/kyaXbWKAEHdHQKn9zMYnarGK9hRLu/MKg=" } } diff --git a/packages/ui/dist/contracts/pagination.json b/packages/ui/dist/contracts/pagination.json index f3e0bac5e..204737ab4 100644 --- a/packages/ui/dist/contracts/pagination.json +++ b/packages/ui/dist/contracts/pagination.json @@ -378,6 +378,6 @@ "copy": { "directory": "copy/pagination/", "manifest": "copy/pagination/manifest.json", - "digest": "sha256-60r+aCzqs2VJdTf9woMF9hv5KthQuTRbZ7iM38aKMBI=" + "digest": "sha256-VnFhaAlOvHjn6UY3qGk2yBXuPfa3PI1CYjoFCi9AAJo=" } } diff --git a/packages/ui/dist/contracts/popover.json b/packages/ui/dist/contracts/popover.json index c4a1083fd..48b7a8e12 100644 --- a/packages/ui/dist/contracts/popover.json +++ b/packages/ui/dist/contracts/popover.json @@ -336,6 +336,6 @@ "copy": { "directory": "copy/popover/", "manifest": "copy/popover/manifest.json", - "digest": "sha256-cbFFGYigmfXCHWbnqp7UDh18ygoUiqUWr96ofsWEhDM=" + "digest": "sha256-Phnn5besyYINT3a2SO+Oyfo34q3wPJpuLaWvH2pQWAU=" } } diff --git a/packages/ui/dist/contracts/progress.json b/packages/ui/dist/contracts/progress.json index c36f0acdb..137a90489 100644 --- a/packages/ui/dist/contracts/progress.json +++ b/packages/ui/dist/contracts/progress.json @@ -298,6 +298,6 @@ "copy": { "directory": "copy/progress/", "manifest": "copy/progress/manifest.json", - "digest": "sha256-1b2q82GAM6aew7BrlzqLA7+ZV6dnlY7OpesY4DV0bOc=" + "digest": "sha256-r+zhlEfXkdl5bcryLN+l4mssjPuUGlyjB4vslOUMdck=" } } diff --git a/packages/ui/dist/contracts/radio-group.json b/packages/ui/dist/contracts/radio-group.json index 15c73317d..aada0527b 100644 --- a/packages/ui/dist/contracts/radio-group.json +++ b/packages/ui/dist/contracts/radio-group.json @@ -396,6 +396,6 @@ "copy": { "directory": "copy/radio-group/", "manifest": "copy/radio-group/manifest.json", - "digest": "sha256-PRTi1+IXRrKIG+iq5rBiBKtFzpsGeQG5/f/16lYpmCw=" + "digest": "sha256-UpYcgVSqDnhnjaAHOl5w3cY9WJP0x1sLlAONVAGlg78=" } } diff --git a/packages/ui/dist/contracts/range.json b/packages/ui/dist/contracts/range.json index 9cd7eb255..b02799426 100644 --- a/packages/ui/dist/contracts/range.json +++ b/packages/ui/dist/contracts/range.json @@ -556,6 +556,6 @@ "copy": { "directory": "copy/range/", "manifest": "copy/range/manifest.json", - "digest": "sha256-83FLaBofKJVFXrLxvl++gdymve8PpMF4DiKOiX0/ZNA=" + "digest": "sha256-9Fj1tjDQyex5Ybg8lOvcWuVuHic/EnjnNXfR/YPoO7c=" } } diff --git a/packages/ui/dist/contracts/repeater.json b/packages/ui/dist/contracts/repeater.json index 593083b71..297b83251 100644 --- a/packages/ui/dist/contracts/repeater.json +++ b/packages/ui/dist/contracts/repeater.json @@ -361,6 +361,6 @@ "copy": { "directory": "copy/repeater/", "manifest": "copy/repeater/manifest.json", - "digest": "sha256-iMtAouXvHNiZEeyxqGOPIX4ptGvUNPZrhPw3akRSvYE=" + "digest": "sha256-Ek/0mqQpQIztzCidbtl1wboLnvHJjvWQ7BM/s4lZ5FM=" } } diff --git a/packages/ui/dist/contracts/search-field.json b/packages/ui/dist/contracts/search-field.json index b3342e12d..c6bfdb188 100644 --- a/packages/ui/dist/contracts/search-field.json +++ b/packages/ui/dist/contracts/search-field.json @@ -484,6 +484,6 @@ "copy": { "directory": "copy/search-field/", "manifest": "copy/search-field/manifest.json", - "digest": "sha256-yt6YbOXtYkZ8+8jd4AuPMSJrWIkpD5DYzBPylnpK5v4=" + "digest": "sha256-pnh7Ao4SBHM7H6SMJlWsYLXgxVp7AdEhbo+/35vi72k=" } } diff --git a/packages/ui/dist/contracts/segmented-control.json b/packages/ui/dist/contracts/segmented-control.json index f6d88b599..846069fec 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-gpupFMlyzlByXEuOUk8kQDsQs4jv/kIEQOZAiz6zMgQ=" + "digest": "sha256-H33N4ElTkCkBMh2MbBR3SPIPib1+HsrpF2WqEwYwOow=" } } diff --git a/packages/ui/dist/contracts/select.json b/packages/ui/dist/contracts/select.json index 3f32c199e..32d990c70 100644 --- a/packages/ui/dist/contracts/select.json +++ b/packages/ui/dist/contracts/select.json @@ -607,6 +607,6 @@ "copy": { "directory": "copy/select/", "manifest": "copy/select/manifest.json", - "digest": "sha256-Y1NfQmSIof6fmELT3rkfGZDSCBfjNPDEpyzctLVkgHI=" + "digest": "sha256-Auv8G7CtLAflBo0zzaMsITFuEZmyeNhvlcRInd1XK04=" } } diff --git a/packages/ui/dist/contracts/settings-panel.json b/packages/ui/dist/contracts/settings-panel.json index 6126a982f..763a61ad2 100644 --- a/packages/ui/dist/contracts/settings-panel.json +++ b/packages/ui/dist/contracts/settings-panel.json @@ -817,6 +817,6 @@ "copy": { "directory": "copy/settings-panel/", "manifest": "copy/settings-panel/manifest.json", - "digest": "sha256-pyfwmrg9NQ+SMVaMISW1+5BGdWSdQ6Ai43LdqNGYwmQ=" + "digest": "sha256-vLsgXoGOv6Ek2Vt1iEvKgMZAwnYyn2CTBoyAh/wxfJw=" } } diff --git a/packages/ui/dist/contracts/sidebar-nav.json b/packages/ui/dist/contracts/sidebar-nav.json index ff4ef4e71..cc2371086 100644 --- a/packages/ui/dist/contracts/sidebar-nav.json +++ b/packages/ui/dist/contracts/sidebar-nav.json @@ -426,6 +426,6 @@ "copy": { "directory": "copy/sidebar-nav/", "manifest": "copy/sidebar-nav/manifest.json", - "digest": "sha256-Rl7kfHhDzahs2E5iAw6o2u7UNqJAiayqCZn3A2ag9D4=" + "digest": "sha256-vJwnwnVoCLZuwhSZpsPKP7dmOI/CkQQTmVryV7sm25s=" } } diff --git a/packages/ui/dist/contracts/skeleton.json b/packages/ui/dist/contracts/skeleton.json index b77646b56..c44cd0130 100644 --- a/packages/ui/dist/contracts/skeleton.json +++ b/packages/ui/dist/contracts/skeleton.json @@ -282,6 +282,6 @@ "copy": { "directory": "copy/skeleton/", "manifest": "copy/skeleton/manifest.json", - "digest": "sha256-YCCxtxYLNlpJZqd02zALos+1RGYqYXZnhNIgbjjTOLk=" + "digest": "sha256-4LwxROheBPrSRHAZZzi9L4TDIlPOW7pk4CjtpDmBKQw=" } } diff --git a/packages/ui/dist/contracts/skip-link.json b/packages/ui/dist/contracts/skip-link.json index 2ac4f5ff0..b6fac58ca 100644 --- a/packages/ui/dist/contracts/skip-link.json +++ b/packages/ui/dist/contracts/skip-link.json @@ -289,6 +289,6 @@ "copy": { "directory": "copy/skip-link/", "manifest": "copy/skip-link/manifest.json", - "digest": "sha256-DLQ8IJEF+7r/cxXoKME+WMqTOVaJevkgDMVRXjTEk0E=" + "digest": "sha256-/jHANaZlfExigzc9YSvrmpKwOgJsNkh3BLB4kOMIj5c=" } } diff --git a/packages/ui/dist/contracts/switch.json b/packages/ui/dist/contracts/switch.json index 7f814dd98..8b4b16a5e 100644 --- a/packages/ui/dist/contracts/switch.json +++ b/packages/ui/dist/contracts/switch.json @@ -395,6 +395,6 @@ "copy": { "directory": "copy/switch/", "manifest": "copy/switch/manifest.json", - "digest": "sha256-ro51Jzhx8KR2dDJCRqTKB5jNf8Mnc8kBcTaICxcws1A=" + "digest": "sha256-YSfVQXXYORkF8TYDuvw8UDQFQ0C2BvhbCcgmyhHx5aE=" } } diff --git a/packages/ui/dist/contracts/table.json b/packages/ui/dist/contracts/table.json index 5e4fe84e6..9f7a6d812 100644 --- a/packages/ui/dist/contracts/table.json +++ b/packages/ui/dist/contracts/table.json @@ -429,6 +429,6 @@ "copy": { "directory": "copy/table/", "manifest": "copy/table/manifest.json", - "digest": "sha256-5x3hanzyxLH3nwERe8/wI2TB7i4kSwR2pISz0yLa+gk=" + "digest": "sha256-uE41ppP3fPQSO1RWxPnhd8Zoqlh9cVyfgTKwwVT5Ajs=" } } diff --git a/packages/ui/dist/contracts/tabs.json b/packages/ui/dist/contracts/tabs.json index 5ff7c31d2..f150ca10d 100644 --- a/packages/ui/dist/contracts/tabs.json +++ b/packages/ui/dist/contracts/tabs.json @@ -398,6 +398,6 @@ "copy": { "directory": "copy/tabs/", "manifest": "copy/tabs/manifest.json", - "digest": "sha256-aW2OMAJ7OKTFBe9zF9B4eVsJyynDgRIDkBVaDylHtNo=" + "digest": "sha256-PM9hfuUIQtvrIekuc8ckBWWQXjPFXTSvcBTd9ovfoQY=" } } diff --git a/packages/ui/dist/contracts/terminal.json b/packages/ui/dist/contracts/terminal.json index 5b3aff4eb..67217d06f 100644 --- a/packages/ui/dist/contracts/terminal.json +++ b/packages/ui/dist/contracts/terminal.json @@ -536,6 +536,6 @@ "copy": { "directory": "copy/terminal/", "manifest": "copy/terminal/manifest.json", - "digest": "sha256-sGsy8R0eqkr6bURvIwkRkH0fLyTW8pfdEwky7NiayLM=" + "digest": "sha256-Um+BronLZKEFOHCEpSta1jnlVHpAUaE+SY2iEDpTXgA=" } } diff --git a/packages/ui/dist/contracts/text-field.json b/packages/ui/dist/contracts/text-field.json index 7d1d73d4f..3a6aa6cba 100644 --- a/packages/ui/dist/contracts/text-field.json +++ b/packages/ui/dist/contracts/text-field.json @@ -536,6 +536,6 @@ "copy": { "directory": "copy/text-field/", "manifest": "copy/text-field/manifest.json", - "digest": "sha256-NnrVBWko4HWPhGkBoIYnMm5jYnXwd76OdbC8XdlUoFc=" + "digest": "sha256-T+FFVaCn+rM3sQkUSAo7Rt0qWttJ1BhryEiHTCNVafE=" } } diff --git a/packages/ui/dist/contracts/textarea.json b/packages/ui/dist/contracts/textarea.json index 0633b1923..90c4402d2 100644 --- a/packages/ui/dist/contracts/textarea.json +++ b/packages/ui/dist/contracts/textarea.json @@ -493,6 +493,6 @@ "copy": { "directory": "copy/textarea/", "manifest": "copy/textarea/manifest.json", - "digest": "sha256-VeZRrTxwhFU2bJcDBQUPI68/dFzyc1GVu0w9WcbtTXU=" + "digest": "sha256-TWjfrH63Bc/kflpuBQDJbS27RePsfSb9IsUWdkGRiwA=" } } diff --git a/packages/ui/dist/contracts/time-picker.json b/packages/ui/dist/contracts/time-picker.json index a47c56ef5..1f2def6ca 100644 --- a/packages/ui/dist/contracts/time-picker.json +++ b/packages/ui/dist/contracts/time-picker.json @@ -567,6 +567,6 @@ "copy": { "directory": "copy/time-picker/", "manifest": "copy/time-picker/manifest.json", - "digest": "sha256-wxpcgxJ9Gi6UvCUrDp9dioJK7/5dGvvJ8K3LZNbXyqM=" + "digest": "sha256-6dQepccMEMurDmXDGAXKgSfV2lWmb9ekpIZ/3hodceI=" } } diff --git a/packages/ui/dist/contracts/timeline.json b/packages/ui/dist/contracts/timeline.json index 2c0f18742..0694bf216 100644 --- a/packages/ui/dist/contracts/timeline.json +++ b/packages/ui/dist/contracts/timeline.json @@ -282,6 +282,6 @@ "copy": { "directory": "copy/timeline/", "manifest": "copy/timeline/manifest.json", - "digest": "sha256-xTdi7g85GA2tcVyJWhakoizpwEDxFhF3UjuOxkrx1Jg=" + "digest": "sha256-0Or3Y8Tm/QMqmLp4lpUHlYERYtvsxQV0B7ZW9XTw6fg=" } } diff --git a/packages/ui/dist/contracts/toast.json b/packages/ui/dist/contracts/toast.json index fd1ff0e41..0207e655b 100644 --- a/packages/ui/dist/contracts/toast.json +++ b/packages/ui/dist/contracts/toast.json @@ -524,6 +524,6 @@ "copy": { "directory": "copy/toast/", "manifest": "copy/toast/manifest.json", - "digest": "sha256-Dulou4hwI8bILLX7ogZBb3IkLJsGcenBCv2301DmbKo=" + "digest": "sha256-5G6eFKtb0RzEvUaf7y/U2BUwja0sO/DtWmx8/bruQU8=" } } diff --git a/packages/ui/dist/contracts/toolbar.json b/packages/ui/dist/contracts/toolbar.json index 313817688..e867e48c9 100644 --- a/packages/ui/dist/contracts/toolbar.json +++ b/packages/ui/dist/contracts/toolbar.json @@ -533,6 +533,6 @@ "copy": { "directory": "copy/toolbar/", "manifest": "copy/toolbar/manifest.json", - "digest": "sha256-Nqfa3AzsL73Ep9jP3gvG3YBOW8qyTGnIZrjSd6zpcWY=" + "digest": "sha256-8hlyqGGelr15H1t7evcG0FBb95rGUZnTNnn/7YboC68=" } } diff --git a/packages/ui/dist/contracts/tooltip.json b/packages/ui/dist/contracts/tooltip.json index bb533235c..e6845887a 100644 --- a/packages/ui/dist/contracts/tooltip.json +++ b/packages/ui/dist/contracts/tooltip.json @@ -357,6 +357,6 @@ "copy": { "directory": "copy/tooltip/", "manifest": "copy/tooltip/manifest.json", - "digest": "sha256-QxjcDTsBx4LoM8mRkg4NgUQUatj3fHOwB6EKt8pWLZw=" + "digest": "sha256-LkcqlVgeLQw44bCRmlXlSU+9P8cA2jVRRTLSgZlvDps=" } } diff --git a/packages/ui/dist/contracts/tree.json b/packages/ui/dist/contracts/tree.json index 28a5e619c..1943dc577 100644 --- a/packages/ui/dist/contracts/tree.json +++ b/packages/ui/dist/contracts/tree.json @@ -339,6 +339,6 @@ "copy": { "directory": "copy/tree/", "manifest": "copy/tree/manifest.json", - "digest": "sha256-4RUETiVuDpUfhbB64T/WAejSHUEhFEXHJnLzKNXk140=" + "digest": "sha256-b/wUhzdct+NttP79qt24e+b3XsS9ej8bN1kxxKgJ7m8=" } } diff --git a/packages/ui/dist/contracts/wizard.json b/packages/ui/dist/contracts/wizard.json index 075df7747..045711804 100644 --- a/packages/ui/dist/contracts/wizard.json +++ b/packages/ui/dist/contracts/wizard.json @@ -631,6 +631,6 @@ "copy": { "directory": "copy/wizard/", "manifest": "copy/wizard/manifest.json", - "digest": "sha256-iGsA8lMX0V0Ipmib1881C1nGntn+vXPGfd3lDDhhYaM=" + "digest": "sha256-m2daflOEDFk6WotvcUWzd9v4LCJpXkBoOyA2h+etXNI=" } } diff --git a/packages/ui/dist/copy/admin-form/manifest.json b/packages/ui/dist/copy/admin-form/manifest.json index fbbf10e3a..ca39230b9 100644 --- a/packages/ui/dist/copy/admin-form/manifest.json +++ b/packages/ui/dist/copy/admin-form/manifest.json @@ -30,7 +30,7 @@ "runtime/components/select.js": "sha256-yyq0jsJOysQGTPpFoA1C1aRWSIukrk+M4Ro2ZwCyWbw=", "runtime/components/admin-form.js": "sha256-aN07ea+gUj6aAxwJjeILpqJFPUQJ27g3LAIjpHmljNg=", "runtime/chunks/forms-BT3z7lNC.js": "sha256-Txmae07dWLj1H/FL869U0Kv84TQxzpdFeOg0g8zGK6I=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Of5oLJY6n5Yfqu44/xCAuuJEYRoCg4Kr+YZbVggbwZE=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-TRLraonRxggrZcfXS9jlN+nTIOpRHiXbMKQNm8NbR2A=", diff --git a/packages/ui/dist/copy/admin-form/tokens.css b/packages/ui/dist/copy/admin-form/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/admin-form/tokens.css +++ b/packages/ui/dist/copy/admin-form/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/alert/manifest.json b/packages/ui/dist/copy/alert/manifest.json index c27181697..b8ba01ebd 100644 --- a/packages/ui/dist/copy/alert/manifest.json +++ b/packages/ui/dist/copy/alert/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/alert.js": "sha256-afRZEs1g1g0l5Fh9oTXjl7R4w6ChNBFZ+N8x/BeJexg=", "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-cEV4WAKxLNKgYY5pU9nDVSG4toj5mM7vGZwyE+6Ui8o=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-QUAq9dxIFB1jlxB27CrSrEZKRLa4rC6qRLbWmR2t/ug=", diff --git a/packages/ui/dist/copy/alert/tokens.css b/packages/ui/dist/copy/alert/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/alert/tokens.css +++ b/packages/ui/dist/copy/alert/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/avatar/manifest.json b/packages/ui/dist/copy/avatar/manifest.json index 88d890514..20d0a101a 100644 --- a/packages/ui/dist/copy/avatar/manifest.json +++ b/packages/ui/dist/copy/avatar/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/avatar.js": "sha256-ewC6RhKRQwH+7jEF62lU5q8KPwKXfyEg/JWISD2N/FE=", "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-XYCR7yVoWMnpJrQG4A+pL3xESyHR6OKMuwJfZGgDpKA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-R1Q+6UFu76jOlVP9cadBrMxVS3+Yb2JgIDkcnKxWvtk=", diff --git a/packages/ui/dist/copy/avatar/tokens.css b/packages/ui/dist/copy/avatar/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/avatar/tokens.css +++ b/packages/ui/dist/copy/avatar/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/badge/manifest.json b/packages/ui/dist/copy/badge/manifest.json index ac71ead8b..caf8d9313 100644 --- a/packages/ui/dist/copy/badge/manifest.json +++ b/packages/ui/dist/copy/badge/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/badge.js": "sha256-l72iC8CAJp/xCXpSX/oJ3xsz8VT4N6UAcVhVSKeC/zs=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-K2TPkFZfKUt35HniL/ub9icdMukZ7wCx0S5+D1FOv8Y=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-rXaOLdDbEK5SMtYsw5TegOMtcnLijmgtU07RVrvJx8o=", diff --git a/packages/ui/dist/copy/badge/tokens.css b/packages/ui/dist/copy/badge/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/badge/tokens.css +++ b/packages/ui/dist/copy/badge/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/breadcrumbs/manifest.json b/packages/ui/dist/copy/breadcrumbs/manifest.json index a21bd93d9..a0c181c65 100644 --- a/packages/ui/dist/copy/breadcrumbs/manifest.json +++ b/packages/ui/dist/copy/breadcrumbs/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/breadcrumbs.js": "sha256-GtJDiM9iN77t0CIkD7Feiu8A1MQ5DeirIUfSVxO6o7Q=", "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-pJjvksTD6NTZ2QRx/SBxS4j7xy1rVLprovo5OnTOafs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-W9qk0XtcetNK1me7748lByEMSMUZyP6NT//vet/Kt0I=", diff --git a/packages/ui/dist/copy/breadcrumbs/tokens.css b/packages/ui/dist/copy/breadcrumbs/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/breadcrumbs/tokens.css +++ b/packages/ui/dist/copy/breadcrumbs/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/button-group/manifest.json b/packages/ui/dist/copy/button-group/manifest.json index d0164cc8e..f85380925 100644 --- a/packages/ui/dist/copy/button-group/manifest.json +++ b/packages/ui/dist/copy/button-group/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/button-group.js": "sha256-9kyXdp1HjHBA1/8MAvS/4B8TzQnyUUIVFbxkMteeCH4=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-f5VJ2bwUNXUnsb5AcdxUYbcOC7PeghM/cnXvDSuGuMs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-4NLobHuAfZnWUQDNQ3ENH9ucyjTTUTD6gk0XV7SHGng=", diff --git a/packages/ui/dist/copy/button-group/tokens.css b/packages/ui/dist/copy/button-group/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/button-group/tokens.css +++ b/packages/ui/dist/copy/button-group/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/button/manifest.json b/packages/ui/dist/copy/button/manifest.json index 6bad16451..c3b593350 100644 --- a/packages/ui/dist/copy/button/manifest.json +++ b/packages/ui/dist/copy/button/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/button.js": "sha256-uMPPvidQWPs9e0OGW6Q+cI2izylinOUSgrBAM94vxAA=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-79ycU5ojNv1Z2yHzJ6KXDmshFL1we3mQNOoIwfMXnyg=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-kLEcMMhF4Tv+byKkImEgGIqqR+QYh6uOOCz/mg5hkPs=", diff --git a/packages/ui/dist/copy/button/tokens.css b/packages/ui/dist/copy/button/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/button/tokens.css +++ b/packages/ui/dist/copy/button/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/card/manifest.json b/packages/ui/dist/copy/card/manifest.json index 8ea13539a..e606058b0 100644 --- a/packages/ui/dist/copy/card/manifest.json +++ b/packages/ui/dist/copy/card/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/card.js": "sha256-REUcny20Az6YiLn0F6l0ZkmNrj18xAqRj9bWUmvkhLo=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-pfXQBPkrp6iF0OlQiLQh9DMUwtsCinOaL1HLAjlChII=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Rc0IwITP8X0cKscYMBt4LgzFbntPHkCAdDQ4xLh2LXs=", diff --git a/packages/ui/dist/copy/card/tokens.css b/packages/ui/dist/copy/card/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/card/tokens.css +++ b/packages/ui/dist/copy/card/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/chart/manifest.json b/packages/ui/dist/copy/chart/manifest.json index b6f7205da..72e49bb9b 100644 --- a/packages/ui/dist/copy/chart/manifest.json +++ b/packages/ui/dist/copy/chart/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/chart.js": "sha256-J4rkX+ylh8URHbl2DxJ2FtbkHBtan2UOpNGVJIh1LjQ=", "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-/W9/IEOepx6zAHtGcRJs1x0lwfMFkVEiYDCV4y4byXw=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Wk7EuPuisom2ohEBkZvcgafrpN7xXzlCUaNrWq7BZEA=", diff --git a/packages/ui/dist/copy/chart/tokens.css b/packages/ui/dist/copy/chart/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/chart/tokens.css +++ b/packages/ui/dist/copy/chart/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/checkbox/manifest.json b/packages/ui/dist/copy/checkbox/manifest.json index 77a59c697..d32a6ce7d 100644 --- a/packages/ui/dist/copy/checkbox/manifest.json +++ b/packages/ui/dist/copy/checkbox/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/checkbox.js": "sha256-dKDUoVoQi9btazDX3FlRb0fnVzLkYEN+W08CewNGTnI=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-PpwiBtqgcGIHn1KgKDXvrsX0DeTZ4PfyQsMnUpwCUrI=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-D5pZAWuWF8+C90nVIZnSREv1i0fk6q9L+6SEdvU1Okk=", diff --git a/packages/ui/dist/copy/checkbox/tokens.css b/packages/ui/dist/copy/checkbox/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/checkbox/tokens.css +++ b/packages/ui/dist/copy/checkbox/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/chip/manifest.json b/packages/ui/dist/copy/chip/manifest.json index 06e848f6b..2ca77473a 100644 --- a/packages/ui/dist/copy/chip/manifest.json +++ b/packages/ui/dist/copy/chip/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/chip.js": "sha256-u34FDCir8vK2ro61A5etBvzomb22WIhnIx7vL6Xcf3k=", "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-nKS3XC8eLjQCMMZHRRKSiHiaNGZgYD6CXzVULJoDU3g=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-yjXdYrZ4DqpcZ/ZDGxD0cgfYY/xqj0qeSkX1dJmVhfY=", diff --git a/packages/ui/dist/copy/chip/tokens.css b/packages/ui/dist/copy/chip/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/chip/tokens.css +++ b/packages/ui/dist/copy/chip/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/code-editor/manifest.json b/packages/ui/dist/copy/code-editor/manifest.json index 45c158724..86ba2212d 100644 --- a/packages/ui/dist/copy/code-editor/manifest.json +++ b/packages/ui/dist/copy/code-editor/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/code-editor.js": "sha256-F0O1Zc5wQaq5NGzIEEBzGXHEfj0hUaCR23D2hnUukLY=", "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-X9h2Mxr0yLKLoKffZDsC55HBiRmSX+SuRQkjkcxerOo=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-aD+1gDxKB5fijO+A+hjuTqChvHPDv5zp5tK9UPZhwLc=", diff --git a/packages/ui/dist/copy/code-editor/tokens.css b/packages/ui/dist/copy/code-editor/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/code-editor/tokens.css +++ b/packages/ui/dist/copy/code-editor/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/combobox/manifest.json b/packages/ui/dist/copy/combobox/manifest.json index a2095a84a..7da01c962 100644 --- a/packages/ui/dist/copy/combobox/manifest.json +++ b/packages/ui/dist/copy/combobox/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/combobox.js": "sha256-5b1Sa2zwhRyysK9sVyLiBCGsYfJyYnfGDsb6r3sA9MA=", "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-f4pI9RLIKYsRggzuVcLA2zYdXHZXY3+DbGFjvBCtbSg=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-/SDEtn3D/9kfnULtpHPFEgK1FAkmwe+77gdxlWNewhY=", diff --git a/packages/ui/dist/copy/combobox/tokens.css b/packages/ui/dist/copy/combobox/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/combobox/tokens.css +++ b/packages/ui/dist/copy/combobox/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/command-palette/manifest.json b/packages/ui/dist/copy/command-palette/manifest.json index ca736a03b..3fd9e71e4 100644 --- a/packages/ui/dist/copy/command-palette/manifest.json +++ b/packages/ui/dist/copy/command-palette/manifest.json @@ -18,7 +18,7 @@ "runtime/components/command-palette.js": "sha256-KMSKyY2a0yyVe6zxGdWjBFFsgbL/DjNUvU8lnxB6USQ=", "runtime/chunks/advanced-DCpe8Ndv.js": "sha256-nr1LFdLYsGeTM4vDyldvuJygRm0F04sYonxatySPu1g=", "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-sXrks2txpylBLDX4L9vKPIvAj11p73qrX0apfh7EgTg=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-mNRkLE+yYA4PARM4rv5bXDj90Oq8yxQLPgoUW8bX6ns=", diff --git a/packages/ui/dist/copy/command-palette/tokens.css b/packages/ui/dist/copy/command-palette/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/command-palette/tokens.css +++ b/packages/ui/dist/copy/command-palette/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/compact-dashboard/manifest.json b/packages/ui/dist/copy/compact-dashboard/manifest.json index 4fd1447ee..135342a39 100644 --- a/packages/ui/dist/copy/compact-dashboard/manifest.json +++ b/packages/ui/dist/copy/compact-dashboard/manifest.json @@ -24,7 +24,7 @@ "runtime/components/compact-dashboard.js": "sha256-AyJRimILR3ZhpG7LU6Jtut1sQj0LSEFhOC9MT+gVfbQ=", "runtime/chunks/compositions-d6BkKTYf.js": "sha256-El5csGAVMeeZWmJ1ztdXW3O3t2AQPrf3YrEOMkGX17c=", "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-CK9kd2wDntxSLF6J4F4+3SFybCPdr/tSqL7xJpw3hFs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-I++zY2714BqcfCh02WgcXCFwujrwXLK4TwP9wII+QE4=", diff --git a/packages/ui/dist/copy/compact-dashboard/tokens.css b/packages/ui/dist/copy/compact-dashboard/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/compact-dashboard/tokens.css +++ b/packages/ui/dist/copy/compact-dashboard/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/data-table/manifest.json b/packages/ui/dist/copy/data-table/manifest.json index f3dd67e9a..98d99f255 100644 --- a/packages/ui/dist/copy/data-table/manifest.json +++ b/packages/ui/dist/copy/data-table/manifest.json @@ -22,7 +22,7 @@ "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", "runtime/components/data-table.js": "sha256-jj60XwNxQlssKZTff5HB9Z6v14UDZdK8O80kLP082l4=", "runtime/chunks/tables-B25ydUHs.js": "sha256-XqRdyfrSS93rVybWHq6a0WhrmZgaboHi5n8ymgwRbM8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-aygLfHiZmFXenQHQrHnjVcw8W0tp2SLdB7d/laGcKgA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-FieIuPCt66UIxpdAH0wuPBOrPEVXUqjJfyWMyCdO9nI=", diff --git a/packages/ui/dist/copy/data-table/tokens.css b/packages/ui/dist/copy/data-table/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/data-table/tokens.css +++ b/packages/ui/dist/copy/data-table/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/date-picker/manifest.json b/packages/ui/dist/copy/date-picker/manifest.json index 1e72b72cf..7bbe89754 100644 --- a/packages/ui/dist/copy/date-picker/manifest.json +++ b/packages/ui/dist/copy/date-picker/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/date-picker.js": "sha256-rglCYTqoXYDZ63YUb01UqeMk0HRjOeYkVcqadAX0qmM=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-InOm4+AU0uQu6XZs3K+f13FA89Jf7iQO1GuL/2+s9YA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Nho5WRdNWOIx9zrVkZR8s5NrC95hgRBVnvDTdnZ7qoo=", diff --git a/packages/ui/dist/copy/date-picker/tokens.css b/packages/ui/dist/copy/date-picker/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/date-picker/tokens.css +++ b/packages/ui/dist/copy/date-picker/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/description-list/manifest.json b/packages/ui/dist/copy/description-list/manifest.json index 6b1cd3df4..f447ddfb2 100644 --- a/packages/ui/dist/copy/description-list/manifest.json +++ b/packages/ui/dist/copy/description-list/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/description-list.js": "sha256-qKd9CujEm+EgRSZfWHW9YXH9JY/d5wMBkkfqqP3z5so=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-MvWyrX2+45DLgWL1ZxTdk0IFVjl5WyfGYZdOYpIeoak=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-h2HPGz9Kz0LvMiuTC767wAQvYHOVVmffDECwh46tG0c=", diff --git a/packages/ui/dist/copy/description-list/tokens.css b/packages/ui/dist/copy/description-list/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/description-list/tokens.css +++ b/packages/ui/dist/copy/description-list/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/diagnostics/manifest.json b/packages/ui/dist/copy/diagnostics/manifest.json index 467ea3b3f..206999afe 100644 --- a/packages/ui/dist/copy/diagnostics/manifest.json +++ b/packages/ui/dist/copy/diagnostics/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/diagnostics.js": "sha256-nC94tOw1MCiaCz5hbJRQf8qjWzQDz53K24KiwRwR8ws=", "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-1uXLsplg978riCNhv/v5p+RvR0hW6fVdRnKgNUo+IYs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-oPPp/R+dnwC1tnH/Td+Hlrs3CRODUkA4Bvq/HK/fAUU=", diff --git a/packages/ui/dist/copy/diagnostics/tokens.css b/packages/ui/dist/copy/diagnostics/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/diagnostics/tokens.css +++ b/packages/ui/dist/copy/diagnostics/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/dialog/manifest.json b/packages/ui/dist/copy/dialog/manifest.json index c3e961b09..3ba912853 100644 --- a/packages/ui/dist/copy/dialog/manifest.json +++ b/packages/ui/dist/copy/dialog/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/dialog.js": "sha256-e9pTCjxk1e95o6PW5WuKLJsHz87/SQRFeL9+DTQyk5I=", "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-d4bh9HaP4YOtfgWmP42qVqw3nqSJ3DF629AWjqoZTn4=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-wFFtRxUFWBTzxYOcblp+JjddYxJQF3QKoOb0/hIuSL0=", diff --git a/packages/ui/dist/copy/dialog/tokens.css b/packages/ui/dist/copy/dialog/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/dialog/tokens.css +++ b/packages/ui/dist/copy/dialog/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/diff-view/manifest.json b/packages/ui/dist/copy/diff-view/manifest.json index bb9423bd5..8b99563fd 100644 --- a/packages/ui/dist/copy/diff-view/manifest.json +++ b/packages/ui/dist/copy/diff-view/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/diff-view.js": "sha256-QfZm092MHlNhP9Vfs6IkWjXkbrGughYsBfHTOCL93cM=", "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-mibFUolrx0OWHlYNpEFTvfkMI0c6h4CUv7SWJ4eQVns=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-t7cx4Y+4qhIPiwFbRPz+6U12N/CFATPTfG7/iZf85zs=", diff --git a/packages/ui/dist/copy/diff-view/tokens.css b/packages/ui/dist/copy/diff-view/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/diff-view/tokens.css +++ b/packages/ui/dist/copy/diff-view/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/disclosure/manifest.json b/packages/ui/dist/copy/disclosure/manifest.json index 4b35acab6..73af296bf 100644 --- a/packages/ui/dist/copy/disclosure/manifest.json +++ b/packages/ui/dist/copy/disclosure/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/disclosure.js": "sha256-T++duSnTm8ippxMGxtM25ykxUO+HYIt0HK55RkVOrHQ=", "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-vVNjPU0AXLKLnxgRPgOVmN3dS6S3pxA6xLFfJFK8ex4=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-ZbpW/j8ZGKofIgL/uVEO47xXhxXmS2mrK5w32n/BWZA=", diff --git a/packages/ui/dist/copy/disclosure/tokens.css b/packages/ui/dist/copy/disclosure/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/disclosure/tokens.css +++ b/packages/ui/dist/copy/disclosure/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/drawer/manifest.json b/packages/ui/dist/copy/drawer/manifest.json index f063c5274..e0561f3ec 100644 --- a/packages/ui/dist/copy/drawer/manifest.json +++ b/packages/ui/dist/copy/drawer/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/drawer.js": "sha256-vwjZdEg2SybEwAsIBL+uJuAs6ArJnLfrtqdRiOtleqA=", "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-39DmGp3B3f8+C/QGAv6xbiVXT7QviSaVCnHk8XpC158=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-RNAiKQJPioHCtfhMtqcsFaQFfwhKvdH+iIfLXOWo6QQ=", diff --git a/packages/ui/dist/copy/drawer/tokens.css b/packages/ui/dist/copy/drawer/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/drawer/tokens.css +++ b/packages/ui/dist/copy/drawer/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/editor-search/manifest.json b/packages/ui/dist/copy/editor-search/manifest.json index ad32c7aac..d985021fd 100644 --- a/packages/ui/dist/copy/editor-search/manifest.json +++ b/packages/ui/dist/copy/editor-search/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/editor-search.js": "sha256-tPLpeyxQ/8Gf/LImxqGBvRraQE6oFXtqIspmI84b8XA=", "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-M0SrYSnjmhmwR0wfAiNg1VU3bXhEQkYknaGRLw0fWMM=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-d4aAYzdcDHNmdiry3w1Y3xEHMEA6MELYHpoj25fZY7M=", diff --git a/packages/ui/dist/copy/editor-search/tokens.css b/packages/ui/dist/copy/editor-search/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/editor-search/tokens.css +++ b/packages/ui/dist/copy/editor-search/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/empty-state/manifest.json b/packages/ui/dist/copy/empty-state/manifest.json index 4c8c8ea64..93927f1fc 100644 --- a/packages/ui/dist/copy/empty-state/manifest.json +++ b/packages/ui/dist/copy/empty-state/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/empty-state.js": "sha256-bmsYB/w+TevvaR9K+tvrVuNDGxVPv2PYR4hbTkhw+dU=", "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Mdd72ooxolJDcPYScpT7yUM7Uj1SV5nk9LuG9vP0EeA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-j6rKuP4LmxmaKm47ZcfAqQ0LKMqN7l90HZwvUydHutQ=", diff --git a/packages/ui/dist/copy/empty-state/tokens.css b/packages/ui/dist/copy/empty-state/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/empty-state/tokens.css +++ b/packages/ui/dist/copy/empty-state/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/error-state/manifest.json b/packages/ui/dist/copy/error-state/manifest.json index 7c323c404..6e0ab789d 100644 --- a/packages/ui/dist/copy/error-state/manifest.json +++ b/packages/ui/dist/copy/error-state/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/error-state.js": "sha256-vgUhuSmkAd9uc2x8r5Oc5k2rjzWbEtFRnrR0smV/YqM=", "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-CdLPhgSZDY0ucB4/nfZpfphuYXcfoqslUTPyuhz2tDw=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-ORjrriOpBHk2VlqSsyeUSEs1medDwB5oaTT4RxrXLFs=", diff --git a/packages/ui/dist/copy/error-state/tokens.css b/packages/ui/dist/copy/error-state/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/error-state/tokens.css +++ b/packages/ui/dist/copy/error-state/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/field/manifest.json b/packages/ui/dist/copy/field/manifest.json index 4cb608a96..0f4ae8b86 100644 --- a/packages/ui/dist/copy/field/manifest.json +++ b/packages/ui/dist/copy/field/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/field.js": "sha256-pEHbl120kbYNPym5N03ZxIzOQFPHyq+rELTr9RnR2tg=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Rd3CCjOeRNdq9v3ql8A+P+nyw3MOp7Fa0LUD8UqBzFA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-M+Faw3Q4PMYCRgzzkpyGYO6m3Sefbyj3JZ3/wdlvGPU=", diff --git a/packages/ui/dist/copy/field/tokens.css b/packages/ui/dist/copy/field/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/field/tokens.css +++ b/packages/ui/dist/copy/field/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/fieldset/manifest.json b/packages/ui/dist/copy/fieldset/manifest.json index fd24f6f69..193d37cd3 100644 --- a/packages/ui/dist/copy/fieldset/manifest.json +++ b/packages/ui/dist/copy/fieldset/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/fieldset.js": "sha256-pAzVFWN+M793N7lFAZ2zTybWJLdSOqZl3AmOTomqmTk=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-TPi15SfEwAaSl4PqQvGAd3bFbbB4BJ2trfD5k2+8yrc=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Z916I2upHIzzffRAz/6w6FSTBwegAd+L49E9Juck2fo=", diff --git a/packages/ui/dist/copy/fieldset/tokens.css b/packages/ui/dist/copy/fieldset/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/fieldset/tokens.css +++ b/packages/ui/dist/copy/fieldset/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/file-browser/manifest.json b/packages/ui/dist/copy/file-browser/manifest.json index 9a3b75e6c..7c1fc8b28 100644 --- a/packages/ui/dist/copy/file-browser/manifest.json +++ b/packages/ui/dist/copy/file-browser/manifest.json @@ -26,7 +26,7 @@ "runtime/components/file-browser.js": "sha256-mmsIwfdO+8Xy7vrRylWFBDIwAoWKfkgmb8J17rxDHVs=", "runtime/chunks/compositions-d6BkKTYf.js": "sha256-El5csGAVMeeZWmJ1ztdXW3O3t2AQPrf3YrEOMkGX17c=", "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-jXsUncF3ZqNTAY54eALB2XHlOFiiumSXp+AnM14Tz1Q=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-TbSmPr7cV31g3WqgPi6LboOGQdmgxz/89Tf/3ld2pfU=", diff --git a/packages/ui/dist/copy/file-browser/tokens.css b/packages/ui/dist/copy/file-browser/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/file-browser/tokens.css +++ b/packages/ui/dist/copy/file-browser/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/file-input/manifest.json b/packages/ui/dist/copy/file-input/manifest.json index dc709e031..ca770ef41 100644 --- a/packages/ui/dist/copy/file-input/manifest.json +++ b/packages/ui/dist/copy/file-input/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/file-input.js": "sha256-b5A8PD7vS8/xWNzSdVbtt2pV33CllxtkKwdSPtC1CSI=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-ezg9wydBGR6KpQziZgvoKiTXURNTPkh+aD9h3vFuuW4=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-3MysNuXXyX6HzlWv0wFhnto4CU9Q/n0JHK2wx1ufwbE=", diff --git a/packages/ui/dist/copy/file-input/tokens.css b/packages/ui/dist/copy/file-input/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/file-input/tokens.css +++ b/packages/ui/dist/copy/file-input/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/filterable-table/manifest.json b/packages/ui/dist/copy/filterable-table/manifest.json index 62392db41..3d57ef133 100644 --- a/packages/ui/dist/copy/filterable-table/manifest.json +++ b/packages/ui/dist/copy/filterable-table/manifest.json @@ -22,7 +22,7 @@ "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", "runtime/components/filterable-table.js": "sha256-1tup9iQXvwHywM5vJL3oiz0gLiDGNw/xjkZ91AA+Sok=", "runtime/chunks/tables-B25ydUHs.js": "sha256-XqRdyfrSS93rVybWHq6a0WhrmZgaboHi5n8ymgwRbM8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-ZpN1xEJy4fV/PBDvH91mkuN2CZqhCUo5wpeCs27jREo=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-3PbF9wWtnKy3q07M9x690D730biEbSwu20wHAcvPPEE=", diff --git a/packages/ui/dist/copy/filterable-table/tokens.css b/packages/ui/dist/copy/filterable-table/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/filterable-table/tokens.css +++ b/packages/ui/dist/copy/filterable-table/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/form-builder/manifest.json b/packages/ui/dist/copy/form-builder/manifest.json index 805c0a843..76ce18794 100644 --- a/packages/ui/dist/copy/form-builder/manifest.json +++ b/packages/ui/dist/copy/form-builder/manifest.json @@ -7,20 +7,20 @@ "register/form-builder.js", "chunks/element-C1XeXVYC.js", "chunks/choice-Db_w_BOQ.js", - "chunks/form-builder-Dkweb1xD.js", - "chunks/form-builder-EQnl1AaR.js", + "chunks/form-builder-C6Rhfsz6.js", + "chunks/form-builder-C5Kx5G9b.js", "chunks/form-workflow-DMGni-Gs.js", "chunks/markup-DeQ4bEMR.js" ], "files": { - "runtime/register/form-builder.js": "sha256-jo5ONsFuzPH0pmoDpmWyq6QVpkKeKDhZYbwW/vKQ+ic=", + "runtime/register/form-builder.js": "sha256-eM9TDYrxREfT+vaywPQ8TCrx3X7gAB/fXuj8viaqKzM=", "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/chunks/form-builder-Dkweb1xD.js": "sha256-y1g6oI2gMoPy6c5S5Lgoec9Po3ydkEadsbsL5vVWFUI=", - "runtime/chunks/form-builder-EQnl1AaR.js": "sha256-lX4d482lke5Pljjn6rKPas9RRdIWgoifB609las09JY=", + "runtime/chunks/form-builder-C6Rhfsz6.js": "sha256-CnwUvLr0BCPWw5F9dlDy1D8Y73slv5huNge/LK40+x8=", + "runtime/chunks/form-builder-C5Kx5G9b.js": "sha256-H2Zi4dAojDJ5ZF7OQWEPsPaCg3kMBiAVVG1k948Yiuw=", "runtime/chunks/form-workflow-DMGni-Gs.js": "sha256-g3g/Afxx3XsClDK4ZfvWQjZKprT6z7Qp1lULS48F0rY=", "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-dgVsrgYuHrvBt6OjTg069abl7yU4iwgXOXUw3n9cB7g=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-vq61pWv0xeMFu0tTsDtRWWpAr16AFefjpz5JTSyF440=", diff --git a/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-EQnl1AaR.js b/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-C5Kx5G9b.js similarity index 99% rename from packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-EQnl1AaR.js rename to packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-C5Kx5G9b.js index bb6438b9f..28f2bf5b9 100644 --- a/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-EQnl1AaR.js +++ b/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-C5Kx5G9b.js @@ -69,7 +69,7 @@ var identity_default = { name: "j3w1-theme", version: "4.0.0", profile: "default", - sourceDigest: "sha256-0pGYzXZFMWkGlbzNIlyxfInXr3Pog+Q6PuQTyO1Rbu0=" + sourceDigest: "sha256-KNf9QNXsLy6MzEixJdv+LTT8TglJJgE7H0JwMdzpjfA=" }; //#endregion //#region packages/ui/src/internal/form-builder.js diff --git a/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-Dkweb1xD.js b/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-C6Rhfsz6.js similarity index 92% rename from packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-Dkweb1xD.js rename to packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-C6Rhfsz6.js index 18dfbad3c..2daa2e07f 100644 --- a/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-Dkweb1xD.js +++ b/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-C6Rhfsz6.js @@ -1,5 +1,5 @@ import { t as J3w1Element } from "./element-C1XeXVYC.js"; -import { t as mountBuilder } from "./form-builder-EQnl1AaR.js"; +import { t as mountBuilder } from "./form-builder-C5Kx5G9b.js"; //#region packages/ui/src/behaviors/form-builder.js function formBuilder(root, { signal }) { const editor = root.querySelector("[data-builder]"); @@ -22,7 +22,7 @@ function formBuilder(root, { signal }) { var J3w1FormBuilder = class extends J3w1Element { static componentId = "form-builder"; static version = "4.0.0"; - static implementationId = "sha256-QcTsnt2RqgWKuYJuM/x0uqMUtYY2cGEONH+jVvm2nuY="; + static implementationId = "sha256-uXS+kL7KbvfhlApDhEsvMY+pFsX9bHFlaTF/qUH94mE="; static connect = formBuilder; static upgradeProperties = [ "disabled", 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 a723c3c65..320e671f8 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,5 +1,5 @@ import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; -import { t as J3w1FormBuilder } from "../chunks/form-builder-Dkweb1xD.js"; +import { t as J3w1FormBuilder } from "../chunks/form-builder-C6Rhfsz6.js"; //#region .cache/ui-build/entries/register/form-builder.js var element = registerElement("j3w1-form-builder", J3w1FormBuilder); //#endregion diff --git a/packages/ui/dist/copy/form-builder/tokens.css b/packages/ui/dist/copy/form-builder/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/form-builder/tokens.css +++ b/packages/ui/dist/copy/form-builder/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/i3-window-frame/manifest.json b/packages/ui/dist/copy/i3-window-frame/manifest.json index 049875715..ba2dedb27 100644 --- a/packages/ui/dist/copy/i3-window-frame/manifest.json +++ b/packages/ui/dist/copy/i3-window-frame/manifest.json @@ -18,7 +18,7 @@ "runtime/components/i3-window-frame.js": "sha256-uqfVHNwkr/11a11fshN7f0r/dXipCi1Vfc0AlLb+i9c=", "runtime/chunks/compositions-d6BkKTYf.js": "sha256-El5csGAVMeeZWmJ1ztdXW3O3t2AQPrf3YrEOMkGX17c=", "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Yk/0tRkcDttUSZKxyg6O6C9kumrEAGehNElFt382jeA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-nNyvwUVLU3Rdy3x0UcZN+IkCA1+Ot5CVwjUB54GDnq8=", diff --git a/packages/ui/dist/copy/i3-window-frame/tokens.css b/packages/ui/dist/copy/i3-window-frame/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/i3-window-frame/tokens.css +++ b/packages/ui/dist/copy/i3-window-frame/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/icon-button/manifest.json b/packages/ui/dist/copy/icon-button/manifest.json index 222e6e228..9fd13d30d 100644 --- a/packages/ui/dist/copy/icon-button/manifest.json +++ b/packages/ui/dist/copy/icon-button/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/icon-button.js": "sha256-GQlt7gcCt926nsvoxCtYRyCMMgdI9IZNyV0+40gv/RQ=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-oGnsvpT9vCQjmmGSRaHOeQIJDUE5f5LrSWgR9jdM6/s=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Zd5z+/mavK2J24Rl+RQLGhMT+nTLwoOf3bAJevwrz7s=", diff --git a/packages/ui/dist/copy/icon-button/tokens.css b/packages/ui/dist/copy/icon-button/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/icon-button/tokens.css +++ b/packages/ui/dist/copy/icon-button/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/kbd/manifest.json b/packages/ui/dist/copy/kbd/manifest.json index 70b29f167..3e1191452 100644 --- a/packages/ui/dist/copy/kbd/manifest.json +++ b/packages/ui/dist/copy/kbd/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/kbd.js": "sha256-xi2+ei38C1TTd2xavWMW/PM7cQTzc0o4g+7LNPNHnUQ=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-sKesLjkvspbpsD6walvgEF0NFv1fsIWXNbBy+hhtAUE=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-tpH9QDJi6WP1xXEjkGhicB0miKDe2fe69wAALVp2X5A=", diff --git a/packages/ui/dist/copy/kbd/tokens.css b/packages/ui/dist/copy/kbd/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/kbd/tokens.css +++ b/packages/ui/dist/copy/kbd/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/link/manifest.json b/packages/ui/dist/copy/link/manifest.json index fcd3173f8..d16d43ea8 100644 --- a/packages/ui/dist/copy/link/manifest.json +++ b/packages/ui/dist/copy/link/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/link.js": "sha256-WC8yN3SdZF28B84F96AQc4WHvgrfmotEdEXUDdPx+gI=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-bMMi6OLOyxVGAoiDlHUR/PYvzH66VbZ4i/UAzrXw4yo=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-I9IW2mf0VnX5LtCoHDI29AJHW7PXUxnRReiAbsbd094=", diff --git a/packages/ui/dist/copy/link/tokens.css b/packages/ui/dist/copy/link/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/link/tokens.css +++ b/packages/ui/dist/copy/link/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/list/manifest.json b/packages/ui/dist/copy/list/manifest.json index 20cb79ecd..f92f65352 100644 --- a/packages/ui/dist/copy/list/manifest.json +++ b/packages/ui/dist/copy/list/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/list.js": "sha256-EfhH50w/Jxw1dj4a/Ul3Xi6WmUlbeRhgpAeATkhO8EU=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-MSEasr2r2kyu8iJSxcX+m4nWTD2FHPKwBU7K8T/9844=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-tiKX+fFUPCsBJEryliaQ7y9RhU4zlh8aEqMJ0aSO8Lk=", diff --git a/packages/ui/dist/copy/list/tokens.css b/packages/ui/dist/copy/list/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/list/tokens.css +++ b/packages/ui/dist/copy/list/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/loading-indicator/manifest.json b/packages/ui/dist/copy/loading-indicator/manifest.json index c14e243d0..6707978d4 100644 --- a/packages/ui/dist/copy/loading-indicator/manifest.json +++ b/packages/ui/dist/copy/loading-indicator/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/loading-indicator.js": "sha256-iTQYSJMXD02jZHXKFvaFfVLsSwVgLrG7ERC0uWAqpvU=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-eNbtRNqnJDdDaKs9tYapfgCNRwMffdQ7e2TqjrYuL6w=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-yiCrGr/OXo7SakIH4qRV3wDHbj09EqyJ2F7eTQHbnbc=", diff --git a/packages/ui/dist/copy/loading-indicator/tokens.css b/packages/ui/dist/copy/loading-indicator/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/loading-indicator/tokens.css +++ b/packages/ui/dist/copy/loading-indicator/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/menu/manifest.json b/packages/ui/dist/copy/menu/manifest.json index c6ebb52e1..967b0a7f5 100644 --- a/packages/ui/dist/copy/menu/manifest.json +++ b/packages/ui/dist/copy/menu/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/menu.js": "sha256-AMtJth+M+4jqb8imqdn9VcM3aKvtgCWkPySfsI7htH8=", "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-SIubQgNKqhuy1abCUQB+rvpnPXZTQ9fiW5Yb6XWT5MQ=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-0SXVO1pxUxzA5mgZzG5YXw21f3G/n81DtP3vy14Nv5M=", diff --git a/packages/ui/dist/copy/menu/tokens.css b/packages/ui/dist/copy/menu/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/menu/tokens.css +++ b/packages/ui/dist/copy/menu/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/multiselect/manifest.json b/packages/ui/dist/copy/multiselect/manifest.json index b0e7a1a23..e5a4033b2 100644 --- a/packages/ui/dist/copy/multiselect/manifest.json +++ b/packages/ui/dist/copy/multiselect/manifest.json @@ -18,7 +18,7 @@ "runtime/components/multiselect.js": "sha256-8L2lHVliSgOdCXDMUzLPyUu9JYyowyYfha4hm57F5/E=", "runtime/chunks/advanced-DCpe8Ndv.js": "sha256-nr1LFdLYsGeTM4vDyldvuJygRm0F04sYonxatySPu1g=", "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-NHeO9yzX+pKu8X05cxcbMC+aba6f5KV7SQL1E+N/kKM=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-1E4hftJizWZX+Gn6uhOJBXC2VAC62t50q2kwRpgS2pQ=", diff --git a/packages/ui/dist/copy/multiselect/tokens.css b/packages/ui/dist/copy/multiselect/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/multiselect/tokens.css +++ b/packages/ui/dist/copy/multiselect/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/number-field/manifest.json b/packages/ui/dist/copy/number-field/manifest.json index 81e54310c..aa318a149 100644 --- a/packages/ui/dist/copy/number-field/manifest.json +++ b/packages/ui/dist/copy/number-field/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/number-field.js": "sha256-27HebtimgA50TSf1kwNGySNCBamP+Cu+9VCSbvOxcDg=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-agyrkFz7FiKZpcU4J9QsaeTNRYBw7yWJQcMOdSd8SPc=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-wabUKPjMJ+zn/+oKJMogtcDlppICQ8zTGXEbhGwm+iQ=", diff --git a/packages/ui/dist/copy/number-field/tokens.css b/packages/ui/dist/copy/number-field/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/number-field/tokens.css +++ b/packages/ui/dist/copy/number-field/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/pagination/manifest.json b/packages/ui/dist/copy/pagination/manifest.json index fcd1065f0..2e0632af6 100644 --- a/packages/ui/dist/copy/pagination/manifest.json +++ b/packages/ui/dist/copy/pagination/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/pagination.js": "sha256-yrEJa21eYjbFYfF3K/IdLp2FXFcKGFkLEVD4bxibWrE=", "runtime/chunks/tables-B25ydUHs.js": "sha256-XqRdyfrSS93rVybWHq6a0WhrmZgaboHi5n8ymgwRbM8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-J6AIVbVHNyS581oA3enNH84ZCf3yRHxSsjlqUa9Z6d0=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-jp4BjPewAxszUnraKXf7iG6Zty7ZB7J8SdFyHQg7hL4=", diff --git a/packages/ui/dist/copy/pagination/tokens.css b/packages/ui/dist/copy/pagination/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/pagination/tokens.css +++ b/packages/ui/dist/copy/pagination/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/popover/manifest.json b/packages/ui/dist/copy/popover/manifest.json index 46b80a225..1c598b30f 100644 --- a/packages/ui/dist/copy/popover/manifest.json +++ b/packages/ui/dist/copy/popover/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/popover.js": "sha256-P63Ou+ew1qtVXdZkxnO6uM5ZG7w9hOBlPK+HNXQbkAU=", "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-53zGKZZyZMB+sdGIbnQk30oFXcLvjoplsW7FfQ9W0u0=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-tBbkSUEedfklBWmTm/lh13o3rlYHe/9AGgvmXp+p/Lo=", diff --git a/packages/ui/dist/copy/popover/tokens.css b/packages/ui/dist/copy/popover/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/popover/tokens.css +++ b/packages/ui/dist/copy/popover/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/progress/manifest.json b/packages/ui/dist/copy/progress/manifest.json index 0d2348a89..43d34b01c 100644 --- a/packages/ui/dist/copy/progress/manifest.json +++ b/packages/ui/dist/copy/progress/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/progress.js": "sha256-SoIKI41QOIzDVzCbEX4RjUwuYIgyVdRipglbNI30PdE=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-qVh6/s9QPg2t6WrczrtP5i8fP1blV8a6S9OZUF5oJdY=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Bm2XYmsDcMrSYl/yKw1emmfA++ea/EjE5wzSjdg0eyw=", diff --git a/packages/ui/dist/copy/progress/tokens.css b/packages/ui/dist/copy/progress/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/progress/tokens.css +++ b/packages/ui/dist/copy/progress/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/radio-group/manifest.json b/packages/ui/dist/copy/radio-group/manifest.json index 3ebb3cfe1..19bc2600c 100644 --- a/packages/ui/dist/copy/radio-group/manifest.json +++ b/packages/ui/dist/copy/radio-group/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/radio-group.js": "sha256-UtfAZUI/Cr3R29YvS/0As27FUks0dSZ5e2Jcx6yDfxk=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Ig6nuF1jMxOL71ppi7cvN8DjEKs9unk/ugZ0b1XTImY=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-6HA7gvr2JUQeKZ5jWPcVyfSw5t4FmaqlAA/+mhuSJjc=", diff --git a/packages/ui/dist/copy/radio-group/tokens.css b/packages/ui/dist/copy/radio-group/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/radio-group/tokens.css +++ b/packages/ui/dist/copy/radio-group/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/range/manifest.json b/packages/ui/dist/copy/range/manifest.json index 056ca641d..13d25c2a9 100644 --- a/packages/ui/dist/copy/range/manifest.json +++ b/packages/ui/dist/copy/range/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/range.js": "sha256-uAqR2sA5IXjunYSDuvl+0MoUbuwonAPLwhQFCExPI/I=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-XwLMipanpFGzjbmGs1VEzJL/+7DPUuYTewuadW6x3zE=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-F3TYZf5Pysp2EfVbSAxBHmgiviXyRS3/dKjUdvZrzF0=", diff --git a/packages/ui/dist/copy/range/tokens.css b/packages/ui/dist/copy/range/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/range/tokens.css +++ b/packages/ui/dist/copy/range/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/repeater/manifest.json b/packages/ui/dist/copy/repeater/manifest.json index 25ce83f73..bad57a698 100644 --- a/packages/ui/dist/copy/repeater/manifest.json +++ b/packages/ui/dist/copy/repeater/manifest.json @@ -18,7 +18,7 @@ "runtime/components/repeater.js": "sha256-pe+MgGoQpseF+J8HpfkS5wU84MsVLuCJl6BAzoyS+lU=", "runtime/chunks/advanced-DCpe8Ndv.js": "sha256-nr1LFdLYsGeTM4vDyldvuJygRm0F04sYonxatySPu1g=", "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-IEhREL5vlXFRdDmE8HHaqwhAbMJ8feOqTJ5MMrQGztk=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-DSCQzrRbDwFOKtw5YmpR+3oYWMIBJFIPnJpes5bSMPY=", diff --git a/packages/ui/dist/copy/repeater/tokens.css b/packages/ui/dist/copy/repeater/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/repeater/tokens.css +++ b/packages/ui/dist/copy/repeater/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/search-field/manifest.json b/packages/ui/dist/copy/search-field/manifest.json index 23f79a60d..9d1ba700a 100644 --- a/packages/ui/dist/copy/search-field/manifest.json +++ b/packages/ui/dist/copy/search-field/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/search-field.js": "sha256-2ODKfrgzC53SjMT+P7oaRa78AgRY37MG12M7HVRwfQU=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-LKiZdfWdQXHUoEdFnG1o5Aka8mOS8NP98IdndPFnsbQ=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-HUFhtyi3m/bOmHYH5vU0uD/8e/TFVZ6EmUZzoucKCCM=", diff --git a/packages/ui/dist/copy/search-field/tokens.css b/packages/ui/dist/copy/search-field/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/search-field/tokens.css +++ b/packages/ui/dist/copy/search-field/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/segmented-control/manifest.json b/packages/ui/dist/copy/segmented-control/manifest.json index 449250032..53fe3d934 100644 --- a/packages/ui/dist/copy/segmented-control/manifest.json +++ b/packages/ui/dist/copy/segmented-control/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/segmented-control.js": "sha256-xN4DQLVyEFJSMDcuTBBrd//fR3iSCEjqnQHkYV4GtbE=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Dq4r47NU2yi+AVRCcT0g+RV5YoPw7Z3JUhDMJqtUoJM=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-/y5XrVYeuiIc2/pZ/wdJWuadUAGF48in7tED7hWQGYI=", diff --git a/packages/ui/dist/copy/segmented-control/tokens.css b/packages/ui/dist/copy/segmented-control/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/segmented-control/tokens.css +++ b/packages/ui/dist/copy/segmented-control/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/select/manifest.json b/packages/ui/dist/copy/select/manifest.json index 454416f74..0adc6d554 100644 --- a/packages/ui/dist/copy/select/manifest.json +++ b/packages/ui/dist/copy/select/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/select.js": "sha256-yyq0jsJOysQGTPpFoA1C1aRWSIukrk+M4Ro2ZwCyWbw=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-F7S6++WxoGrwiPfTq2NRQciL64rhre0zZKEhwee9I1E=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-1rMGJynWvvm/FG3mKaD7Cc+QHA+zhkGFyc7tL4Ul37Q=", diff --git a/packages/ui/dist/copy/select/tokens.css b/packages/ui/dist/copy/select/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/select/tokens.css +++ b/packages/ui/dist/copy/select/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/settings-panel/manifest.json b/packages/ui/dist/copy/settings-panel/manifest.json index 3def1e66b..b0dcd7f9c 100644 --- a/packages/ui/dist/copy/settings-panel/manifest.json +++ b/packages/ui/dist/copy/settings-panel/manifest.json @@ -22,7 +22,7 @@ "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", "runtime/components/settings-panel.js": "sha256-eL+HBTD98ipggaB6cWxKOgb2UXkBgKT50n7xxlWPHn0=", "runtime/chunks/forms-BT3z7lNC.js": "sha256-Txmae07dWLj1H/FL869U0Kv84TQxzpdFeOg0g8zGK6I=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-bKV+vxJoQcQ+/WSkUADY0AkxpU9pAMAviGj+BrOQK1w=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Z1ZqDdIXySN8gWG0bvhT8iMaa+GaOyHy/vumYpCsYt8=", diff --git a/packages/ui/dist/copy/settings-panel/tokens.css b/packages/ui/dist/copy/settings-panel/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/settings-panel/tokens.css +++ b/packages/ui/dist/copy/settings-panel/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/sidebar-nav/manifest.json b/packages/ui/dist/copy/sidebar-nav/manifest.json index a48fa15ec..f93673f85 100644 --- a/packages/ui/dist/copy/sidebar-nav/manifest.json +++ b/packages/ui/dist/copy/sidebar-nav/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/sidebar-nav.js": "sha256-LfEAicAsreVm6Jp/H/ocft61HelJ6RZo1rIPWFWRCCU=", "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-daIsd5K5mOs8Mmspd3m8ktJKgxTzPCRGoQY/6MQCDww=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-LBoiPSLgtVIozM1wEFWbV78DaFWbIW+6OgOjaCSim8g=", diff --git a/packages/ui/dist/copy/sidebar-nav/tokens.css b/packages/ui/dist/copy/sidebar-nav/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/sidebar-nav/tokens.css +++ b/packages/ui/dist/copy/sidebar-nav/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/skeleton/manifest.json b/packages/ui/dist/copy/skeleton/manifest.json index 5a3cbca38..1127c0d44 100644 --- a/packages/ui/dist/copy/skeleton/manifest.json +++ b/packages/ui/dist/copy/skeleton/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/skeleton.js": "sha256-Ou8+/8NCHGRzG6ik6k6762M8G4PMLaBQXj4aPynetXo=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-JI92x7GOktbjpIm0AQnODJ4rVTJnEQA4DLP34bflM4k=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-/g7jxryHfbaG3yxoxK8NfCh2k5U92wPPELD/107+2Ps=", diff --git a/packages/ui/dist/copy/skeleton/tokens.css b/packages/ui/dist/copy/skeleton/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/skeleton/tokens.css +++ b/packages/ui/dist/copy/skeleton/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/skip-link/manifest.json b/packages/ui/dist/copy/skip-link/manifest.json index 77946ee8c..4dca9be87 100644 --- a/packages/ui/dist/copy/skip-link/manifest.json +++ b/packages/ui/dist/copy/skip-link/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/skip-link.js": "sha256-PjQqYJSg0aTsGAbfb9qa+aisYGXDJgGgWN+ZwS/vgFQ=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-KCkIExZyQJQhySZCEQIOrm9lPtDzOq95R9+IED0MI8A=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-TllH5VfEO0Xn2+KsNK2k/W4RJWPv9CVLWE38btvoOpw=", diff --git a/packages/ui/dist/copy/skip-link/tokens.css b/packages/ui/dist/copy/skip-link/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/skip-link/tokens.css +++ b/packages/ui/dist/copy/skip-link/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/switch/manifest.json b/packages/ui/dist/copy/switch/manifest.json index 10ebfb915..aa583d23b 100644 --- a/packages/ui/dist/copy/switch/manifest.json +++ b/packages/ui/dist/copy/switch/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/switch.js": "sha256-Cad08u/MHjqLKKV0MpUQNKaHz1fLJnvy5dfayoqsjvI=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-wQ5f/FFGWolJtnjyPar452XqRgkIhBLJEQbc8ziQvag=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-bja8BqOYebPhAJ/84m7EUQysf7pqQJ3wMJ10wj4YBz4=", diff --git a/packages/ui/dist/copy/switch/tokens.css b/packages/ui/dist/copy/switch/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/switch/tokens.css +++ b/packages/ui/dist/copy/switch/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/table/manifest.json b/packages/ui/dist/copy/table/manifest.json index 159c2eecd..525560668 100644 --- a/packages/ui/dist/copy/table/manifest.json +++ b/packages/ui/dist/copy/table/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/table.js": "sha256-leonu0udFEH8CaIXE0yhLXubdVcLX8V/g+fDayFea7E=", "runtime/chunks/tables-B25ydUHs.js": "sha256-XqRdyfrSS93rVybWHq6a0WhrmZgaboHi5n8ymgwRbM8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-ZLczhksx4+OpxZGChcR6o/jBIHldhOt8XpRDJPyDfeU=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-eTlfzsTldT7TjA25qNYpX+MAAskuYiA9Y+zZW9/B+MU=", diff --git a/packages/ui/dist/copy/table/tokens.css b/packages/ui/dist/copy/table/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/table/tokens.css +++ b/packages/ui/dist/copy/table/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/tabs/manifest.json b/packages/ui/dist/copy/tabs/manifest.json index 8a25bae6e..ae1b96e4b 100644 --- a/packages/ui/dist/copy/tabs/manifest.json +++ b/packages/ui/dist/copy/tabs/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/tabs.js": "sha256-42FcvN/By1ouS+HE0CiZ9FaasHLpN8HY7TiypjcFkdQ=", "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-zVXkxQteKGqZmvOgx444SE+3ubxZ6YdRaGci9hT3GeU=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-xe4UR+a4C9oNodr9UlW5OGE5DR5R9JErwW0UAalo8oE=", diff --git a/packages/ui/dist/copy/tabs/tokens.css b/packages/ui/dist/copy/tabs/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/tabs/tokens.css +++ b/packages/ui/dist/copy/tabs/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/terminal/manifest.json b/packages/ui/dist/copy/terminal/manifest.json index 8a1f625d7..40f88d737 100644 --- a/packages/ui/dist/copy/terminal/manifest.json +++ b/packages/ui/dist/copy/terminal/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/terminal.js": "sha256-nnvO5VIA3kECyTshxbykc7AqrK88ML0IDEe6bYvfsQs=", "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-U9mukzoAnquuoQ1KFzbK6bI+fxJdrdrhSiZgfwulwJM=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-WyXNyoxiAXNq3bLZRmrc1qS2XzgHghN+5tO+9HpocVA=", diff --git a/packages/ui/dist/copy/terminal/tokens.css b/packages/ui/dist/copy/terminal/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/terminal/tokens.css +++ b/packages/ui/dist/copy/terminal/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/text-field/manifest.json b/packages/ui/dist/copy/text-field/manifest.json index 0b09c1b30..71b32a046 100644 --- a/packages/ui/dist/copy/text-field/manifest.json +++ b/packages/ui/dist/copy/text-field/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/text-field.js": "sha256-6f5tLWwF57IFY+uH5zM0afiU3g09PW3M4772zC7zD4Q=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Y3xQDYeeCQmNtobwOfTiTh/OVHOCJt5If76c4411/ns=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-R8UtNVXLOQSMMT+NPAGht8BHx8b1yIjvTii2pQlPs8k=", diff --git a/packages/ui/dist/copy/text-field/tokens.css b/packages/ui/dist/copy/text-field/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/text-field/tokens.css +++ b/packages/ui/dist/copy/text-field/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/textarea/manifest.json b/packages/ui/dist/copy/textarea/manifest.json index 658201928..00bbcb881 100644 --- a/packages/ui/dist/copy/textarea/manifest.json +++ b/packages/ui/dist/copy/textarea/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/textarea.js": "sha256-qJqDEskuaVeBUFjefVF+KSbJV3s6vpaKCtd4aQ4QtoY=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-BbcGdXHTnD7C55UItp05tibzn6AUyioSMT0hgk45J68=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-FrTRU04fY9wZ6rThXepEiAOHAf/WPEcefiPDsYvSLsM=", diff --git a/packages/ui/dist/copy/textarea/tokens.css b/packages/ui/dist/copy/textarea/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/textarea/tokens.css +++ b/packages/ui/dist/copy/textarea/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/time-picker/manifest.json b/packages/ui/dist/copy/time-picker/manifest.json index b055ccf2d..f0235953b 100644 --- a/packages/ui/dist/copy/time-picker/manifest.json +++ b/packages/ui/dist/copy/time-picker/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/time-picker.js": "sha256-K1tUYKUlk8oOLnC7XwOpKWl/CUzqs0NmsRJ38SjjI1U=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-J5VoJUQp+zDREm8yqwh0jq7TRzMH+H8XMK+3CWxjgIU=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-RLfLhDEtkzyeISgOb1Njmp8QsxMKjIUzebwrMAg9GNk=", diff --git a/packages/ui/dist/copy/time-picker/tokens.css b/packages/ui/dist/copy/time-picker/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/time-picker/tokens.css +++ b/packages/ui/dist/copy/time-picker/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/timeline/manifest.json b/packages/ui/dist/copy/timeline/manifest.json index b4e2203bc..257ae2756 100644 --- a/packages/ui/dist/copy/timeline/manifest.json +++ b/packages/ui/dist/copy/timeline/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/timeline.js": "sha256-c1+8tebuE76i5IkY1RRqwNlDkRBrhVwBH4BiCMTSBs4=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-VnvBxMC1c6IWen0gQ3RLi0m3FOelH4E8j4xG+B5Zoas=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-pj/LmsP7e5l3NZI2ZWOLcerU4j0Vn1w2EloUpExz0nw=", diff --git a/packages/ui/dist/copy/timeline/tokens.css b/packages/ui/dist/copy/timeline/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/timeline/tokens.css +++ b/packages/ui/dist/copy/timeline/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/toast/manifest.json b/packages/ui/dist/copy/toast/manifest.json index abfd35dc6..b87a5e7c4 100644 --- a/packages/ui/dist/copy/toast/manifest.json +++ b/packages/ui/dist/copy/toast/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/toast.js": "sha256-v6J5D8moC3m7GxC2mVYytkK8MOkwHSwODcmKmj1Kkgk=", "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-dMp7q8HbznH2LxwbeRaoK7WL/2M2GeVwkitql3aJ3GE=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-2DXrOBOlEPzc9p3N5SEbw98qHHSMYTxlOnR6gT91kkU=", diff --git a/packages/ui/dist/copy/toast/tokens.css b/packages/ui/dist/copy/toast/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/toast/tokens.css +++ b/packages/ui/dist/copy/toast/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/toolbar/manifest.json b/packages/ui/dist/copy/toolbar/manifest.json index b7d91907b..0ad1503f9 100644 --- a/packages/ui/dist/copy/toolbar/manifest.json +++ b/packages/ui/dist/copy/toolbar/manifest.json @@ -20,7 +20,7 @@ "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", "runtime/register/menu.js": "sha256-YX+9ydadaIbkPIBFhLWX4Jv3V9vIl4UY1qolxLGfZUg=", "runtime/components/menu.js": "sha256-AMtJth+M+4jqb8imqdn9VcM3aKvtgCWkPySfsI7htH8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-uTfyFdWFrx91RdklrAzqAHNf5B2q1psaqjlF71eT+Xc=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-MRU95stqvOm7gd3wzi8XadrYOLU9MRKqdwFO/bmSaPY=", diff --git a/packages/ui/dist/copy/toolbar/tokens.css b/packages/ui/dist/copy/toolbar/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/toolbar/tokens.css +++ b/packages/ui/dist/copy/toolbar/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/tooltip/manifest.json b/packages/ui/dist/copy/tooltip/manifest.json index fea800f7e..8c8004da2 100644 --- a/packages/ui/dist/copy/tooltip/manifest.json +++ b/packages/ui/dist/copy/tooltip/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/tooltip.js": "sha256-3/N04wmhF1WPLWW0LBMN2pFnpLGTy7p7toYw2pZpNw0=", "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Skdu3czE82hMaq0VZwtG6ERV4Hud75l3iMhOfMR7K7U=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-+kSohyFbJg7z8/YUnlkzY1UQAu9ZLX7qE1eFLvk/1hI=", diff --git a/packages/ui/dist/copy/tooltip/tokens.css b/packages/ui/dist/copy/tooltip/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/tooltip/tokens.css +++ b/packages/ui/dist/copy/tooltip/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/tree/manifest.json b/packages/ui/dist/copy/tree/manifest.json index 23667f515..16c631511 100644 --- a/packages/ui/dist/copy/tree/manifest.json +++ b/packages/ui/dist/copy/tree/manifest.json @@ -18,7 +18,7 @@ "runtime/components/tree.js": "sha256-1wgpPM9BoC1/T0Or37ZhoekuO2YZ3luXp+DpWKVKBcU=", "runtime/chunks/advanced-DCpe8Ndv.js": "sha256-nr1LFdLYsGeTM4vDyldvuJygRm0F04sYonxatySPu1g=", "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-CMMLz+0autEo86UbTxzkyHVpMoNtyKskesgbIua+YiQ=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-F1zSdM5xw3/jlndjR4iQRRyZ7K9gfkgofh1Oin9xUAo=", diff --git a/packages/ui/dist/copy/tree/tokens.css b/packages/ui/dist/copy/tree/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/tree/tokens.css +++ b/packages/ui/dist/copy/tree/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/copy/wizard/manifest.json b/packages/ui/dist/copy/wizard/manifest.json index 955453147..eff65cd79 100644 --- a/packages/ui/dist/copy/wizard/manifest.json +++ b/packages/ui/dist/copy/wizard/manifest.json @@ -16,7 +16,7 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/wizard.js": "sha256-WMaA9QqPtqe0dUBowMDw++tHyL+HZFO8+VoCJpn+HXM=", "runtime/chunks/forms-BT3z7lNC.js": "sha256-Txmae07dWLj1H/FL869U0Kv84TQxzpdFeOg0g8zGK6I=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-TIsUn3die+vDqK/B4+HqIiSctLsbfAW5EflsX5y1oJA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-T5EJ8DcqnD1rFEoCwvdUpmBCh0hH9dJSmq5oOkC+mi4=", diff --git a/packages/ui/dist/copy/wizard/tokens.css b/packages/ui/dist/copy/wizard/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/copy/wizard/tokens.css +++ b/packages/ui/dist/copy/wizard/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/packages/ui/dist/enhance/form-builder.js b/packages/ui/dist/enhance/form-builder.js index 67def171f..b83cdfef9 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-EQnl1AaR.js"; +export { t as mountBuilder } from "../chunks/form-builder-C5Kx5G9b.js"; diff --git a/packages/ui/dist/index.js b/packages/ui/dist/index.js index eb9a41fd4..e2a7d53b9 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-Dkweb1xD.js"; +import { t as J3w1FormBuilder } from "./chunks/form-builder-C6Rhfsz6.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 307a78af9..ac123b6ea 100644 --- a/packages/ui/dist/manifest.json +++ b/packages/ui/dist/manifest.json @@ -521,13 +521,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/button.js": "sha256-uMPPvidQWPs9e0OGW6Q+cI2izylinOUSgrBAM94vxAA=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-79ycU5ojNv1Z2yHzJ6KXDmshFL1we3mQNOoIwfMXnyg=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-kLEcMMhF4Tv+byKkImEgGIqqR+QYh6uOOCz/mg5hkPs=", "index.html": "sha256-uj00vnflsiaqN+2apiLHqJpCJQQxYasFb7KAWllw5dM=", "README.md": "sha256-q0HhyjwcljqPHR5pUVYK1uw9OCz+qKStetrXmYwvBR0=", - "manifest.json": "sha256-Bat7CbXli1BVcEmYLAyJ42OAFKhWDW0Y3N9ebMbsR+k=" + "manifest.json": "sha256-c6TgjUcOcYCt67r5dMnrTmZpgv9LuAg3v1JdKvlJv+I=" } } }, @@ -903,13 +903,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/icon-button.js": "sha256-GQlt7gcCt926nsvoxCtYRyCMMgdI9IZNyV0+40gv/RQ=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-oGnsvpT9vCQjmmGSRaHOeQIJDUE5f5LrSWgR9jdM6/s=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Zd5z+/mavK2J24Rl+RQLGhMT+nTLwoOf3bAJevwrz7s=", "index.html": "sha256-1y5bo9Aq1K+z6CIM0Ef/YeTqqv1dTsU0UQCeeo8cxrs=", "README.md": "sha256-kfL9rqvRiTy+cXrhgmDnHSmrAvPR1uA5rKGMQPP1UIM=", - "manifest.json": "sha256-Yq0utAFthUSAFiDa7lcg55cQhUdK+H2LnBgt5a/6/C0=" + "manifest.json": "sha256-ySWwdGJTFvqUPfIPiE//EF2SBXqYn8iDa05Ljnz5WmE=" } } }, @@ -1242,13 +1242,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/link.js": "sha256-WC8yN3SdZF28B84F96AQc4WHvgrfmotEdEXUDdPx+gI=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-bMMi6OLOyxVGAoiDlHUR/PYvzH66VbZ4i/UAzrXw4yo=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-I9IW2mf0VnX5LtCoHDI29AJHW7PXUxnRReiAbsbd094=", "index.html": "sha256-kh0VS0IbzhJnHVnQwZQ2ZRbX2qADJqm2SjicvR49IB0=", "README.md": "sha256-x8NFY5DSM/rYjOcAeTMFjFuNeI2xoG8yxyGfTnk8/wk=", - "manifest.json": "sha256-VtFCGcmp+kAitC5o4ewjNT824WaoxY3/igfHlJhH0uA=" + "manifest.json": "sha256-9RCBHV2eK/OPYH+iLaWZUBLLRL/3/Db67A/AA/gLtVA=" } } }, @@ -1582,13 +1582,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/button-group.js": "sha256-9kyXdp1HjHBA1/8MAvS/4B8TzQnyUUIVFbxkMteeCH4=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-f5VJ2bwUNXUnsb5AcdxUYbcOC7PeghM/cnXvDSuGuMs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-4NLobHuAfZnWUQDNQ3ENH9ucyjTTUTD6gk0XV7SHGng=", "index.html": "sha256-jp7d1/nw1z4Jpji1Vc8gp8BdBvkGTLC7tdVzkGSKG28=", "README.md": "sha256-lxk9uEo0CDVb02dn3zqLATkEEbC7gk0mkkX9yRpWCC8=", - "manifest.json": "sha256-YKE2o9BZmy5u6eQtlL6F7qjaDs3StPobS7MNVotT0KI=" + "manifest.json": "sha256-vwsYAxmno4/3Uq0+30v3izOHgMpzwUEntDgsiFb/uAE=" } } }, @@ -2050,13 +2050,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/segmented-control.js": "sha256-xN4DQLVyEFJSMDcuTBBrd//fR3iSCEjqnQHkYV4GtbE=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Dq4r47NU2yi+AVRCcT0g+RV5YoPw7Z3JUhDMJqtUoJM=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-/y5XrVYeuiIc2/pZ/wdJWuadUAGF48in7tED7hWQGYI=", "index.html": "sha256-zUD5N3s3EYsmNmV+t33T6lt+kNsDMoRbcdyTYDikNPI=", "README.md": "sha256-lEaJfO3PJMUKPPqSK45yRRL6euErAHItarIyeoshEI4=", - "manifest.json": "sha256-gpupFMlyzlByXEuOUk8kQDsQs4jv/kIEQOZAiz6zMgQ=" + "manifest.json": "sha256-H33N4ElTkCkBMh2MbBR3SPIPib1+HsrpF2WqEwYwOow=" } } }, @@ -2441,13 +2441,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/field.js": "sha256-pEHbl120kbYNPym5N03ZxIzOQFPHyq+rELTr9RnR2tg=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Rd3CCjOeRNdq9v3ql8A+P+nyw3MOp7Fa0LUD8UqBzFA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-M+Faw3Q4PMYCRgzzkpyGYO6m3Sefbyj3JZ3/wdlvGPU=", "index.html": "sha256-60Xj3vT6YA5V4cnFFqd+JceMzjQ4nZCBnBjOt3OId+A=", "README.md": "sha256-AzjdGpWnzYlGi9+vtMZD2GQ180dH8au7cLFaahlKJZw=", - "manifest.json": "sha256-GQ3tkXxmRfI41HNyehqJhHunv4ftTZccXD8irv00Nxo=" + "manifest.json": "sha256-w3/ZZLfNarfyG9UY8KNfqo/QA/4ufORLVSWeIwS/iYY=" } } }, @@ -2994,13 +2994,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/text-field.js": "sha256-6f5tLWwF57IFY+uH5zM0afiU3g09PW3M4772zC7zD4Q=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Y3xQDYeeCQmNtobwOfTiTh/OVHOCJt5If76c4411/ns=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-R8UtNVXLOQSMMT+NPAGht8BHx8b1yIjvTii2pQlPs8k=", "index.html": "sha256-J9hbLzXuEnbSdeQVzpl5q51KXvGGqGz+Y21d3vAb3a4=", "README.md": "sha256-U5UskFkuRc314VHTU09nhnEvLqV//5UXlnD2tS0RftI=", - "manifest.json": "sha256-NnrVBWko4HWPhGkBoIYnMm5jYnXwd76OdbC8XdlUoFc=" + "manifest.json": "sha256-T+FFVaCn+rM3sQkUSAo7Rt0qWttJ1BhryEiHTCNVafE=" } } }, @@ -3504,13 +3504,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/textarea.js": "sha256-qJqDEskuaVeBUFjefVF+KSbJV3s6vpaKCtd4aQ4QtoY=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-BbcGdXHTnD7C55UItp05tibzn6AUyioSMT0hgk45J68=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-FrTRU04fY9wZ6rThXepEiAOHAf/WPEcefiPDsYvSLsM=", "index.html": "sha256-xM2w2jkYyi5BE0Nc6YGqICrh5wAW+DKYGmHHjEB1tOM=", "README.md": "sha256-F6nGVVbKhFVOmZH/GiI2JV5yeoVGMJCFzjcytVdyGrs=", - "manifest.json": "sha256-VeZRrTxwhFU2bJcDBQUPI68/dFzyc1GVu0w9WcbtTXU=" + "manifest.json": "sha256-TWjfrH63Bc/kflpuBQDJbS27RePsfSb9IsUWdkGRiwA=" } } }, @@ -4128,13 +4128,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/select.js": "sha256-yyq0jsJOysQGTPpFoA1C1aRWSIukrk+M4Ro2ZwCyWbw=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-F7S6++WxoGrwiPfTq2NRQciL64rhre0zZKEhwee9I1E=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-1rMGJynWvvm/FG3mKaD7Cc+QHA+zhkGFyc7tL4Ul37Q=", "index.html": "sha256-f4rQyCq7pkNwF1oV2xWbeCAut4dwtAt0CPyZLBiz+1Y=", "README.md": "sha256-MrNAdB126mt16m2mdh0VynM3ujESd5+tjBkbyYHVpQw=", - "manifest.json": "sha256-Y1NfQmSIof6fmELT3rkfGZDSCBfjNPDEpyzctLVkgHI=" + "manifest.json": "sha256-Auv8G7CtLAflBo0zzaMsITFuEZmyeNhvlcRInd1XK04=" } } }, @@ -4636,13 +4636,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/checkbox.js": "sha256-dKDUoVoQi9btazDX3FlRb0fnVzLkYEN+W08CewNGTnI=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-PpwiBtqgcGIHn1KgKDXvrsX0DeTZ4PfyQsMnUpwCUrI=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-D5pZAWuWF8+C90nVIZnSREv1i0fk6q9L+6SEdvU1Okk=", "index.html": "sha256-zm4zdpqK+QV2pfYf2WrPK1bYk0S65vU+AWWPEq60/mE=", "README.md": "sha256-WEnN989sIQKKMpAjmYvjRbS2hGIBqYi+IEj9c/xhVFs=", - "manifest.json": "sha256-hJd553Ef33h7Ny4ruLLSL8+BmSTVMIt41aCWwR9Kavc=" + "manifest.json": "sha256-kFFpTffP1dDIr9wzNmLVN7foHnf/nRwRbekip3C4oYY=" } } }, @@ -5049,13 +5049,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/radio-group.js": "sha256-UtfAZUI/Cr3R29YvS/0As27FUks0dSZ5e2Jcx6yDfxk=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Ig6nuF1jMxOL71ppi7cvN8DjEKs9unk/ugZ0b1XTImY=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-6HA7gvr2JUQeKZ5jWPcVyfSw5t4FmaqlAA/+mhuSJjc=", "index.html": "sha256-4ptm1dy28zuJlLU04Zd8QtEveiw6njq8DNNQd89W/1w=", "README.md": "sha256-L+Z3W5VfP83lnvB20pwCI2E1gQ/vKF4Yvd/mDw4diyE=", - "manifest.json": "sha256-PRTi1+IXRrKIG+iq5rBiBKtFzpsGeQG5/f/16lYpmCw=" + "manifest.json": "sha256-UpYcgVSqDnhnjaAHOl5w3cY9WJP0x1sLlAONVAGlg78=" } } }, @@ -5461,13 +5461,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/switch.js": "sha256-Cad08u/MHjqLKKV0MpUQNKaHz1fLJnvy5dfayoqsjvI=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-wQ5f/FFGWolJtnjyPar452XqRgkIhBLJEQbc8ziQvag=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-bja8BqOYebPhAJ/84m7EUQysf7pqQJ3wMJ10wj4YBz4=", "index.html": "sha256-UZvqjISxPBGEl7MJkilEMem3b7sjRYRpBJpzJneqq/Q=", "README.md": "sha256-9Yw9PXXsjkMqCnWGR6UbhauQtlI0q6dR39YdGBbG71A=", - "manifest.json": "sha256-ro51Jzhx8KR2dDJCRqTKB5jNf8Mnc8kBcTaICxcws1A=" + "manifest.json": "sha256-YSfVQXXYORkF8TYDuvw8UDQFQ0C2BvhbCcgmyhHx5aE=" } } }, @@ -6034,13 +6034,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/range.js": "sha256-uAqR2sA5IXjunYSDuvl+0MoUbuwonAPLwhQFCExPI/I=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-XwLMipanpFGzjbmGs1VEzJL/+7DPUuYTewuadW6x3zE=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-F3TYZf5Pysp2EfVbSAxBHmgiviXyRS3/dKjUdvZrzF0=", "index.html": "sha256-xuKPgkTCOPNTZ8muQffKPJpVLWZpA03yfkf+90bVZmw=", "README.md": "sha256-lW1eqkbbrr3cTilmwEqgWHViJTPEMEDqDOHhsAizE1I=", - "manifest.json": "sha256-83FLaBofKJVFXrLxvl++gdymve8PpMF4DiKOiX0/ZNA=" + "manifest.json": "sha256-9Fj1tjDQyex5Ybg8lOvcWuVuHic/EnjnNXfR/YPoO7c=" } } }, @@ -6417,13 +6417,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/fieldset.js": "sha256-pAzVFWN+M793N7lFAZ2zTybWJLdSOqZl3AmOTomqmTk=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-TPi15SfEwAaSl4PqQvGAd3bFbbB4BJ2trfD5k2+8yrc=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Z916I2upHIzzffRAz/6w6FSTBwegAd+L49E9Juck2fo=", "index.html": "sha256-/G/GqORWDhO+K+ngVGX8Mrb/mp0XHqSZ3PP1WwffRXQ=", "README.md": "sha256-dNh39iesY0kLTE75KP+a0WhhHDQpT+j04MoZgMmV4F8=", - "manifest.json": "sha256-2Z7hETSoJn6L/hHgchT0vJnPEZyrqjO6/vefg/ENXPk=" + "manifest.json": "sha256-uljFodRq8xH/+kpic5mcTdwYRi6D8uRATY8/65tRHSA=" } } }, @@ -7042,13 +7042,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/number-field.js": "sha256-27HebtimgA50TSf1kwNGySNCBamP+Cu+9VCSbvOxcDg=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-agyrkFz7FiKZpcU4J9QsaeTNRYBw7yWJQcMOdSd8SPc=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-wabUKPjMJ+zn/+oKJMogtcDlppICQ8zTGXEbhGwm+iQ=", "index.html": "sha256-yH23EzsY61NhYO5ZTaRXcpIb2OUYezkZl+VlqSSVS/M=", "README.md": "sha256-ZNn4SinUkL66soe9hksIPf65yrk5SCJshryFP1N2GnI=", - "manifest.json": "sha256-hegLu++sUwG/DMW8Hg7cZrcebrq4rTNvBxMl75+x2dQ=" + "manifest.json": "sha256-p6h3APhk2/kyaXbWKAEHdHQKn9zMYnarGK9hRLu/MKg=" } } }, @@ -7543,13 +7543,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/search-field.js": "sha256-2ODKfrgzC53SjMT+P7oaRa78AgRY37MG12M7HVRwfQU=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-LKiZdfWdQXHUoEdFnG1o5Aka8mOS8NP98IdndPFnsbQ=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-HUFhtyi3m/bOmHYH5vU0uD/8e/TFVZ6EmUZzoucKCCM=", "index.html": "sha256-pNWMnOcTZTr/TNcGVa53Ac8S3/6iWYnBj5B5CjnTcVI=", "README.md": "sha256-aDgof37yYQAYKjMAPaaPxNDPtVVxOfCjHh2aT60B4xo=", - "manifest.json": "sha256-yt6YbOXtYkZ8+8jd4AuPMSJrWIkpD5DYzBPylnpK5v4=" + "manifest.json": "sha256-pnh7Ao4SBHM7H6SMJlWsYLXgxVp7AdEhbo+/35vi72k=" } } }, @@ -8108,13 +8108,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/combobox.js": "sha256-5b1Sa2zwhRyysK9sVyLiBCGsYfJyYnfGDsb6r3sA9MA=", "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-f4pI9RLIKYsRggzuVcLA2zYdXHZXY3+DbGFjvBCtbSg=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-/SDEtn3D/9kfnULtpHPFEgK1FAkmwe+77gdxlWNewhY=", "index.html": "sha256-TgE5FDYDcg51ETqt8UekGbIULwjwCa+CjxGdU63wd/k=", "README.md": "sha256-d6hom7buY1pZpNug4Bx9SqSXvSLDY+cq2xwlZ2Fei/U=", - "manifest.json": "sha256-Z6FLAAQ/vWunhYlUN5k67m7KZO/GNkn0b+T8HAGYFis=" + "manifest.json": "sha256-rdA+FV9dwxEdykFLa7tzZnjl+60iBGTXLBwm5cfXOnE=" } } }, @@ -8616,13 +8616,13 @@ "runtime/components/multiselect.js": "sha256-8L2lHVliSgOdCXDMUzLPyUu9JYyowyYfha4hm57F5/E=", "runtime/chunks/advanced-DCpe8Ndv.js": "sha256-nr1LFdLYsGeTM4vDyldvuJygRm0F04sYonxatySPu1g=", "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-NHeO9yzX+pKu8X05cxcbMC+aba6f5KV7SQL1E+N/kKM=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-1E4hftJizWZX+Gn6uhOJBXC2VAC62t50q2kwRpgS2pQ=", "index.html": "sha256-/iSVBFFALSTS0ebIls1qu3/g280a8lbMULm2Al9zFMM=", "README.md": "sha256-754Tt+bveWNGF8niAMoHQEB7D8SGYGEJhu6GpbhKpiU=", - "manifest.json": "sha256-O1IjRfwEZvhLWVLk3LK9TIML1tL3gVj3my8BX/zwegw=" + "manifest.json": "sha256-vXlR0srvz+KDPAaPbWuMQCTQmQGqocNNjF2ccKGVUeA=" } } }, @@ -9216,13 +9216,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/date-picker.js": "sha256-rglCYTqoXYDZ63YUb01UqeMk0HRjOeYkVcqadAX0qmM=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-InOm4+AU0uQu6XZs3K+f13FA89Jf7iQO1GuL/2+s9YA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Nho5WRdNWOIx9zrVkZR8s5NrC95hgRBVnvDTdnZ7qoo=", "index.html": "sha256-eGq952lAjjjM/6cG7o5Rv4hcM4Tuc6zA38HiAPrEevM=", "README.md": "sha256-7Nf1YMBxm1cGzO+rzOKvfqWgRfugAjR+6/WjnVo2qpc=", - "manifest.json": "sha256-7BRpb4bMBn6h5aixxc8Fb+OE71//nfE+Rlqox36UEek=" + "manifest.json": "sha256-48K6bsVp7ch78EFmIyDgXpAaLzUWaLgA1nfjOo2NwZo=" } } }, @@ -9800,13 +9800,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/time-picker.js": "sha256-K1tUYKUlk8oOLnC7XwOpKWl/CUzqs0NmsRJ38SjjI1U=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-J5VoJUQp+zDREm8yqwh0jq7TRzMH+H8XMK+3CWxjgIU=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-RLfLhDEtkzyeISgOb1Njmp8QsxMKjIUzebwrMAg9GNk=", "index.html": "sha256-0uRkUg8W3uzjOeM45/CL0JXuey7R36hf4eL2pcTXKZY=", "README.md": "sha256-bK7PieiUKZ/3zwSldV/HlWMak7kwtWyvgpYy1YfAmbM=", - "manifest.json": "sha256-wxpcgxJ9Gi6UvCUrDp9dioJK7/5dGvvJ8K3LZNbXyqM=" + "manifest.json": "sha256-6dQepccMEMurDmXDGAXKgSfV2lWmb9ekpIZ/3hodceI=" } } }, @@ -10339,13 +10339,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/file-input.js": "sha256-b5A8PD7vS8/xWNzSdVbtt2pV33CllxtkKwdSPtC1CSI=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-ezg9wydBGR6KpQziZgvoKiTXURNTPkh+aD9h3vFuuW4=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-3MysNuXXyX6HzlWv0wFhnto4CU9Q/n0JHK2wx1ufwbE=", "index.html": "sha256-fBkoQQjmYl2pS2ZhIJZ6zX3QXl6l6HTDfKsrsy4jmb8=", "README.md": "sha256-fT5UasqXVH/Um8vNgVGEXNG0Pk7WZ4Aq+K44FBlAdpk=", - "manifest.json": "sha256-TKiC1mhiYH8D1y50C5ACpP4Lz10Z3xCa4GxvUdkDEnw=" + "manifest.json": "sha256-PCFjtc+DwT+gaXF4ED4ra/J3ypLKXVDF9kT/4IXn4No=" } } }, @@ -10718,13 +10718,13 @@ "runtime/components/repeater.js": "sha256-pe+MgGoQpseF+J8HpfkS5wU84MsVLuCJl6BAzoyS+lU=", "runtime/chunks/advanced-DCpe8Ndv.js": "sha256-nr1LFdLYsGeTM4vDyldvuJygRm0F04sYonxatySPu1g=", "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-IEhREL5vlXFRdDmE8HHaqwhAbMJ8feOqTJ5MMrQGztk=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-DSCQzrRbDwFOKtw5YmpR+3oYWMIBJFIPnJpes5bSMPY=", "index.html": "sha256-c0jxp+wZ+Fh6pdflIdXG673av6oOTGx7HobpD63O2Sk=", "README.md": "sha256-iFFjPHWI+gh/aJ7+flDL4I/Qaclwv1yCfGRuJ06o6tE=", - "manifest.json": "sha256-iMtAouXvHNiZEeyxqGOPIX4ptGvUNPZrhPw3akRSvYE=" + "manifest.json": "sha256-Ek/0mqQpQIztzCidbtl1wboLnvHJjvWQ7BM/s4lZ5FM=" } } }, @@ -11366,13 +11366,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/wizard.js": "sha256-WMaA9QqPtqe0dUBowMDw++tHyL+HZFO8+VoCJpn+HXM=", "runtime/chunks/forms-BT3z7lNC.js": "sha256-Txmae07dWLj1H/FL869U0Kv84TQxzpdFeOg0g8zGK6I=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-TIsUn3die+vDqK/B4+HqIiSctLsbfAW5EflsX5y1oJA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-T5EJ8DcqnD1rFEoCwvdUpmBCh0hH9dJSmq5oOkC+mi4=", "index.html": "sha256-x7w0JHEaRfh3sRM0TmJcKmqI73CDTfRHzbgURIS3m80=", "README.md": "sha256-B9klMh35GlqO5l2mxI77I6x2Gwfl8AMNSH6P+up7GdY=", - "manifest.json": "sha256-iGsA8lMX0V0Ipmib1881C1nGntn+vXPGfd3lDDhhYaM=" + "manifest.json": "sha256-m2daflOEDFk6WotvcUWzd9v4LCJpXkBoOyA2h+etXNI=" } } }, @@ -12256,20 +12256,20 @@ "copy": { "directory": "copy/form-builder/", "files": { - "runtime/register/form-builder.js": "sha256-jo5ONsFuzPH0pmoDpmWyq6QVpkKeKDhZYbwW/vKQ+ic=", + "runtime/register/form-builder.js": "sha256-eM9TDYrxREfT+vaywPQ8TCrx3X7gAB/fXuj8viaqKzM=", "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/chunks/form-builder-Dkweb1xD.js": "sha256-y1g6oI2gMoPy6c5S5Lgoec9Po3ydkEadsbsL5vVWFUI=", - "runtime/chunks/form-builder-EQnl1AaR.js": "sha256-lX4d482lke5Pljjn6rKPas9RRdIWgoifB609las09JY=", + "runtime/chunks/form-builder-C6Rhfsz6.js": "sha256-CnwUvLr0BCPWw5F9dlDy1D8Y73slv5huNge/LK40+x8=", + "runtime/chunks/form-builder-C5Kx5G9b.js": "sha256-H2Zi4dAojDJ5ZF7OQWEPsPaCg3kMBiAVVG1k948Yiuw=", "runtime/chunks/form-workflow-DMGni-Gs.js": "sha256-g3g/Afxx3XsClDK4ZfvWQjZKprT6z7Qp1lULS48F0rY=", "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-dgVsrgYuHrvBt6OjTg069abl7yU4iwgXOXUw3n9cB7g=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-vq61pWv0xeMFu0tTsDtRWWpAr16AFefjpz5JTSyF440=", "index.html": "sha256-v74xLbiCzhGoMsKDM8vIO3nwDmWQJymihSOqXqvPlkk=", "README.md": "sha256-MGlPh4CEW6DLecBSj7Ym9ww3NAGe8r5V9uANRpZLY48=", - "manifest.json": "sha256-aoSpEA6qVQhF0JI5HP7ycm4UbGmG+ya3B7tt1wA5RnE=" + "manifest.json": "sha256-/AJpK7InIcUrx5C6r4HWc3McmNfuSvcN0bFFLRwFx7s=" } } }, @@ -12678,13 +12678,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/tabs.js": "sha256-42FcvN/By1ouS+HE0CiZ9FaasHLpN8HY7TiypjcFkdQ=", "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-zVXkxQteKGqZmvOgx444SE+3ubxZ6YdRaGci9hT3GeU=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-xe4UR+a4C9oNodr9UlW5OGE5DR5R9JErwW0UAalo8oE=", "index.html": "sha256-w1fTqm25U4WCS0w6RvFvuUPfonjfue1T0ZJN83ccPr0=", "README.md": "sha256-uBwdwc6EkHrqha/dCs9PWntoU1l7EAJb7Y6nx+zzrqI=", - "manifest.json": "sha256-aW2OMAJ7OKTFBe9zF9B4eVsJyynDgRIDkBVaDylHtNo=" + "manifest.json": "sha256-PM9hfuUIQtvrIekuc8ckBWWQXjPFXTSvcBTd9ovfoQY=" } } }, @@ -13035,13 +13035,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/breadcrumbs.js": "sha256-GtJDiM9iN77t0CIkD7Feiu8A1MQ5DeirIUfSVxO6o7Q=", "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-pJjvksTD6NTZ2QRx/SBxS4j7xy1rVLprovo5OnTOafs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-W9qk0XtcetNK1me7748lByEMSMUZyP6NT//vet/Kt0I=", "index.html": "sha256-OWJN8qhGZ4YIN1OKUp03drZk8CY4D66GaO0t6LtKvJs=", "README.md": "sha256-KtiYxcVwfGDIDiTnYI/c2MhmVKez7eLztyU55QJQXgs=", - "manifest.json": "sha256-/aBGJEdE5pG/blq4jU0tuQHrHU7s37pK/hbNdI+bRL8=" + "manifest.json": "sha256-EalDQFcoOagLdF+WFVS1L0RqDU9zG7P6zi6BdvHcFFM=" } } }, @@ -13430,13 +13430,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/pagination.js": "sha256-yrEJa21eYjbFYfF3K/IdLp2FXFcKGFkLEVD4bxibWrE=", "runtime/chunks/tables-B25ydUHs.js": "sha256-XqRdyfrSS93rVybWHq6a0WhrmZgaboHi5n8ymgwRbM8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-J6AIVbVHNyS581oA3enNH84ZCf3yRHxSsjlqUa9Z6d0=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-jp4BjPewAxszUnraKXf7iG6Zty7ZB7J8SdFyHQg7hL4=", "index.html": "sha256-/fV58cVZi1JLHRPrv8jsrMD51D/264mvCsNHTj4WEYM=", "README.md": "sha256-CkmYa5gHgFCQLGpkV2WpwdaxjhezkCTRRw8d9KDRUqg=", - "manifest.json": "sha256-60r+aCzqs2VJdTf9woMF9hv5KthQuTRbZ7iM38aKMBI=" + "manifest.json": "sha256-VnFhaAlOvHjn6UY3qGk2yBXuPfa3PI1CYjoFCi9AAJo=" } } }, @@ -13873,13 +13873,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/sidebar-nav.js": "sha256-LfEAicAsreVm6Jp/H/ocft61HelJ6RZo1rIPWFWRCCU=", "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-daIsd5K5mOs8Mmspd3m8ktJKgxTzPCRGoQY/6MQCDww=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-LBoiPSLgtVIozM1wEFWbV78DaFWbIW+6OgOjaCSim8g=", "index.html": "sha256-iigY56T4Y5udSqoBZloU6658GNUHY+ynrBQSOg/+UIc=", "README.md": "sha256-QjtvSq2sHwF8bsMsDu3BpvOyATxZ0oanPWICItjaETU=", - "manifest.json": "sha256-Rl7kfHhDzahs2E5iAw6o2u7UNqJAiayqCZn3A2ag9D4=" + "manifest.json": "sha256-vJwnwnVoCLZuwhSZpsPKP7dmOI/CkQQTmVryV7sm25s=" } } }, @@ -14425,13 +14425,13 @@ "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", "runtime/register/menu.js": "sha256-YX+9ydadaIbkPIBFhLWX4Jv3V9vIl4UY1qolxLGfZUg=", "runtime/components/menu.js": "sha256-AMtJth+M+4jqb8imqdn9VcM3aKvtgCWkPySfsI7htH8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-uTfyFdWFrx91RdklrAzqAHNf5B2q1psaqjlF71eT+Xc=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-MRU95stqvOm7gd3wzi8XadrYOLU9MRKqdwFO/bmSaPY=", "index.html": "sha256-qzep40OKd67lZTxeQflCRA+sfx2A6/zxVgtV4re8LgY=", "README.md": "sha256-jPzt7MdgG4yEEJJ6qWZk3Cgw9KNNNHEKkwz/nnKK3co=", - "manifest.json": "sha256-Nqfa3AzsL73Ep9jP3gvG3YBOW8qyTGnIZrjSd6zpcWY=" + "manifest.json": "sha256-8hlyqGGelr15H1t7evcG0FBb95rGUZnTNnn/7YboC68=" } } }, @@ -14976,13 +14976,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/menu.js": "sha256-AMtJth+M+4jqb8imqdn9VcM3aKvtgCWkPySfsI7htH8=", "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-SIubQgNKqhuy1abCUQB+rvpnPXZTQ9fiW5Yb6XWT5MQ=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-0SXVO1pxUxzA5mgZzG5YXw21f3G/n81DtP3vy14Nv5M=", "index.html": "sha256-nwGZ4fZm7plv8ayxNa3zbvZ6jTO5Efxv0EvQBeohNN8=", "README.md": "sha256-ICc5PzI3f6/Kpyf9KXWame8aNgGPR8JKtgBhHc9HrsE=", - "manifest.json": "sha256-YWF7LtF4Y/ZgN5otpkiIBHeQDPn8kKw129WvyZSELhs=" + "manifest.json": "sha256-Ud+V3UiG+NGVSscSNIvn3E4AuJOFFvDO/8r2oe1R9sw=" } } }, @@ -15401,13 +15401,13 @@ "runtime/components/command-palette.js": "sha256-KMSKyY2a0yyVe6zxGdWjBFFsgbL/DjNUvU8lnxB6USQ=", "runtime/chunks/advanced-DCpe8Ndv.js": "sha256-nr1LFdLYsGeTM4vDyldvuJygRm0F04sYonxatySPu1g=", "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-sXrks2txpylBLDX4L9vKPIvAj11p73qrX0apfh7EgTg=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-mNRkLE+yYA4PARM4rv5bXDj90Oq8yxQLPgoUW8bX6ns=", "index.html": "sha256-I5o97Y3ykrn6MCqMmtWvFGTxDBltracgMFnF25iNwZk=", "README.md": "sha256-KLn7bklioLvnV4bRDAgf3A5aqqCSezXa9kKARSYCUcw=", - "manifest.json": "sha256-sjwZw/AW7vcseMQ1l9pbcq/hDRYxIdZs2DOV5595GV4=" + "manifest.json": "sha256-RxOWXeniso+hvwGsCJGdxMEfsQnCjBbPcgMkNi70XEY=" } } }, @@ -15758,13 +15758,13 @@ "runtime/components/tree.js": "sha256-1wgpPM9BoC1/T0Or37ZhoekuO2YZ3luXp+DpWKVKBcU=", "runtime/chunks/advanced-DCpe8Ndv.js": "sha256-nr1LFdLYsGeTM4vDyldvuJygRm0F04sYonxatySPu1g=", "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-CMMLz+0autEo86UbTxzkyHVpMoNtyKskesgbIua+YiQ=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-F1zSdM5xw3/jlndjR4iQRRyZ7K9gfkgofh1Oin9xUAo=", "index.html": "sha256-+NV68HiyyQfXclh/Z5F0O/9UwWGzR6RouwMjxM/4DZI=", "README.md": "sha256-rkAg9VO8TxgNCrXXP8dhUJ24Zori5pT/6k3w7gj4ixA=", - "manifest.json": "sha256-4RUETiVuDpUfhbB64T/WAejSHUEhFEXHJnLzKNXk140=" + "manifest.json": "sha256-b/wUhzdct+NttP79qt24e+b3XsS9ej8bN1kxxKgJ7m8=" } } }, @@ -16110,13 +16110,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/disclosure.js": "sha256-T++duSnTm8ippxMGxtM25ykxUO+HYIt0HK55RkVOrHQ=", "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-vVNjPU0AXLKLnxgRPgOVmN3dS6S3pxA6xLFfJFK8ex4=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-ZbpW/j8ZGKofIgL/uVEO47xXhxXmS2mrK5w32n/BWZA=", "index.html": "sha256-IGRscuNxsfbVQd8cDkiBz1/QAEamMHSToesnIwq38AU=", "README.md": "sha256-eHT7DdGUFZxUFoiTNsB5j6dKCRG6kf9fT0gY1oSBy/8=", - "manifest.json": "sha256-pUsMYVXWCYN1EVfwL18klJsWytxWbWsJ5ZCkon4Ohb4=" + "manifest.json": "sha256-srtw0ECNjqeIbiyT88LWtptOK+3TJpxgjEzBwafyhBE=" } } }, @@ -16416,13 +16416,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/skip-link.js": "sha256-PjQqYJSg0aTsGAbfb9qa+aisYGXDJgGgWN+ZwS/vgFQ=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-KCkIExZyQJQhySZCEQIOrm9lPtDzOq95R9+IED0MI8A=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-TllH5VfEO0Xn2+KsNK2k/W4RJWPv9CVLWE38btvoOpw=", "index.html": "sha256-/HDnZh+ZTER/j0o82CsKR1s11+5KNWqzGpG3Q+RrG1Q=", "README.md": "sha256-YX3Ch7JuUJRqIpsiYPlIc/09irmjC9OLqMTSPNUidYM=", - "manifest.json": "sha256-DLQ8IJEF+7r/cxXoKME+WMqTOVaJevkgDMVRXjTEk0E=" + "manifest.json": "sha256-/jHANaZlfExigzc9YSvrmpKwOgJsNkh3BLB4kOMIj5c=" } } }, @@ -16795,13 +16795,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/card.js": "sha256-REUcny20Az6YiLn0F6l0ZkmNrj18xAqRj9bWUmvkhLo=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-pfXQBPkrp6iF0OlQiLQh9DMUwtsCinOaL1HLAjlChII=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Rc0IwITP8X0cKscYMBt4LgzFbntPHkCAdDQ4xLh2LXs=", "index.html": "sha256-IvoBispcGfdc1cclMkSpIk4mImhXxUS8/bDAr0dLmcU=", "README.md": "sha256-7NvZudM1FuKwW/ZySKs98FmFwxwir6nLM/lGAvvcI+4=", - "manifest.json": "sha256-uCrS1zqZdZJERPpycHAm2jRonQ5KvUciSZZ0GDG/r2c=" + "manifest.json": "sha256-i+pJofI3U2yKMpy/iUtg9GQYpMJuhdXqk8eQsj/fFsk=" } } }, @@ -17219,13 +17219,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/list.js": "sha256-EfhH50w/Jxw1dj4a/Ul3Xi6WmUlbeRhgpAeATkhO8EU=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-MSEasr2r2kyu8iJSxcX+m4nWTD2FHPKwBU7K8T/9844=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-tiKX+fFUPCsBJEryliaQ7y9RhU4zlh8aEqMJ0aSO8Lk=", "index.html": "sha256-sY1ilmVvk6pArKOSGuz/1p4PN883f3mu5PXF1sOLwX4=", "README.md": "sha256-lw1NGV62/UGys6imJuVkK5qPyHaJqiOgSEuHCgehwNc=", - "manifest.json": "sha256-QvzckZWIiDE/ImHAN4r4S19GgKtTUSk1eHxUqy+pyXQ=" + "manifest.json": "sha256-SbBbbXQ5+Bc1H2Pt8GwTLH1s6pniel+amh1L4cKgwss=" } } }, @@ -17517,13 +17517,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/description-list.js": "sha256-qKd9CujEm+EgRSZfWHW9YXH9JY/d5wMBkkfqqP3z5so=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-MvWyrX2+45DLgWL1ZxTdk0IFVjl5WyfGYZdOYpIeoak=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-h2HPGz9Kz0LvMiuTC767wAQvYHOVVmffDECwh46tG0c=", "index.html": "sha256-mGxvifjxa5eFOtCBUQR3P/9IKtYsKd4nsTfWb9+u9w0=", "README.md": "sha256-RrAu5lsq7QsSDTX+KygEzIsHJphBaeLyKmqBc+xa5G0=", - "manifest.json": "sha256-HW+ZJFxBuqoK3d8KJlYivtpz6Ql2Fa89enziCfIyg1Y=" + "manifest.json": "sha256-X4Ucl253TcuE6dHaVe7snooGjXH6qNADSDI8KIVB11A=" } } }, @@ -17986,13 +17986,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/badge.js": "sha256-l72iC8CAJp/xCXpSX/oJ3xsz8VT4N6UAcVhVSKeC/zs=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-K2TPkFZfKUt35HniL/ub9icdMukZ7wCx0S5+D1FOv8Y=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-rXaOLdDbEK5SMtYsw5TegOMtcnLijmgtU07RVrvJx8o=", "index.html": "sha256-adxgp7aQqS8TWwQ8h7ZunxvDdJpxjaS8oGagTh0d+s0=", "README.md": "sha256-5TsNDY9d5k6gLYa4KQycTh+1uwvXsoF0XilR9xhKVVw=", - "manifest.json": "sha256-raQq7vv7/AES3cx9gip/td/yODbpi3TvQ6minqOTVqg=" + "manifest.json": "sha256-dYqinOxtXZZbvC2MgSv3k1KR+2WgDw7MIWYvM1syecw=" } } }, @@ -18389,13 +18389,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/chip.js": "sha256-u34FDCir8vK2ro61A5etBvzomb22WIhnIx7vL6Xcf3k=", "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-nKS3XC8eLjQCMMZHRRKSiHiaNGZgYD6CXzVULJoDU3g=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-yjXdYrZ4DqpcZ/ZDGxD0cgfYY/xqj0qeSkX1dJmVhfY=", "index.html": "sha256-w6jTubEaofdbvKO8llTmtTpw3a/ixglUtu1tDybz2iY=", "README.md": "sha256-Ay+51qOAHcbN22QHsMfcbrA/66D52crp5OlQCHyMYmg=", - "manifest.json": "sha256-CDpgsi4gq8pm3VmaExEHAIHIro+79mdFp7dhVprq6XE=" + "manifest.json": "sha256-yT0JmPG1bG7dWQAeyCEaG9vmhKJg43cR+dngTQc3ToY=" } } }, @@ -18680,13 +18680,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/avatar.js": "sha256-ewC6RhKRQwH+7jEF62lU5q8KPwKXfyEg/JWISD2N/FE=", "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-XYCR7yVoWMnpJrQG4A+pL3xESyHR6OKMuwJfZGgDpKA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-R1Q+6UFu76jOlVP9cadBrMxVS3+Yb2JgIDkcnKxWvtk=", "index.html": "sha256-6wIoUvdBP1c8DCQbO8yN3AbgSvI4jPyNvKs6IYYA/7o=", "README.md": "sha256-u+Rv0zskk5yOTH1pAzZ2eB3pId21guCqbzSFwIC5pcw=", - "manifest.json": "sha256-RRx0kD6cBwLeZFpZWYUl397tEaCFc8+hAq4Iul/dLR4=" + "manifest.json": "sha256-c6GiHt1iB6I4HICzh/PnoN9D4wm4omp6h7bp2vBfftg=" } } }, @@ -19126,13 +19126,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/table.js": "sha256-leonu0udFEH8CaIXE0yhLXubdVcLX8V/g+fDayFea7E=", "runtime/chunks/tables-B25ydUHs.js": "sha256-XqRdyfrSS93rVybWHq6a0WhrmZgaboHi5n8ymgwRbM8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-ZLczhksx4+OpxZGChcR6o/jBIHldhOt8XpRDJPyDfeU=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-eTlfzsTldT7TjA25qNYpX+MAAskuYiA9Y+zZW9/B+MU=", "index.html": "sha256-wHPL38nEdZyiESe+MlLb9ZgRLg+MfbRXMzN538tD0pE=", "README.md": "sha256-hZvyqPLVQoQuOKc7t2j0cESQRW84E8XfCL/ad6sXIdw=", - "manifest.json": "sha256-5x3hanzyxLH3nwERe8/wI2TB7i4kSwR2pISz0yLa+gk=" + "manifest.json": "sha256-uE41ppP3fPQSO1RWxPnhd8Zoqlh9cVyfgTKwwVT5Ajs=" } } }, @@ -19753,13 +19753,13 @@ "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", "runtime/components/data-table.js": "sha256-jj60XwNxQlssKZTff5HB9Z6v14UDZdK8O80kLP082l4=", "runtime/chunks/tables-B25ydUHs.js": "sha256-XqRdyfrSS93rVybWHq6a0WhrmZgaboHi5n8ymgwRbM8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-aygLfHiZmFXenQHQrHnjVcw8W0tp2SLdB7d/laGcKgA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-FieIuPCt66UIxpdAH0wuPBOrPEVXUqjJfyWMyCdO9nI=", "index.html": "sha256-wxdZWAwB7Q/aPOpcvws/xlqJAMNO1twAxfHnSVMuNlo=", "README.md": "sha256-bS0eRb53j0VgRsRbFv81sqclvoIS7Uv4m/FIBGXMqTw=", - "manifest.json": "sha256-HPNF+mZXjuU3YIozdl2drk3Led2FIYYUMYaIgdU5O68=" + "manifest.json": "sha256-2ou/6/GgNuGgAaCssLJwSinsCUqepjlg+x2p8l6YANI=" } } }, @@ -20052,13 +20052,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/timeline.js": "sha256-c1+8tebuE76i5IkY1RRqwNlDkRBrhVwBH4BiCMTSBs4=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-VnvBxMC1c6IWen0gQ3RLi0m3FOelH4E8j4xG+B5Zoas=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-pj/LmsP7e5l3NZI2ZWOLcerU4j0Vn1w2EloUpExz0nw=", "index.html": "sha256-Ob/LUhVAfw+2yZ5HV+/MpGcf5gBqNfOvKXpabGlMOEs=", "README.md": "sha256-CNaX7w50n7r2LnTaBiC5oWdtQN0tep2SK/Q0ggYScgo=", - "manifest.json": "sha256-xTdi7g85GA2tcVyJWhakoizpwEDxFhF3UjuOxkrx1Jg=" + "manifest.json": "sha256-0Or3Y8Tm/QMqmLp4lpUHlYERYtvsxQV0B7ZW9XTw6fg=" } } }, @@ -20405,13 +20405,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/chart.js": "sha256-J4rkX+ylh8URHbl2DxJ2FtbkHBtan2UOpNGVJIh1LjQ=", "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-/W9/IEOepx6zAHtGcRJs1x0lwfMFkVEiYDCV4y4byXw=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Wk7EuPuisom2ohEBkZvcgafrpN7xXzlCUaNrWq7BZEA=", "index.html": "sha256-HuXni+L2aI7ES/QsPUPIODbff80dbY+jNFEIzyVxLFg=", "README.md": "sha256-AvM1lRutn7M/qWu0sIsbdBF9wn5nT5Ag8avrXpfo9a4=", - "manifest.json": "sha256-vN7Sze32H790CZumX+te7Ju/JDPFYxXOYbJyBD+Fl34=" + "manifest.json": "sha256-lm2ZxifbDt5iYTAwiLkbvEREqGAmkeGkqLeoqfgfbLw=" } } }, @@ -20676,13 +20676,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/kbd.js": "sha256-xi2+ei38C1TTd2xavWMW/PM7cQTzc0o4g+7LNPNHnUQ=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-sKesLjkvspbpsD6walvgEF0NFv1fsIWXNbBy+hhtAUE=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-tpH9QDJi6WP1xXEjkGhicB0miKDe2fe69wAALVp2X5A=", "index.html": "sha256-n95EF5vEOXJJV0vVrIVOke9WC7Ja83CiFAFm4jiOY3w=", "README.md": "sha256-CY2b+9Xug3mHZLhawZDvq8BFYG/fjfij5F7sNanjAy4=", - "manifest.json": "sha256-T+bUtWMpGiYAfACd3t+B2UJX8FK3BzlfN5i/tTOryoY=" + "manifest.json": "sha256-N3o7jonx7ZxjgaydH4c9BuaHiyHBNtfdwvsGJReVWvc=" } } }, @@ -21138,13 +21138,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/alert.js": "sha256-afRZEs1g1g0l5Fh9oTXjl7R4w6ChNBFZ+N8x/BeJexg=", "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-cEV4WAKxLNKgYY5pU9nDVSG4toj5mM7vGZwyE+6Ui8o=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-QUAq9dxIFB1jlxB27CrSrEZKRLa4rC6qRLbWmR2t/ug=", "index.html": "sha256-F+j2IXSP/bqqvJ5iiyqLOkHvIuLBvN0FsF+7CX+ZhVs=", "README.md": "sha256-tx+34leZRjiZARWtxlnmDc9/6JPBGKFZl1od0IYo4kc=", - "manifest.json": "sha256-f/+taezEaLxGwimv58Q/I0IZhOlgqScdKlt4tv+J4js=" + "manifest.json": "sha256-2ZbWfxl+0O3OjPAuMynLSs9Kp25QuUMiwXSpMKBlxQ0=" } } }, @@ -21679,13 +21679,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/toast.js": "sha256-v6J5D8moC3m7GxC2mVYytkK8MOkwHSwODcmKmj1Kkgk=", "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-dMp7q8HbznH2LxwbeRaoK7WL/2M2GeVwkitql3aJ3GE=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-2DXrOBOlEPzc9p3N5SEbw98qHHSMYTxlOnR6gT91kkU=", "index.html": "sha256-UfXmgxl10YQJyIiSccW0Sy7gHSjlICq9a865B0vR+7Q=", "README.md": "sha256-Gqkqv+2L4+y8mTQfPGpUxoV4B+6QJazzN5XtXWfyj4w=", - "manifest.json": "sha256-Dulou4hwI8bILLX7ogZBb3IkLJsGcenBCv2301DmbKo=" + "manifest.json": "sha256-5G6eFKtb0RzEvUaf7y/U2BUwja0sO/DtWmx8/bruQU8=" } } }, @@ -21994,13 +21994,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/progress.js": "sha256-SoIKI41QOIzDVzCbEX4RjUwuYIgyVdRipglbNI30PdE=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-qVh6/s9QPg2t6WrczrtP5i8fP1blV8a6S9OZUF5oJdY=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Bm2XYmsDcMrSYl/yKw1emmfA++ea/EjE5wzSjdg0eyw=", "index.html": "sha256-PMCQa/n0AlL1bSbPiT96VPfHTQgJmUowUoHElZGYf5k=", "README.md": "sha256-oXXC+n+f426Xr1+uHSEamfpzBwqmaBbe41P73puQ9p4=", - "manifest.json": "sha256-1b2q82GAM6aew7BrlzqLA7+ZV6dnlY7OpesY4DV0bOc=" + "manifest.json": "sha256-r+zhlEfXkdl5bcryLN+l4mssjPuUGlyjB4vslOUMdck=" } } }, @@ -22297,13 +22297,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/loading-indicator.js": "sha256-iTQYSJMXD02jZHXKFvaFfVLsSwVgLrG7ERC0uWAqpvU=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-eNbtRNqnJDdDaKs9tYapfgCNRwMffdQ7e2TqjrYuL6w=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-yiCrGr/OXo7SakIH4qRV3wDHbj09EqyJ2F7eTQHbnbc=", "index.html": "sha256-MGxeLPPCJTIT6qFSP0xS4GBpdzFTGjBojEELvbNO6VY=", "README.md": "sha256-YVFITjZXVN2sAQCTUcMZO5v0Xsc63owlmsQGMTQ42wY=", - "manifest.json": "sha256-Z6/RoN7WPNcBLssWQ87bGJZ78aTSUa9ZuXMYDROZNus=" + "manifest.json": "sha256-E5QH4rXH0Q8cEQtr0bOGShuzZQlv5Y0cZ76Um3cCKCg=" } } }, @@ -22596,13 +22596,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/skeleton.js": "sha256-Ou8+/8NCHGRzG6ik6k6762M8G4PMLaBQXj4aPynetXo=", "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-JI92x7GOktbjpIm0AQnODJ4rVTJnEQA4DLP34bflM4k=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-/g7jxryHfbaG3yxoxK8NfCh2k5U92wPPELD/107+2Ps=", "index.html": "sha256-wOHcfVLjvDJzcjrxHt2FdIU6zvsgQKyM+mk68FWiW1g=", "README.md": "sha256-nzNnLPK+pu75MG+iTs+EMp/xOyJFTC/9GM9JCwIoCno=", - "manifest.json": "sha256-YCCxtxYLNlpJZqd02zALos+1RGYqYXZnhNIgbjjTOLk=" + "manifest.json": "sha256-4LwxROheBPrSRHAZZzi9L4TDIlPOW7pk4CjtpDmBKQw=" } } }, @@ -22970,13 +22970,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/tooltip.js": "sha256-3/N04wmhF1WPLWW0LBMN2pFnpLGTy7p7toYw2pZpNw0=", "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Skdu3czE82hMaq0VZwtG6ERV4Hud75l3iMhOfMR7K7U=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-+kSohyFbJg7z8/YUnlkzY1UQAu9ZLX7qE1eFLvk/1hI=", "index.html": "sha256-E+iyir+kE7FZW4yp4r+zjaBJSIcRsJGbvmwPckUJga0=", "README.md": "sha256-gCdLT45+37bldGYfH9LhZjTXGX04d3jZOS7ARTD3bCE=", - "manifest.json": "sha256-QxjcDTsBx4LoM8mRkg4NgUQUatj3fHOwB6EKt8pWLZw=" + "manifest.json": "sha256-LkcqlVgeLQw44bCRmlXlSU+9P8cA2jVRRTLSgZlvDps=" } } }, @@ -23323,13 +23323,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/popover.js": "sha256-P63Ou+ew1qtVXdZkxnO6uM5ZG7w9hOBlPK+HNXQbkAU=", "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-53zGKZZyZMB+sdGIbnQk30oFXcLvjoplsW7FfQ9W0u0=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-tBbkSUEedfklBWmTm/lh13o3rlYHe/9AGgvmXp+p/Lo=", "index.html": "sha256-qj6qyYYBmNfnfn4cPT10GeMQN/ToGtN/ZB6H3yjUV/g=", "README.md": "sha256-2w2CMw7jTANV0wE6ux5POoe9QeMf/7BVerq3YrpiziI=", - "manifest.json": "sha256-cbFFGYigmfXCHWbnqp7UDh18ygoUiqUWr96ofsWEhDM=" + "manifest.json": "sha256-Phnn5besyYINT3a2SO+Oyfo34q3wPJpuLaWvH2pQWAU=" } } }, @@ -24035,13 +24035,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/dialog.js": "sha256-e9pTCjxk1e95o6PW5WuKLJsHz87/SQRFeL9+DTQyk5I=", "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-d4bh9HaP4YOtfgWmP42qVqw3nqSJ3DF629AWjqoZTn4=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-wFFtRxUFWBTzxYOcblp+JjddYxJQF3QKoOb0/hIuSL0=", "index.html": "sha256-cDDMTM4Wj+7faOBKrvRWjGkb2tcMvyJcbhuH6ForsLs=", "README.md": "sha256-qhTQOsunJthiAQNFRNPTJx74lX2dH6rh6jISELzgD5Q=", - "manifest.json": "sha256-AJuEfuBHZb4d3lOAX/LxDDfwsCCYi6i4YdV+9O78IPY=" + "manifest.json": "sha256-ffV0ZOGvzK4N5REfOqb5SopYFtk70wS5so3vIH5qUHc=" } } }, @@ -24748,13 +24748,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/drawer.js": "sha256-vwjZdEg2SybEwAsIBL+uJuAs6ArJnLfrtqdRiOtleqA=", "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-39DmGp3B3f8+C/QGAv6xbiVXT7QviSaVCnHk8XpC158=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-RNAiKQJPioHCtfhMtqcsFaQFfwhKvdH+iIfLXOWo6QQ=", "index.html": "sha256-CbS/ignNl9YlA8MUwmXMnGVVRk6rR78IN2YGSe3T/OI=", "README.md": "sha256-fOfwfTYC9vdlgQFOfWiigzqCKfrU93VWnGHVQW9kH8s=", - "manifest.json": "sha256-sVEeq/PKuPmVSBR72cingvVcslqWxp/7MiJZtdMTaT0=" + "manifest.json": "sha256-4F6UZloyQg8I7wVtudpN0GlasZZCpflUeQnezTwqvss=" } } }, @@ -25194,13 +25194,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/empty-state.js": "sha256-bmsYB/w+TevvaR9K+tvrVuNDGxVPv2PYR4hbTkhw+dU=", "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Mdd72ooxolJDcPYScpT7yUM7Uj1SV5nk9LuG9vP0EeA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-j6rKuP4LmxmaKm47ZcfAqQ0LKMqN7l90HZwvUydHutQ=", "index.html": "sha256-rcFm3dTOVu+pB+gds4jp/elaQrgi/1rGF8xpNTCacL4=", "README.md": "sha256-460PP03z7gtyCcQW1opIbUBVyz/wg3Dv8SyzbynmB2E=", - "manifest.json": "sha256-h6FDAg6a5sS+S1za92hKQI46WLnC4dZBTi2eTWdOP+A=" + "manifest.json": "sha256-75nIi6f/Ht0GN4W2P39d86rZv1OvN/aduq/2EcG1HB4=" } } }, @@ -25564,13 +25564,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/error-state.js": "sha256-vgUhuSmkAd9uc2x8r5Oc5k2rjzWbEtFRnrR0smV/YqM=", "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-CdLPhgSZDY0ucB4/nfZpfphuYXcfoqslUTPyuhz2tDw=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-ORjrriOpBHk2VlqSsyeUSEs1medDwB5oaTT4RxrXLFs=", "index.html": "sha256-ypHtxbip0wQwfxcnTK23eRJ0nU1YTWrbBIr8zvdVgzA=", "README.md": "sha256-Dl3lNTMlz4fye9SN1UJc6WVgA6BbWKgqHMIRpH62yOY=", - "manifest.json": "sha256-tmU/T4Skbf9Eu3//L9hqqYCXoJofZolyF9xBuaRZ/fM=" + "manifest.json": "sha256-gv+zrrKBwqknOREXPEz57rKP+7GJco38FRkXeXQqAbU=" } } }, @@ -26112,13 +26112,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/code-editor.js": "sha256-F0O1Zc5wQaq5NGzIEEBzGXHEfj0hUaCR23D2hnUukLY=", "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-X9h2Mxr0yLKLoKffZDsC55HBiRmSX+SuRQkjkcxerOo=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-aD+1gDxKB5fijO+A+hjuTqChvHPDv5zp5tK9UPZhwLc=", "index.html": "sha256-Dn2d67XC/1eO3QNVfsBf4pv4f2WuhBmmk1fFbSiGnWY=", "README.md": "sha256-oP4WnaIDAzxwm22ndFvMgchWr7l/DH7YotacPAFZuO8=", - "manifest.json": "sha256-AZOed+UbhiUZzGPeg4XOfbQaDtbSuEA5oe+y2k51vjI=" + "manifest.json": "sha256-ilcy8XyaIxDvpFx8RrzkFJhHJ6uot99rm2kBpXxBYBI=" } } }, @@ -26492,13 +26492,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/editor-search.js": "sha256-tPLpeyxQ/8Gf/LImxqGBvRraQE6oFXtqIspmI84b8XA=", "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-M0SrYSnjmhmwR0wfAiNg1VU3bXhEQkYknaGRLw0fWMM=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-d4aAYzdcDHNmdiry3w1Y3xEHMEA6MELYHpoj25fZY7M=", "index.html": "sha256-nzYqIKBlE7peT4onxSzqAj0mwZHNcvHOF2jIuZV5iKo=", "README.md": "sha256-uCiQ7xpaMDEYDoL/7zMcafsbXKeQ+tnAyLmxgCMABh8=", - "manifest.json": "sha256-oRjcQaiNJcbQgPckQh0vjN6z83eBEU7mtbesGoE5HGk=" + "manifest.json": "sha256-tzETVZ5wEm/wqmqM6Gu3ONUNlEVtbZUiPneNH2sbPZ8=" } } }, @@ -27077,13 +27077,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/diagnostics.js": "sha256-nC94tOw1MCiaCz5hbJRQf8qjWzQDz53K24KiwRwR8ws=", "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-1uXLsplg978riCNhv/v5p+RvR0hW6fVdRnKgNUo+IYs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-oPPp/R+dnwC1tnH/Td+Hlrs3CRODUkA4Bvq/HK/fAUU=", "index.html": "sha256-Tq03gSM/g1JYQlO5vswlLUOSXHf9l2bEjBuZbLQpK1E=", "README.md": "sha256-zoebnEYS306DsFzwTsEnc2EoKA+8Dm/eyz4eTXdSnAs=", - "manifest.json": "sha256-Pxd8jPIYkeRwMC2E/I0DzzxVoxnL9iQ6p2cvAWl7Qkk=" + "manifest.json": "sha256-UpdG5YWwniZZMmaHLoJEtfjfHyOOvfgh9kwW7yzjGME=" } } }, @@ -27610,13 +27610,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/diff-view.js": "sha256-QfZm092MHlNhP9Vfs6IkWjXkbrGughYsBfHTOCL93cM=", "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-mibFUolrx0OWHlYNpEFTvfkMI0c6h4CUv7SWJ4eQVns=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-t7cx4Y+4qhIPiwFbRPz+6U12N/CFATPTfG7/iZf85zs=", "index.html": "sha256-EYPYe3QVJkVBz7byssoY6NHiAMZc9tW/oSLut2DPrX4=", "README.md": "sha256-2/6IFU4JJZ25X3ZvCCwHM1P9pvt3nJHAUfxoS/Ubi/0=", - "manifest.json": "sha256-cIqnQO+bVVoaU28MWcHfPoVhXheewGMtTBcDUDs8vxU=" + "manifest.json": "sha256-kxUgBrJ5pugX+Rn/YdpdeR3lTLsYCBlHWGv/+4xyeGY=" } } }, @@ -28163,13 +28163,13 @@ "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", "runtime/components/terminal.js": "sha256-nnvO5VIA3kECyTshxbykc7AqrK88ML0IDEe6bYvfsQs=", "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-U9mukzoAnquuoQ1KFzbK6bI+fxJdrdrhSiZgfwulwJM=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-WyXNyoxiAXNq3bLZRmrc1qS2XzgHghN+5tO+9HpocVA=", "index.html": "sha256-7nIjP5H9Tnolb/DAw1vtVGkOfqf2/oL9ZxMvSounzKk=", "README.md": "sha256-JMb0MyBFXbZ2TBIQrpRDNUjcH0R6qtmsRDfzwcOAY6o=", - "manifest.json": "sha256-sGsy8R0eqkr6bURvIwkRkH0fLyTW8pfdEwky7NiayLM=" + "manifest.json": "sha256-Um+BronLZKEFOHCEpSta1jnlVHpAUaE+SY2iEDpTXgA=" } } }, @@ -29000,13 +29000,13 @@ "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", "runtime/components/settings-panel.js": "sha256-eL+HBTD98ipggaB6cWxKOgb2UXkBgKT50n7xxlWPHn0=", "runtime/chunks/forms-BT3z7lNC.js": "sha256-Txmae07dWLj1H/FL869U0Kv84TQxzpdFeOg0g8zGK6I=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-bKV+vxJoQcQ+/WSkUADY0AkxpU9pAMAviGj+BrOQK1w=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Z1ZqDdIXySN8gWG0bvhT8iMaa+GaOyHy/vumYpCsYt8=", "index.html": "sha256-jGGdyR2U7IytSpOvqtrVJUJKtnNfW/khN9J+vCUatNM=", "README.md": "sha256-Jbd8VDlivmCdwjmixGLdZrE/QQ9xdJyk+UIIOcLDqZE=", - "manifest.json": "sha256-pyfwmrg9NQ+SMVaMISW1+5BGdWSdQ6Ai43LdqNGYwmQ=" + "manifest.json": "sha256-vLsgXoGOv6Ek2Vt1iEvKgMZAwnYyn2CTBoyAh/wxfJw=" } } }, @@ -29933,13 +29933,13 @@ "runtime/components/select.js": "sha256-yyq0jsJOysQGTPpFoA1C1aRWSIukrk+M4Ro2ZwCyWbw=", "runtime/components/admin-form.js": "sha256-aN07ea+gUj6aAxwJjeILpqJFPUQJ27g3LAIjpHmljNg=", "runtime/chunks/forms-BT3z7lNC.js": "sha256-Txmae07dWLj1H/FL869U0Kv84TQxzpdFeOg0g8zGK6I=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Of5oLJY6n5Yfqu44/xCAuuJEYRoCg4Kr+YZbVggbwZE=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-TRLraonRxggrZcfXS9jlN+nTIOpRHiXbMKQNm8NbR2A=", "index.html": "sha256-HsmeIqneb7G9ZHVJEuzAqXdP7AYU8OlzG8Rs70uYyBQ=", "README.md": "sha256-bid+/EA6npftuo0cAZQP6rg+96qu7gNC4h/Klx23PF0=", - "manifest.json": "sha256-HtST9X/UpiRDsFEMo7i1ElwMpiALSDf/MyJKLw0Dk90=" + "manifest.json": "sha256-nYS8jMsuxKEj8F3dOHKvnVCccydqs1Pp3Z6SsTCUoOU=" } } }, @@ -30709,13 +30709,13 @@ "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", "runtime/components/filterable-table.js": "sha256-1tup9iQXvwHywM5vJL3oiz0gLiDGNw/xjkZ91AA+Sok=", "runtime/chunks/tables-B25ydUHs.js": "sha256-XqRdyfrSS93rVybWHq6a0WhrmZgaboHi5n8ymgwRbM8=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-ZpN1xEJy4fV/PBDvH91mkuN2CZqhCUo5wpeCs27jREo=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-3PbF9wWtnKy3q07M9x690D730biEbSwu20wHAcvPPEE=", "index.html": "sha256-61p1J3mpIgWTPXP4+wTHI0p/MffdvGq+yeT7j0urEZA=", "README.md": "sha256-eYSWLSbTgjyr+5CUJR+E3qhY267Qh6rmF+5P40UanuU=", - "manifest.json": "sha256-tE2lTsJjQH6ZBaYTO4TyapuKMSc19KHg0ode/N3j828=" + "manifest.json": "sha256-6e9ro37teOmSFrYcAJ7t+PP1FQ9FEb9GhcBjA3Ah5iw=" } } }, @@ -31689,13 +31689,13 @@ "runtime/components/i3-window-frame.js": "sha256-uqfVHNwkr/11a11fshN7f0r/dXipCi1Vfc0AlLb+i9c=", "runtime/chunks/compositions-d6BkKTYf.js": "sha256-El5csGAVMeeZWmJ1ztdXW3O3t2AQPrf3YrEOMkGX17c=", "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Yk/0tRkcDttUSZKxyg6O6C9kumrEAGehNElFt382jeA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-nNyvwUVLU3Rdy3x0UcZN+IkCA1+Ot5CVwjUB54GDnq8=", "index.html": "sha256-5VNshBKwk0GCY7ID/iL5fiZjb6VRrIZhEdVK/HjtiK0=", "README.md": "sha256-C0hpJoSU0W6E5VFxM/5nRjno1clSop0NLti9ZjvJiO0=", - "manifest.json": "sha256-SQObA3CbBJSibf9fY3JRlURdH9FXLA7SfbAElKJ+pPs=" + "manifest.json": "sha256-U0UgHnHKVp5XKkj1fNN5b+MOeYjoFSjDI5MDm6KE5Qw=" } } }, @@ -32170,13 +32170,13 @@ "runtime/components/file-browser.js": "sha256-mmsIwfdO+8Xy7vrRylWFBDIwAoWKfkgmb8J17rxDHVs=", "runtime/chunks/compositions-d6BkKTYf.js": "sha256-El5csGAVMeeZWmJ1ztdXW3O3t2AQPrf3YrEOMkGX17c=", "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-jXsUncF3ZqNTAY54eALB2XHlOFiiumSXp+AnM14Tz1Q=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-TbSmPr7cV31g3WqgPi6LboOGQdmgxz/89Tf/3ld2pfU=", "index.html": "sha256-68VZEF9M4ZFNgI9IZ7yrpktM4/9dA+GR/D6aTo6ocn0=", "README.md": "sha256-pldg7PuzlPHL6J8L3tFRBhM4Mqi8AlcED3V2DXOXZRU=", - "manifest.json": "sha256-ega8f7vafG5gKtOcw4Aole+jb7E5C7xB7jZhdJWN0bQ=" + "manifest.json": "sha256-dumD1CMdclQzMmPsrLn3Denb28aFPOcd34uk/ZtbEgI=" } } }, @@ -32670,13 +32670,13 @@ "runtime/components/compact-dashboard.js": "sha256-AyJRimILR3ZhpG7LU6Jtut1sQj0LSEFhOC9MT+gVfbQ=", "runtime/chunks/compositions-d6BkKTYf.js": "sha256-El5csGAVMeeZWmJ1ztdXW3O3t2AQPrf3YrEOMkGX17c=", "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "tokens.css": "sha256-5KKDTxOLymgbrDN8N70C5k46wvIT1IQF4wwPwpLNy4c=", + "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-CK9kd2wDntxSLF6J4F4+3SFybCPdr/tSqL7xJpw3hFs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-I++zY2714BqcfCh02WgcXCFwujrwXLK4TwP9wII+QE4=", "index.html": "sha256-3/JWb8Uk24wjHBuQjWRaXDvwfUi9Mp9wjh4uYtdNxQ4=", "README.md": "sha256-6g2tbWoWmdPy5ju9eAR0VdQ5vp0GjEEftnqhmjoP1j4=", - "manifest.json": "sha256-8Tz2CHZNJCFbdxv2h7ms7Dvyie84SceiClcFGjQ4iT0=" + "manifest.json": "sha256-6VcljZV/ScZZHBdlliiCRDKmNJun1WvkMSswT57Yue4=" } } } diff --git a/packages/ui/dist/register/form-builder.js b/packages/ui/dist/register/form-builder.js index a723c3c65..320e671f8 100644 --- a/packages/ui/dist/register/form-builder.js +++ b/packages/ui/dist/register/form-builder.js @@ -1,5 +1,5 @@ import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; -import { t as J3w1FormBuilder } from "../chunks/form-builder-Dkweb1xD.js"; +import { t as J3w1FormBuilder } from "../chunks/form-builder-C6Rhfsz6.js"; //#region .cache/ui-build/entries/register/form-builder.js var element = registerElement("j3w1-form-builder", J3w1FormBuilder); //#endregion diff --git a/packages/ui/dist/tokens.css b/packages/ui/dist/tokens.css index 69307ea93..b7acac46b 100644 --- a/packages/ui/dist/tokens.css +++ b/packages/ui/dist/tokens.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/ports/chatgpt/capabilities.json b/ports/chatgpt/capabilities.json index bb61c72fb..65a14d089 100644 --- a/ports/chatgpt/capabilities.json +++ b/ports/chatgpt/capabilities.json @@ -1534,6 +1534,16 @@ "surface": "typography", "reason": "ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default)." }, + "font.line-height.display": { + "state": "unsupported", + "surface": "typography", + "reason": "ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default)." + }, + "font.line-height.title": { + "state": "unsupported", + "surface": "typography", + "reason": "ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default)." + }, "font.line-height.h1": { "state": "unsupported", "surface": "typography", @@ -1584,6 +1594,16 @@ "surface": "appearance-settings", "reason": "Set by Code font size." }, + "font.size.display": { + "state": "unsupported", + "surface": "typography", + "reason": "ChatGPT has only a UI size and a code size." + }, + "font.size.title": { + "state": "unsupported", + "surface": "typography", + "reason": "ChatGPT has only a UI size and a code size." + }, "font.size.h1": { "state": "unsupported", "surface": "typography", diff --git a/ports/chatgpt/mapping.json b/ports/chatgpt/mapping.json index 89194e9ed..a75d61ada 100644 --- a/ports/chatgpt/mapping.json +++ b/ports/chatgpt/mapping.json @@ -324,6 +324,8 @@ "font.letter-spacing.terminal": "ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).", "font.line-height.caption": "ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).", "font.line-height.code": "ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).", + "font.line-height.display": "ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).", + "font.line-height.title": "ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).", "font.line-height.h1": "ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).", "font.line-height.h2": "ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).", "font.line-height.h3": "ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).", @@ -333,6 +335,8 @@ "font.line-height.ui-md": "ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).", "font.line-height.ui-sm": "ChatGPT uses its own fonts (the UI and code font can be chosen by name, but the port leaves them as the system default).", "font.size.caption": "ChatGPT has only a UI size and a code size.", + "font.size.display": "ChatGPT has only a UI size and a code size.", + "font.size.title": "ChatGPT has only a UI size and a code size.", "font.size.h1": "ChatGPT has only a UI size and a code size.", "font.size.h2": "ChatGPT has only a UI size and a code size.", "font.size.h3": "ChatGPT has only a UI size and a code size.", diff --git a/ports/chatgpt/port.json b/ports/chatgpt/port.json index 7e0ee0ff4..1c618f9af 100644 --- a/ports/chatgpt/port.json +++ b/ports/chatgpt/port.json @@ -4,7 +4,7 @@ "displayName": "ChatGPT desktop app (Appearance)", "status": "experimental", "themeVersion": "4.0.0", - "tokenDigest": "sha256-zFvYCG+sRacSRpLqVjVsMUNxxfakWzjnJrCN7WOgQYY=", + "tokenDigest": "sha256-3KBrfmIiz4L6Qyqvi99TdTe4+5NeuA0ZWZe3Am4sRo4=", "profile": "default", "format": "chatgpt-appearance", "targetVersions": [ diff --git a/ports/claude-code/capabilities.json b/ports/claude-code/capabilities.json index c3d010929..46408d1e4 100644 --- a/ports/claude-code/capabilities.json +++ b/ports/claude-code/capabilities.json @@ -1510,6 +1510,16 @@ "surface": "outside-claude", "reason": "Not a colour; a Claude Code theme carries colours only." }, + "font.line-height.display": { + "state": "out-of-scope", + "surface": "outside-claude", + "reason": "Not a colour; a Claude Code theme carries colours only." + }, + "font.line-height.title": { + "state": "out-of-scope", + "surface": "outside-claude", + "reason": "Not a colour; a Claude Code theme carries colours only." + }, "font.line-height.h1": { "state": "out-of-scope", "surface": "outside-claude", @@ -1560,6 +1570,16 @@ "surface": "outside-claude", "reason": "Not a colour; a Claude Code theme carries colours only." }, + "font.size.display": { + "state": "out-of-scope", + "surface": "outside-claude", + "reason": "Not a colour; a Claude Code theme carries colours only." + }, + "font.size.title": { + "state": "out-of-scope", + "surface": "outside-claude", + "reason": "Not a colour; a Claude Code theme carries colours only." + }, "font.size.h1": { "state": "out-of-scope", "surface": "outside-claude", diff --git a/ports/claude-code/mapping.json b/ports/claude-code/mapping.json index a2fbece55..9685d49a5 100644 --- a/ports/claude-code/mapping.json +++ b/ports/claude-code/mapping.json @@ -399,6 +399,8 @@ "font.letter-spacing.terminal": "Not a colour; a Claude Code theme carries colours only.", "font.line-height.caption": "Not a colour; a Claude Code theme carries colours only.", "font.line-height.code": "Not a colour; a Claude Code theme carries colours only.", + "font.line-height.display": "Not a colour; a Claude Code theme carries colours only.", + "font.line-height.title": "Not a colour; a Claude Code theme carries colours only.", "font.line-height.h1": "Not a colour; a Claude Code theme carries colours only.", "font.line-height.h2": "Not a colour; a Claude Code theme carries colours only.", "font.line-height.h3": "Not a colour; a Claude Code theme carries colours only.", @@ -409,6 +411,8 @@ "font.line-height.ui-sm": "Not a colour; a Claude Code theme carries colours only.", "font.size.caption": "Not a colour; a Claude Code theme carries colours only.", "font.size.code": "Not a colour; a Claude Code theme carries colours only.", + "font.size.display": "Not a colour; a Claude Code theme carries colours only.", + "font.size.title": "Not a colour; a Claude Code theme carries colours only.", "font.size.h1": "Not a colour; a Claude Code theme carries colours only.", "font.size.h2": "Not a colour; a Claude Code theme carries colours only.", "font.size.h3": "Not a colour; a Claude Code theme carries colours only.", diff --git a/ports/claude-code/port.json b/ports/claude-code/port.json index 6786abdef..0df48cd06 100644 --- a/ports/claude-code/port.json +++ b/ports/claude-code/port.json @@ -4,7 +4,7 @@ "displayName": "Claude Code (custom theme)", "status": "experimental", "themeVersion": "4.0.0", - "tokenDigest": "sha256-zFvYCG+sRacSRpLqVjVsMUNxxfakWzjnJrCN7WOgQYY=", + "tokenDigest": "sha256-3KBrfmIiz4L6Qyqvi99TdTe4+5NeuA0ZWZe3Am4sRo4=", "profile": "default", "format": "claude-theme-json", "targetVersions": [ diff --git a/ports/codex/capabilities.json b/ports/codex/capabilities.json index fdd3c664f..a28aef5f5 100644 --- a/ports/codex/capabilities.json +++ b/ports/codex/capabilities.json @@ -1514,6 +1514,16 @@ "surface": "outside-codex", "reason": "Not a colour; a tmTheme carries colours only." }, + "font.line-height.display": { + "state": "out-of-scope", + "surface": "outside-codex", + "reason": "Not a colour; a tmTheme carries colours only." + }, + "font.line-height.title": { + "state": "out-of-scope", + "surface": "outside-codex", + "reason": "Not a colour; a tmTheme carries colours only." + }, "font.line-height.h1": { "state": "out-of-scope", "surface": "outside-codex", @@ -1564,6 +1574,16 @@ "surface": "outside-codex", "reason": "Not a colour; a tmTheme carries colours only." }, + "font.size.display": { + "state": "out-of-scope", + "surface": "outside-codex", + "reason": "Not a colour; a tmTheme carries colours only." + }, + "font.size.title": { + "state": "out-of-scope", + "surface": "outside-codex", + "reason": "Not a colour; a tmTheme carries colours only." + }, "font.size.h1": { "state": "out-of-scope", "surface": "outside-codex", diff --git a/ports/codex/mapping.json b/ports/codex/mapping.json index fa8c1e9b1..b8200251f 100644 --- a/ports/codex/mapping.json +++ b/ports/codex/mapping.json @@ -345,6 +345,8 @@ "font.letter-spacing.terminal": "Not a colour; a tmTheme carries colours only.", "font.line-height.caption": "Not a colour; a tmTheme carries colours only.", "font.line-height.code": "Not a colour; a tmTheme carries colours only.", + "font.line-height.display": "Not a colour; a tmTheme carries colours only.", + "font.line-height.title": "Not a colour; a tmTheme carries colours only.", "font.line-height.h1": "Not a colour; a tmTheme carries colours only.", "font.line-height.h2": "Not a colour; a tmTheme carries colours only.", "font.line-height.h3": "Not a colour; a tmTheme carries colours only.", @@ -355,6 +357,8 @@ "font.line-height.ui-sm": "Not a colour; a tmTheme carries colours only.", "font.size.caption": "Not a colour; a tmTheme carries colours only.", "font.size.code": "Not a colour; a tmTheme carries colours only.", + "font.size.display": "Not a colour; a tmTheme carries colours only.", + "font.size.title": "Not a colour; a tmTheme carries colours only.", "font.size.h1": "Not a colour; a tmTheme carries colours only.", "font.size.h2": "Not a colour; a tmTheme carries colours only.", "font.size.h3": "Not a colour; a tmTheme carries colours only.", diff --git a/ports/codex/port.json b/ports/codex/port.json index e96a08f1f..c614fd759 100644 --- a/ports/codex/port.json +++ b/ports/codex/port.json @@ -4,7 +4,7 @@ "displayName": "Codex CLI (tmTheme)", "status": "experimental", "themeVersion": "4.0.0", - "tokenDigest": "sha256-zFvYCG+sRacSRpLqVjVsMUNxxfakWzjnJrCN7WOgQYY=", + "tokenDigest": "sha256-3KBrfmIiz4L6Qyqvi99TdTe4+5NeuA0ZWZe3Am4sRo4=", "profile": "default", "format": "codex-tmtheme", "targetVersions": [ diff --git a/ports/ghostty/capabilities.json b/ports/ghostty/capabilities.json index 72c4ab303..9bc326e6e 100644 --- a/ports/ghostty/capabilities.json +++ b/ports/ghostty/capabilities.json @@ -1514,6 +1514,16 @@ "surface": "outside-terminal", "reason": "Not a colour; a terminal theme file carries colours only." }, + "font.line-height.display": { + "state": "out-of-scope", + "surface": "outside-terminal", + "reason": "Not a colour; a terminal theme file carries colours only." + }, + "font.line-height.title": { + "state": "out-of-scope", + "surface": "outside-terminal", + "reason": "Not a colour; a terminal theme file carries colours only." + }, "font.line-height.h1": { "state": "out-of-scope", "surface": "outside-terminal", @@ -1564,6 +1574,16 @@ "surface": "outside-terminal", "reason": "Not a colour; a terminal theme file carries colours only." }, + "font.size.display": { + "state": "out-of-scope", + "surface": "outside-terminal", + "reason": "Not a colour; a terminal theme file carries colours only." + }, + "font.size.title": { + "state": "out-of-scope", + "surface": "outside-terminal", + "reason": "Not a colour; a terminal theme file carries colours only." + }, "font.size.h1": { "state": "out-of-scope", "surface": "outside-terminal", diff --git a/ports/ghostty/mapping.json b/ports/ghostty/mapping.json index 9fa005210..0700eec17 100644 --- a/ports/ghostty/mapping.json +++ b/ports/ghostty/mapping.json @@ -345,6 +345,8 @@ "font.letter-spacing.terminal": "A Ghostty theme carries colours; Ghostty has no letter-spacing key.", "font.line-height.caption": "Not a colour; a terminal theme file carries colours only.", "font.line-height.code": "Not a colour; a terminal theme file carries colours only.", + "font.line-height.display": "Not a colour; a terminal theme file carries colours only.", + "font.line-height.title": "Not a colour; a terminal theme file carries colours only.", "font.line-height.h1": "Not a colour; a terminal theme file carries colours only.", "font.line-height.h2": "Not a colour; a terminal theme file carries colours only.", "font.line-height.h3": "Not a colour; a terminal theme file carries colours only.", @@ -355,6 +357,8 @@ "font.line-height.ui-sm": "Not a colour; a terminal theme file carries colours only.", "font.size.caption": "Not a colour; a terminal theme file carries colours only.", "font.size.code": "Not a colour; a terminal theme file carries colours only.", + "font.size.display": "Not a colour; a terminal theme file carries colours only.", + "font.size.title": "Not a colour; a terminal theme file carries colours only.", "font.size.h1": "Not a colour; a terminal theme file carries colours only.", "font.size.h2": "Not a colour; a terminal theme file carries colours only.", "font.size.h3": "Not a colour; a terminal theme file carries colours only.", diff --git a/ports/ghostty/port.json b/ports/ghostty/port.json index d5686daad..068879537 100644 --- a/ports/ghostty/port.json +++ b/ports/ghostty/port.json @@ -4,7 +4,7 @@ "displayName": "Ghostty theme", "status": "experimental", "themeVersion": "4.0.0", - "tokenDigest": "sha256-zFvYCG+sRacSRpLqVjVsMUNxxfakWzjnJrCN7WOgQYY=", + "tokenDigest": "sha256-3KBrfmIiz4L6Qyqvi99TdTe4+5NeuA0ZWZe3Am4sRo4=", "profile": "default", "format": "ghostty-config", "targetVersions": [ diff --git a/ports/obsidian/capabilities.json b/ports/obsidian/capabilities.json index 4a3f32aa1..abe78d102 100644 --- a/ports/obsidian/capabilities.json +++ b/ports/obsidian/capabilities.json @@ -1507,6 +1507,16 @@ "surface": "host-behavior", "reason": "font.size.terminal: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host." }, + "font.size.display": { + "state": "inherited", + "surface": "host-behavior", + "reason": "font.size.display: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host." + }, + "font.size.title": { + "state": "inherited", + "surface": "host-behavior", + "reason": "font.size.title: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host." + }, "font.size.h1": { "state": "inherited", "surface": "host-behavior", @@ -1557,6 +1567,16 @@ "surface": "host-behavior", "reason": "font.line-height.terminal: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host." }, + "font.line-height.display": { + "state": "inherited", + "surface": "host-behavior", + "reason": "font.line-height.display: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host." + }, + "font.line-height.title": { + "state": "inherited", + "surface": "host-behavior", + "reason": "font.line-height.title: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host." + }, "font.line-height.h1": { "state": "inherited", "surface": "host-behavior", diff --git a/ports/obsidian/mapping.json b/ports/obsidian/mapping.json index e43a63359..f03c74374 100644 --- a/ports/obsidian/mapping.json +++ b/ports/obsidian/mapping.json @@ -656,6 +656,8 @@ "font.size.reading": "font.size.reading: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.", "font.size.code": "font.size.code: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.", "font.size.terminal": "font.size.terminal: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.", + "font.size.display": "font.size.display: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.", + "font.size.title": "font.size.title: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.", "font.size.h1": "font.size.h1: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.", "font.size.h2": "font.size.h2: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.", "font.size.h3": "font.size.h3: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.", @@ -666,6 +668,8 @@ "font.line-height.reading": "font.line-height.reading: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.", "font.line-height.code": "font.line-height.code: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.", "font.line-height.terminal": "font.line-height.terminal: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.", + "font.line-height.display": "font.line-height.display: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.", + "font.line-height.title": "font.line-height.title: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.", "font.line-height.h1": "font.line-height.h1: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.", "font.line-height.h2": "font.line-height.h2: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.", "font.line-height.h3": "font.line-height.h3: preserve user sizes, zoom and native layout/target, motion or focus geometry; the reference metric is not imposed on the host.", diff --git a/ports/obsidian/port.json b/ports/obsidian/port.json index 4874342f1..57cb68983 100644 --- a/ports/obsidian/port.json +++ b/ports/obsidian/port.json @@ -4,7 +4,7 @@ "displayName": "Obsidian theme", "status": "experimental", "themeVersion": "4.0.0", - "tokenDigest": "sha256-zFvYCG+sRacSRpLqVjVsMUNxxfakWzjnJrCN7WOgQYY=", + "tokenDigest": "sha256-3KBrfmIiz4L6Qyqvi99TdTe4+5NeuA0ZWZe3Am4sRo4=", "profile": "default", "format": "obsidian-theme", "targetVersions": [ diff --git a/ports/orca/capabilities.json b/ports/orca/capabilities.json index da7e92741..b9736592c 100644 --- a/ports/orca/capabilities.json +++ b/ports/orca/capabilities.json @@ -1518,6 +1518,16 @@ "surface": "outside-terminal", "reason": "Not a colour; a terminal theme file carries colours only." }, + "font.line-height.display": { + "state": "out-of-scope", + "surface": "outside-terminal", + "reason": "Not a colour; a terminal theme file carries colours only." + }, + "font.line-height.title": { + "state": "out-of-scope", + "surface": "outside-terminal", + "reason": "Not a colour; a terminal theme file carries colours only." + }, "font.line-height.h1": { "state": "out-of-scope", "surface": "outside-terminal", @@ -1568,6 +1578,16 @@ "surface": "outside-terminal", "reason": "Not a colour; a terminal theme file carries colours only." }, + "font.size.display": { + "state": "out-of-scope", + "surface": "outside-terminal", + "reason": "Not a colour; a terminal theme file carries colours only." + }, + "font.size.title": { + "state": "out-of-scope", + "surface": "outside-terminal", + "reason": "Not a colour; a terminal theme file carries colours only." + }, "font.size.h1": { "state": "out-of-scope", "surface": "outside-terminal", diff --git a/ports/orca/mapping.json b/ports/orca/mapping.json index 1fe38b972..03901f9e1 100644 --- a/ports/orca/mapping.json +++ b/ports/orca/mapping.json @@ -350,6 +350,8 @@ "font.letter-spacing.terminal": "Neither the Ghostty config nor Orca's import has a letter-spacing key.", "font.line-height.caption": "Not a colour; a terminal theme file carries colours only.", "font.line-height.code": "Not a colour; a terminal theme file carries colours only.", + "font.line-height.display": "Not a colour; a terminal theme file carries colours only.", + "font.line-height.title": "Not a colour; a terminal theme file carries colours only.", "font.line-height.h1": "Not a colour; a terminal theme file carries colours only.", "font.line-height.h2": "Not a colour; a terminal theme file carries colours only.", "font.line-height.h3": "Not a colour; a terminal theme file carries colours only.", @@ -360,6 +362,8 @@ "font.line-height.ui-sm": "Not a colour; a terminal theme file carries colours only.", "font.size.caption": "Not a colour; a terminal theme file carries colours only.", "font.size.code": "Not a colour; a terminal theme file carries colours only.", + "font.size.display": "Not a colour; a terminal theme file carries colours only.", + "font.size.title": "Not a colour; a terminal theme file carries colours only.", "font.size.h1": "Not a colour; a terminal theme file carries colours only.", "font.size.h2": "Not a colour; a terminal theme file carries colours only.", "font.size.h3": "Not a colour; a terminal theme file carries colours only.", diff --git a/ports/orca/port.json b/ports/orca/port.json index 25dfb77f0..cdc2072a0 100644 --- a/ports/orca/port.json +++ b/ports/orca/port.json @@ -4,7 +4,7 @@ "displayName": "Orca (Ghostty config import)", "status": "experimental", "themeVersion": "4.0.0", - "tokenDigest": "sha256-zFvYCG+sRacSRpLqVjVsMUNxxfakWzjnJrCN7WOgQYY=", + "tokenDigest": "sha256-3KBrfmIiz4L6Qyqvi99TdTe4+5NeuA0ZWZe3Am4sRo4=", "profile": "default", "format": "ghostty-config", "targetVersions": [ diff --git a/ports/telegram/capabilities.json b/ports/telegram/capabilities.json index 50f4e8fce..3ff7271dc 100644 --- a/ports/telegram/capabilities.json +++ b/ports/telegram/capabilities.json @@ -1530,6 +1530,16 @@ "surface": "typography", "reason": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these." }, + "font.size.display": { + "state": "inherited", + "surface": "typography", + "reason": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these." + }, + "font.size.title": { + "state": "inherited", + "surface": "typography", + "reason": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these." + }, "font.size.h1": { "state": "inherited", "surface": "typography", @@ -1580,6 +1590,16 @@ "surface": "typography", "reason": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these." }, + "font.line-height.display": { + "state": "inherited", + "surface": "typography", + "reason": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these." + }, + "font.line-height.title": { + "state": "inherited", + "surface": "typography", + "reason": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these." + }, "font.line-height.h1": { "state": "inherited", "surface": "typography", diff --git a/ports/telegram/mapping.json b/ports/telegram/mapping.json index b4526484f..7c4bf80f8 100644 --- a/ports/telegram/mapping.json +++ b/ports/telegram/mapping.json @@ -1544,6 +1544,8 @@ "font.size.reading": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.", "font.size.code": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.", "font.size.terminal": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.", + "font.size.display": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.", + "font.size.title": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.", "font.size.h1": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.", "font.size.h2": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.", "font.size.h3": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.", @@ -1554,6 +1556,8 @@ "font.line-height.reading": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.", "font.line-height.code": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.", "font.line-height.terminal": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.", + "font.line-height.display": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.", + "font.line-height.title": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.", "font.line-height.h1": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.", "font.line-height.h2": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.", "font.line-height.h3": "Telegram theme files cannot set geometry, font metrics, layout, motion or focus-ring shape; host settings and accessibility preferences own these.", diff --git a/ports/telegram/port.json b/ports/telegram/port.json index 58722d954..2a900ce77 100644 --- a/ports/telegram/port.json +++ b/ports/telegram/port.json @@ -4,7 +4,7 @@ "displayName": "Telegram Android and Desktop", "status": "experimental", "themeVersion": "4.0.0", - "tokenDigest": "sha256-zFvYCG+sRacSRpLqVjVsMUNxxfakWzjnJrCN7WOgQYY=", + "tokenDigest": "sha256-3KBrfmIiz4L6Qyqvi99TdTe4+5NeuA0ZWZe3Am4sRo4=", "profile": "default", "format": "telegram-theme", "targetVersions": [ diff --git a/ports/warp/capabilities.json b/ports/warp/capabilities.json index f77db78ee..beea1dcc4 100644 --- a/ports/warp/capabilities.json +++ b/ports/warp/capabilities.json @@ -1514,6 +1514,16 @@ "surface": "outside-terminal", "reason": "Not a colour; a terminal theme file carries colours only." }, + "font.line-height.display": { + "state": "out-of-scope", + "surface": "outside-terminal", + "reason": "Not a colour; a terminal theme file carries colours only." + }, + "font.line-height.title": { + "state": "out-of-scope", + "surface": "outside-terminal", + "reason": "Not a colour; a terminal theme file carries colours only." + }, "font.line-height.h1": { "state": "out-of-scope", "surface": "outside-terminal", @@ -1564,6 +1574,16 @@ "surface": "outside-terminal", "reason": "Not a colour; a terminal theme file carries colours only." }, + "font.size.display": { + "state": "out-of-scope", + "surface": "outside-terminal", + "reason": "Not a colour; a terminal theme file carries colours only." + }, + "font.size.title": { + "state": "out-of-scope", + "surface": "outside-terminal", + "reason": "Not a colour; a terminal theme file carries colours only." + }, "font.size.h1": { "state": "out-of-scope", "surface": "outside-terminal", diff --git a/ports/warp/mapping.json b/ports/warp/mapping.json index bb30c10d8..a573fb2a2 100644 --- a/ports/warp/mapping.json +++ b/ports/warp/mapping.json @@ -340,6 +340,8 @@ "font.letter-spacing.terminal": "The application's own terminal font setting.", "font.line-height.caption": "Not a colour; a terminal theme file carries colours only.", "font.line-height.code": "Not a colour; a terminal theme file carries colours only.", + "font.line-height.display": "Not a colour; a terminal theme file carries colours only.", + "font.line-height.title": "Not a colour; a terminal theme file carries colours only.", "font.line-height.h1": "Not a colour; a terminal theme file carries colours only.", "font.line-height.h2": "Not a colour; a terminal theme file carries colours only.", "font.line-height.h3": "Not a colour; a terminal theme file carries colours only.", @@ -350,6 +352,8 @@ "font.line-height.ui-sm": "Not a colour; a terminal theme file carries colours only.", "font.size.caption": "Not a colour; a terminal theme file carries colours only.", "font.size.code": "Not a colour; a terminal theme file carries colours only.", + "font.size.display": "Not a colour; a terminal theme file carries colours only.", + "font.size.title": "Not a colour; a terminal theme file carries colours only.", "font.size.h1": "Not a colour; a terminal theme file carries colours only.", "font.size.h2": "Not a colour; a terminal theme file carries colours only.", "font.size.h3": "Not a colour; a terminal theme file carries colours only.", diff --git a/ports/warp/port.json b/ports/warp/port.json index 879728ac2..120a194ce 100644 --- a/ports/warp/port.json +++ b/ports/warp/port.json @@ -4,7 +4,7 @@ "displayName": "Warp theme YAML (also Orca's Import from YAML)", "status": "experimental", "themeVersion": "4.0.0", - "tokenDigest": "sha256-zFvYCG+sRacSRpLqVjVsMUNxxfakWzjnJrCN7WOgQYY=", + "tokenDigest": "sha256-3KBrfmIiz4L6Qyqvi99TdTe4+5NeuA0ZWZe3Am4sRo4=", "profile": "default", "format": "warp-yaml", "targetVersions": [ diff --git a/ports/windows/capabilities.json b/ports/windows/capabilities.json index a24fb875b..10bd61b74 100644 --- a/ports/windows/capabilities.json +++ b/ports/windows/capabilities.json @@ -1509,6 +1509,16 @@ "surface": "unsupported", "reason": "Outside Windows visual adapter scope; preserve host semantics." }, + "font.size.display": { + "state": "unsupported", + "surface": "unsupported", + "reason": "Outside Windows visual adapter scope; preserve host semantics." + }, + "font.size.title": { + "state": "unsupported", + "surface": "unsupported", + "reason": "Outside Windows visual adapter scope; preserve host semantics." + }, "font.size.h1": { "state": "mapped", "surface": "powertoys", @@ -1559,6 +1569,16 @@ "surface": "unsupported", "reason": "Outside Windows visual adapter scope; preserve host semantics." }, + "font.line-height.display": { + "state": "unsupported", + "surface": "unsupported", + "reason": "Outside Windows visual adapter scope; preserve host semantics." + }, + "font.line-height.title": { + "state": "unsupported", + "surface": "unsupported", + "reason": "Outside Windows visual adapter scope; preserve host semantics." + }, "font.line-height.h1": { "state": "mapped", "surface": "powertoys", diff --git a/ports/windows/mapping.json b/ports/windows/mapping.json index b3a8fe2ba..b7bd2c3e8 100644 --- a/ports/windows/mapping.json +++ b/ports/windows/mapping.json @@ -2474,11 +2474,15 @@ "font.size.ui-md": "Outside Windows visual adapter scope; preserve host semantics.", "font.size.ui-lg": "Outside Windows visual adapter scope; preserve host semantics.", "font.size.terminal": "Outside Windows visual adapter scope; preserve host semantics.", + "font.size.display": "Outside Windows visual adapter scope; preserve host semantics.", + "font.size.title": "Outside Windows visual adapter scope; preserve host semantics.", "font.size.caption": "Outside Windows visual adapter scope; preserve host semantics.", "font.line-height.ui-sm": "Outside Windows visual adapter scope; preserve host semantics.", "font.line-height.ui-md": "Outside Windows visual adapter scope; preserve host semantics.", "font.line-height.ui-lg": "Outside Windows visual adapter scope; preserve host semantics.", "font.line-height.terminal": "Outside Windows visual adapter scope; preserve host semantics.", + "font.line-height.display": "Outside Windows visual adapter scope; preserve host semantics.", + "font.line-height.title": "Outside Windows visual adapter scope; preserve host semantics.", "font.line-height.caption": "Outside Windows visual adapter scope; preserve host semantics.", "font.letter-spacing.terminal": "Outside Windows visual adapter scope; preserve host semantics.", "density.compact.control-height": "Outside Windows visual adapter scope; preserve host semantics.", diff --git a/ports/windows/port.json b/ports/windows/port.json index 607a7ecff..9cda29dce 100644 --- a/ports/windows/port.json +++ b/ports/windows/port.json @@ -4,7 +4,7 @@ "displayName": "Windows 11 native and Windhawk theme", "status": "experimental", "themeVersion": "4.0.0", - "tokenDigest": "sha256-zFvYCG+sRacSRpLqVjVsMUNxxfakWzjnJrCN7WOgQYY=", + "tokenDigest": "sha256-3KBrfmIiz4L6Qyqvi99TdTe4+5NeuA0ZWZe3Am4sRo4=", "profile": "default", "format": "windows-theme", "targetVersions": [ diff --git a/schemas/roles.mjs b/schemas/roles.mjs index a0402af2d..8ee0f1628 100644 --- a/schemas/roles.mjs +++ b/schemas/roles.mjs @@ -47,8 +47,8 @@ export const REQUIRED_FOUNDATION_ROLES = [ "radius.none", "font.family.mono", ...under("font.weight", ["regular", "bold"]), - ...under("font.size", ["ui-sm", "ui-md", "ui-lg", "reading", "code", "terminal", "h1", "h2", "h3", "caption"]), - ...under("font.line-height", ["ui-sm", "ui-md", "ui-lg", "reading", "code", "terminal", "h1", "h2", "h3", "caption"]), + ...under("font.size", ["ui-sm", "ui-md", "ui-lg", "reading", "code", "terminal", "display", "title", "h1", "h2", "h3", "caption"]), + ...under("font.line-height", ["ui-sm", "ui-md", "ui-lg", "reading", "code", "terminal", "display", "title", "h1", "h2", "h3", "caption"]), "font.letter-spacing.terminal", ...["compact", "comfortable"].flatMap((d) => under(`density.${d}`, ["control-height", "row-height", "control-padding-x", "icon", "gap"])), ...under("focus", ["ring", "ring-container", "offset", "offset-container", "offset-invalid"]), diff --git a/site/src/styles/tokens.generated.css b/site/src/styles/tokens.generated.css index b5f05093b..9f5cac134 100644 --- a/site/src/styles/tokens.generated.css +++ b/site/src/styles/tokens.generated.css @@ -303,6 +303,8 @@ --font-size-reading: 15px; --font-size-code: 13px; --font-size-terminal: 13px; + --font-size-display: 32px; + --font-size-title: 24px; --font-size-h1: 20px; --font-size-h2: 16px; --font-size-h3: 13px; @@ -313,6 +315,8 @@ --font-line-height-reading: 24px; --font-line-height-code: 19px; --font-line-height-terminal: 19px; + --font-line-height-display: 40px; + --font-line-height-title: 32px; --font-line-height-h1: 28px; --font-line-height-h2: 24px; --font-line-height-h3: 18px; diff --git a/spec/decisions.md b/spec/decisions.md index 4232e37e7..4c5d6076a 100644 --- a/spec/decisions.md +++ b/spec/decisions.md @@ -53,6 +53,7 @@ apply. | D-034 | Versioned Windows native and Windhawk adapters | accepted | 2026-09-28 | owner (explicit implementation plan) | | D-035 | An accent surface for the user's own content | accepted | 2026-10-06 | owner (Telegram acceptance: own and other people's messages too similar; chose #3d0c0a from a side-by-side comparison) | | D-036 | A translucent text-selection tint | accepted | 2026-10-06 | owner (Telegram acceptance: Android text selection barely visible; chose 50% from a side-by-side comparison) | +| D-037 | Display and title type sizes | proposed | 2026-10-14 | — | ## D-000 Responsibility split @@ -949,3 +950,20 @@ visible in the message field. Android's text-selection keys had the 12% **Status.** accepted · 2026-10-06 · owner, who saw the problem in real use and chose 50% from the side-by-side comparison after the review rejected the opaque fill. + +## D-037 Display and title type sizes + +**Decision.** Two type roles join the scale: `font.size.display` with +`font.line-height.display` (32/40) for page heroes and metric figures, and +`font.size.title` with `font.line-height.title` (24/32) for page titles above +h1. Portal pages use them instead of literal sizes; components keep h1–h3. + +**Why.** The portal set 48, 32, 24, 22 and 18px outside the token scale. The +owner chose token sizes over shrinking every heading to h1 (planning, +2026-10-14). + +**Alternatives.** The existing scale only (portal headings shrink to 20px), or +page-local literal sizes. + +**Status.** proposed · 2026-10-14. The owner asked for display type tokens in +planning; the owner sets the status. diff --git a/tests/telegram-port.test.js b/tests/telegram-port.test.js index 925feae15..13ad43031 100644 --- a/tests/telegram-port.test.js +++ b/tests/telegram-port.test.js @@ -117,7 +117,7 @@ test("emission is byte-identical across repeats and time zones", () => { }); test("every token and upstream key has one classification with direct, non-redundant inheritance", () => { - assert.equal(resolved.size, 352); + assert.equal(resolved.size, 356); assertPortMapping({ ...port, mapping }, resolved.keys()); assertCapabilities({ ...port, mapping }, capabilities); const keys = Object.values(mapping.mappings).flat(); assert.equal(new Set(keys).size, keys.length); diff --git a/tokens/foundations.tokens.json b/tokens/foundations.tokens.json index 38ce3d7da..daa15856f 100644 --- a/tokens/foundations.tokens.json +++ b/tokens/foundations.tokens.json @@ -156,6 +156,20 @@ }, "$description": "URxvt pixelsize 13." }, + "display": { + "$value": { + "value": 32, + "unit": "px" + }, + "$description": "Page heroes and metric figures on the portal (D-037)." + }, + "title": { + "$value": { + "value": 24, + "unit": "px" + }, + "$description": "Page titles above h1 on the portal (D-037)." + }, "h1": { "$value": { "value": 20, @@ -220,6 +234,18 @@ "unit": "px" } }, + "display": { + "$value": { + "value": 40, + "unit": "px" + } + }, + "title": { + "$value": { + "value": 32, + "unit": "px" + } + }, "h1": { "$value": { "value": 28, From c495cf7a93bdda3af1495e978364c3dbca0af911 Mon Sep 17 00:00:00 2001 From: j3w1 Date: Wed, 14 Oct 2026 15:37:08 -0500 Subject: [PATCH 02/65] spec: regroup the decision log by topic and condense entries The owner asked for the decisions to be regrouped and for duplication and verbosity to go. The index is now one table per topic and the entries follow that order; every id, status, date, heading and Status line is unchanged. Text that repeated another decision or spec/ became a pointer, and contrast figures from the computed report point to exports/contrast.md where the decision did not depend on the exact number. Co-Authored-By: Claude Opus 5.5 --- spec/decisions.md | 1251 +++++++++++++++++++++------------------------ 1 file changed, 571 insertions(+), 680 deletions(-) diff --git a/spec/decisions.md b/spec/decisions.md index 4c5d6076a..11c4fd5bb 100644 --- a/spec/decisions.md +++ b/spec/decisions.md @@ -10,51 +10,80 @@ A token moves from `proposed` to `approved` only by an `accepted` decision refer in its `$extensions["io.github.j3w1.theme"].approval.decision`. Agents may open `proposed` entries; only the owner changes a status. -Each entry has a Decision and a Status line (status, date, who decided, and -what later entries changed), plus Why, Consequences and Alternatives where they -apply. +Each entry has a Decision, a Why and a Status line (status, date, who decided, +and what later entries changed). Alternatives and Consequences appear only where +they add something stated nowhere else. Entries are ordered by topic. + +## Decisions by topic + +### Governance and process | # | Title | Status | Date | Decided by | | --- | --- | --- | --- | --- | | D-000 | Responsibility split: tokens, spec, ports, evidence | accepted | 2026-09-05 | owner (design package) | -| D-001 | Controlled three-hue extension for status, diagnostics and diffs | accepted | 2026-09-06 | owner | | D-002 | v0.1.0 ships the full R1 component inventory | accepted | 2026-09-06 | owner | -| D-003 | Text-role corrections with new in-hue values | accepted | 2026-09-06 | owner | | D-004 | Public repository; MIT code, CC BY 4.0 prose | accepted | 2026-09-06 | owner | | D-005 | Default profile id is `default` | proposed | 2026-09-06 | — | -| D-006 | Focus-ring rule, including invalid + focus | proposed | 2026-09-06 | — | -| D-007 | `border.control` uses `#A3676B` | proposed | 2026-09-06 | — | -| D-008 | Fold site hairlines into `border.divider`; `surface.sunken`; unified overlay border | proposed | 2026-09-06 | — | -| D-009 | Density modes `compact` and `comfortable` as tokens | proposed | 2026-09-06 | — | | D-010 | The site deploys from `main` | proposed | 2026-09-06 | — | | D-011 | Reference screenshots are cropped before publication | proposed | 2026-09-06 | — | | D-012 | Exports are committed and drift-checked | proposed | 2026-09-06 | — | | D-013 | Consumption eligibility is separate from approval | proposed | 2026-09-07 | — | -| D-014 | Automatic inline literal color previews | proposed | 2026-09-07 | — | -| D-015 | Clarify component mappings exposed by consumption acceptance | proposed | 2026-09-07 | — | -| D-016 | Pinned release comparison report and historical rendering | proposed | 2026-09-08 | — | -| D-017 | Private framework parity evidence | proposed | 2026-09-08 | — | -| D-018 | Declared port capabilities and fresh import evidence | proposed | 2026-09-08 | — | -| D-019 | One-way namespaced Figma Variables bridge | proposed | 2026-09-08 | — | -| D-020 | Bounded local validation and recovery workflow | proposed | 2026-09-08 | — | -| D-021 | Local form composition with versioned data | proposed | 2026-09-08 | — | -| D-022 | Local visual selection before agent implementation distribution | proposed | 2026-09-08 | — | +| D-028 | Merge gates and the deployment gate are different suites | accepted | 2026-09-11 | owner (explicit verification-split instruction) | +| D-031 | Select the checks a change needs; shard the deployment matrix | accepted | 2026-09-26 | owner (explicit CI renovation request, plan approval) | + +### Colour foundation + +| # | Title | Status | Date | Decided by | +| --- | --- | --- | --- | --- | +| D-001 | Controlled three-hue extension for status, diagnostics and diffs | accepted | 2026-09-06 | owner | +| D-003 | Text-role corrections with new in-hue values | accepted | 2026-09-06 | owner | +| D-007 | `border.control` uses `#A3676B` | proposed | 2026-09-06 | — | +| D-008 | Fold site hairlines into `border.divider`; `surface.sunken`; unified overlay border | proposed | 2026-09-06 | — | | D-023 | True Black / Rose canonical foundation | accepted | 2026-09-08 | owner (explicit selection of candidate I) | -| D-024 | Distinguish links from body text and headings | accepted | 2026-09-08 | owner (explicit preview correction) | -| D-025 | Theme interactive controls throughout the portal and demo | accepted | 2026-09-09 | owner (explicit native-control replacement request) | | D-026 | Primary action fill darkens off heritage ANSI 12 | accepted | 2026-09-11 | owner (explicit acceptance after visual review) | | D-027 | Recede the interactive chrome | accepted | 2026-09-11 | owner (explicit acceptance after visual review) | -| D-028 | Merge gates and the deployment gate are different suites | accepted | 2026-09-11 | owner (explicit verification-split instruction) | | D-029 | Readable terminal and code reds | accepted | 2026-09-26 | owner (explicit selection of values and release in planning) | | D-030 | Hued syntax roles for opt-in code highlighting | accepted | 2026-09-26 | owner (explicit request for a more colourful Codex, selection of the extended hues) | -| D-031 | Select the checks a change needs; shard the deployment matrix | accepted | 2026-09-26 | owner (explicit CI renovation request, plan approval) | | D-032 | Coral slot 6 and a fixed prompt background | accepted | 2026-09-26 | owner (explicit selection of coral and the PowerShell prompt look) | -| D-033 | Rose prose, semantic content headings and inherited bold | accepted | 2026-09-28 | owner (explicit implementation plan) | -| D-034 | Versioned Windows native and Windhawk adapters | accepted | 2026-09-28 | owner (explicit implementation plan) | | D-035 | An accent surface for the user's own content | accepted | 2026-10-06 | owner (Telegram acceptance: own and other people's messages too similar; chose #3d0c0a from a side-by-side comparison) | | D-036 | A translucent text-selection tint | accepted | 2026-10-06 | owner (Telegram acceptance: Android text selection barely visible; chose 50% from a side-by-side comparison) | + +### Typography and density + +| # | Title | Status | Date | Decided by | +| --- | --- | --- | --- | --- | +| D-009 | Density modes `compact` and `comfortable` as tokens | proposed | 2026-09-06 | — | +| D-033 | Rose prose, semantic content headings and inherited bold | accepted | 2026-09-28 | owner (explicit implementation plan) | | D-037 | Display and title type sizes | proposed | 2026-10-14 | — | +### Interaction and components + +| # | Title | Status | Date | Decided by | +| --- | --- | --- | --- | --- | +| D-006 | Focus-ring rule, including invalid + focus | proposed | 2026-09-06 | — | +| D-014 | Automatic inline literal color previews | proposed | 2026-09-07 | — | +| D-015 | Clarify component mappings exposed by consumption acceptance | proposed | 2026-09-07 | — | +| D-024 | Distinguish links from body text and headings | accepted | 2026-09-08 | owner (explicit preview correction) | +| D-025 | Theme interactive controls throughout the portal and demo | accepted | 2026-09-09 | owner (explicit native-control replacement request) | + +### Site, tools and distribution + +| # | Title | Status | Date | Decided by | +| --- | --- | --- | --- | --- | +| D-016 | Pinned release comparison report and historical rendering | proposed | 2026-09-08 | — | +| D-017 | Private framework parity evidence | proposed | 2026-09-08 | — | +| D-019 | One-way namespaced Figma Variables bridge | proposed | 2026-09-08 | — | +| D-020 | Bounded local validation and recovery workflow | proposed | 2026-09-08 | — | +| D-021 | Local form composition with versioned data | proposed | 2026-09-08 | — | +| D-022 | Local visual selection before agent implementation distribution | proposed | 2026-09-08 | — | + +### Ports + +| # | Title | Status | Date | Decided by | +| --- | --- | --- | --- | --- | +| D-018 | Declared port capabilities and fresh import evidence | proposed | 2026-09-08 | — | +| D-034 | Versioned Windows native and Windhawk adapters | accepted | 2026-09-28 | owner (explicit implementation plan) | + ## D-000 Responsibility split **Decision.** Token files own literal values and aliases; the specification owns @@ -68,53 +97,14 @@ origin, not an override of the adopted accessible design. **Status.** accepted · 2026-09-05 · owner (design package `ARCHITECTURE.md`). -## D-001 Controlled three-hue extension - -**Decision.** `default` adds three desaturated, warm-shifted hues: amber -`#C9973F` (warning, modified), green `#86A46F` (success, added), blue `#7E9EBB` -(info); dark tints `#1F1A0C`, `#0F1A0E`, `#0F141C`. They appear only in -`status`, `diagnostic` and `diff` (plus `code`, `terminal` and `chart` in -`extended`), never in `surface`, `text`, `border`, `interaction` or `action`. No -purple, cyan or magenta. Every status role also has a glyph, underline pattern -or border style. `default` syntax stays monochrome; `extended` stays `proposed`. - -**Why.** Lightness alone cannot separate diagnostics, diffs and status (a -200-line diff cannot be scanned by glyph); the owner's PhpStorm scheme already -uses such hues. - -**Consequences.** Contrast on canvas / surface / raised: amber 7.54 / 7.34 / -6.90, green 7.13 / 6.95 / 6.53, blue 7.08 / 6.90 / 6.48. - -**Status.** accepted · 2026-09-06 · owner. Superseded in part by D-030 (opt-in -`code.hued.*`; `code.syntax.*` stays monochrome). - ## D-002 v0.1.0 inventory **Decision.** The first public release holds every `R1` inventory component (about 47 across all nine families) plus four composed specimens (settings panel, administrative form, filterable table, i3 window frame), each *specified* and *demonstrated*. Ten core components are also *tested*: button, link, -text-field, select, checkbox, radio-group, tabs, dialog, menu, table. - -**Consequences.** `R2` items and the form-builder specimen wait for v0.2. - -**Status.** accepted · 2026-09-06 · owner. - -## D-003 Text-role corrections - -**Decision.** `text.subtle` = `#AD7175` (5.10 / 4.96 / 4.67) for metadata, -comments and line numbers. `text.disabled` = `#8A5559` (3.33 / 3.24 / 3.05; -exempt under WCAG 1.4.3, at least 3:1 by house policy). `#A3676B` stays as -`border.control`, `icon.decorative`, `status.neutral.fill` and `chart.series.4` -(non-text, at least 3:1); `#7D1310` only as `border.disabled`, `code.whitespace` -and minor grid lines, never text. - -**Why.** `#A3676B` (the site's `--quiet`) measures 4.45:1 on `#0C0909` and -`#7D1310` (`--inactive`) 1.86:1, yet the site used `#7D1310` for line numbers; -its suggested `#A8403A` measures only 3.27:1. - -**Consequences.** `heritage-ansi` keeps the original assignments, flagged -`$deprecated`. +text-field, select, checkbox, radio-group, tabs, dialog, menu, table. `R2` items +and the form-builder specimen wait for v0.2. **Status.** accepted · 2026-09-06 · owner. @@ -123,10 +113,8 @@ its suggested `#A8403A` measures only 3.27:1. **Decision.** The repository is public. MIT: code, tokens, schemas, scripts, tests, site source, generated JSON/CSS exports. CC BY 4.0: specification prose, specimens, generated Markdown exports. Screenshots under `references/`: all -rights reserved, reference only. - -**Consequences.** Fonts, vendor template material and private business data are -never committed; CI scans for them. See `LICENSE.md`. +rights reserved, reference only. Fonts, vendor template material and private +business data are never committed; CI scans for them. See `LICENSE.md`. **Status.** accepted · 2026-09-06 · owner. @@ -137,57 +125,6 @@ renaming it later is a MAJOR version change. **Status.** proposed · 2026-09-06. -## D-006 Focus-ring rule - -**Decision.** Controls and rows: `outline: 1px dashed -{color.interaction.focus.ring}` (`#E53935`), `outline-offset: -2px`. Focusable -containers (panes, windows, dialogs, cards): `outline: 2px solid -{color.interaction.focus.ring-container}` (`#FFA2A7`), `outline-offset: -3px`. -On any fill (selection, action, status) the ring takes the on-fill text colour; -on invalid + focus, where the 2px danger border is already red, it takes -`#FFA2A7` at `outline-offset: -4px`. `:focus:not(:focus-visible)` draws nothing; -forced-colors mode uses `Highlight`. Selection is a fill, focus a ring. - -**Why.** `#E53935` on `#911410` measures 2.15:1. - -**Status.** proposed · 2026-09-06. Clarified by D-015 (declared component ring -mappings on fills). Since D-027 a selected row (`#531310`, 3.38:1) takes the -ordinary ring. - -## D-007 Control boundary colour - -**Decision.** `border.control` = `#A3676B` (4.45 / 4.33 / 4.07). - -**Why.** Control boundaries need 3:1 against their surface (WCAG 1.4.11); -`#531310` (1.39) and `#9E231F` (2.56) fail. - -**Alternatives.** `#C81A1A` (3.42): too loud for every input at rest. - -**Status.** proposed · 2026-09-06. - -## D-008 Hairlines, sunken surface, overlay border - -**Decision.** The site's six near-identical hairlines (`#290D0C`, `#24100F`, -`#321110`, `#38100F`, `#190B0B`, `#2B0E0D`) fold into `border.divider` = -`#2B0E0D`. `#0A0707` becomes `surface.sunken`. Every floating layer (dialog, -drawer, menu, popover, toast) takes a 1px `border.overlay` = `#E53935`. - -**Consequences.** The dunst frame `#AE1914` survives only in `heritage-ansi`. - -**Status.** proposed · 2026-09-06. - -## D-009 Density modes - -**Decision.** Density modes are tokens, set with `data-density` on any subtree. -`compact` matches the site: control 24px, row 28px, UI type 12/16, icon 16, list -gap 2. `comfortable`: control 32px, row 36px, UI type 13/18, icon 16, list gap -4. - -**Consequences.** Both meet the 24×24 CSS-pixel target minimum; `compact` needs -4px between adjacent targets. - -**Status.** proposed · 2026-09-06. - ## D-010 Deployment source **Decision.** The site deploys from `main` through GitHub Actions after the full @@ -226,223 +163,138 @@ profiles are historical-only; deprecated or heritage roles cannot be newly mapped in an approved profile, and no substitute is implied. Observed/approved roles are usable within their documented scope; primitives are inspection-only. Release version, profile status, role status, deprecation and eligibility are -separate facts; the generator emits the policy and eligibility metadata. +separate facts; the generator emits the policy and eligibility metadata. This +governs consumption only: no pending value is approved, and D-005 through D-012 +are unchanged. **Why.** Issue #4 found conflicting instructions to use and to prohibit pending -roles in the approved default profile. - -**Consequences.** Governs consumption only: no pending value is approved, and -D-005 through D-012 are unchanged. - -**Alternatives.** Block pending roles until individually approved. +roles in the approved default profile; blocking them until each is approved was +the alternative. **Status.** proposed · 2026-09-07 (formal log status remains owner-controlled). Owner direction, 2026-09-07, in Phase 1 planning: "Use and report", and "Block new use" for deprecated roles; implementation authorized. -## D-014 Automatic inline literal color previews +## D-028 Merge gates and the deployment gate are different suites -**Decision.** Every visible CSS hex literal on the spec page gets one generated -preview; the literal stays exact and is data, never inferred from a token or -screenshot. The preview is 16px with its theme-derived 1px boundary, circular at -rest; on CSS `:hover` it scales to 17.4px with radius zero (fast duration token -and ease-out on transform and border-radius; none under reduced motion). Alpha -shows over a checkerboard of theme tokens. Only this preview may use rounded -geometry, patterned gradient backgrounds and border-radius animation. Text, -copying, keyboard order and no-JS access stay intact. Syntax specimens `#f00`, -`#f008`, `#ff0000`, `#ff000080`, `#000000`, `#ffffff` (literal data, not roles) -also test copy fidelity and transparent, dark and light previews in the browser -suite. +**Decision.** The full browser and packed-consumer matrix gates deployment, not +merging; it runs on `main` before `deploy` and on demand through the workflow +dispatch. A subset never writes evidence: it uses the plain list reporter, +because the evidence reporter would mark unselected tests not run and publish a +matrix that only looked complete. Packed consumers move with the browser suite, +which republishes their evidence against the deployed package; +`scripts/ui-verification-report.mjs` requires the complete protocol on all three +engines. No mandatory local gate: `npm run test:all` is recommended, never +verified; the practice is recorded in `AGENTS.md`. As first recorded, pull +requests merged on `validate`, `build` and a `smoke` job (desktop project; page, +portal, button and text-field specs; plain list reporter), which is never a +coverage claim. -**Why.** Issue #1 asks for circular previews and a transparency checkerboard, -against the square and no-gradient rules. +**Why.** Accepting D-026 and D-027 cost 29.5 minutes of CI before merge, 84% of +it the browser matrix: pure latency on a public repository. A browser failure +stops publication, not a correct merge; a local receipt proves only that +something wrote it. Sharding before merge (about six minutes, partial evidence +files) and consumers on the merge path were rejected. -**Consequences.** Literal-data presentation only: no new palette, semantic role -or geometry rule. +**Status.** accepted · 2026-09-11 · owner: merges gate on a few minutes of +checks, the full matrix gates deployment, a local full run stays recommended. +Superseded in part by D-031 (path-selected pull-request checks, a sharded +deployment matrix with one evidence report, `release-gate` as the only required +check); the rules above still hold. -**Status.** proposed · 2026-09-07 (formal log status remains owner-controlled). -Owner direction, 2026-09-07: the narrow exception explicitly approved, -implementation authorized. +## D-031 Select the checks a change needs; shard the deployment matrix -### Follow the pointer hovering effect +**Decision.** CI is `select` → checks → `release-gate`. -Part of this exception only; the tooltip and focus contracts are unchanged. -Mouse and pen pointers open a non-interactive popup with the exact value; touch -and unknown pointers do not. CSS `:hover` alone drives the morph; neither uses -the `hover` or `any-hover` media features, which can report no hover despite -mouse input. The popup follows the pointer inside the circle at an 8px gap, -flips when necessary and stays within an 8px viewport gutter, bounded by the -viewport. It closes at once when the pointer leaves the circle, on an outside -press, Escape or loss of window focus, and after page or nested-container -scrolling unless the same circle is still under the last pointer position. It -cannot capture input or hold itself open and adds no keyboard stop; token tables -and the keyboard-accessible token inspector keep the persistent information and -links. Tracking has no animation or easing, even under reduced motion. Circles -and literal text stay visible without JavaScript. +- `select` reads the changed paths and `scripts/ci/proofs.json`; a path gets + cheaper only when a rule claims it. Unclaimed paths and control files + (workflows, the selector and registry, `package.json`, the lockfile, the + Playwright configs) run every check: a broad rule is a floor, never a verdict. + On a pull request the base commit's control list also applies, so a change + cannot make itself cheaper; review protects the selector. A file a browser + spec imports runs that spec and counts as a site change. +- Unit tests and the build run in parallel. A pull request runs only the + selected checks; browser subsets write no evidence (D-028). +- A push to `main` that changes the site runs the whole matrix: browser projects + split into jobs (desktop in four parts; projects read from the Playwright + config) whose blob reports merge once into the evidence reporter, with packed + consumers in parallel. The merge needs every shard passed and reported; a + check refuses evidence missing any configured test in any project. Then the + verification report and deployment; no site change, no deployment. Changed + paths count from the last commit that reached Pages, so a failed deploy is + counted again. +- `release-gate`, the only required check, recomputes the plan from Git with the + same code, refuses a mismatch, and checks each job ran exactly as planned and + passed. +- `fullyParallel`, two workers per CI job, zero retries. The page axe scan is + two tests (colour contrast; every other rule) from a tag-based run, together + exactly the tagged rules. Only `playwright test` with nothing narrowing or + listing it, or the merge of every shard, writes evidence; the counting check + runs no reporter and proves the evidence file unchanged. -## D-015 Clarify component mappings exposed by consumption acceptance +**Why.** `main` ran every check whatever changed: a terminal-kit-only change, +which the site never reads, took 63 minutes to deploy, and the browser suite ran +on one worker for 24.7 minutes. Shards now write blob reports merged into one +report, so D-028's objection to sharding no longer applies. Rejected: a +self-hosted runner (fork pull requests could run code on it), reusing +pull-request evidence on `main` (the build stamps the commit), Playwright's +internal shard weights (not public). -**Decision.** Keep current component appearance and all token values. Ordinary -confirmation uses the primary tone; destructive tone is for destructive actions, -whatever the confirmation's semantic role. A pressed primary button keeps -`color.action.primary.border`, secondary and tertiary use `color.border.active`, -destructive keeps its declared border; the generic metadata is corrected to -match. Controls keep their documented ring mappings (primary and -checked/selected fills: `color.interaction.focus.ring-container` where declared; -destructive fills: their on-fill text role). The global wording points to them, -keeping ring geometry, forced-colors behavior and every contrast floor. +**Status.** accepted · 2026-09-26 · owner, who found thirty-minute runs on +`main` unacceptable and asked for classified checks modelled on theselfish.one. +Supersedes D-028 in part. -**Why.** Phase 2's independently reviewed composed acceptance preserved these -three contradictions; Phase 3 controls must not present an arbitrary -interpretation as canonical. +## D-001 Controlled three-hue extension -**Consequences.** No profile or pending-token approval; historical acceptance -reports stay historical evidence. +**Decision.** `default` adds three desaturated, warm-shifted hues: amber +`#C9973F` (warning, modified), green `#86A46F` (success, added), blue `#7E9EBB` +(info); dark tints `#1F1A0C`, `#0F1A0E`, `#0F141C`. They appear only in +`status`, `diagnostic` and `diff` (plus `code`, `terminal` and `chart` in +`extended`), never in `surface`, `text`, `border`, `interaction` or `action`. No +purple, cyan or magenta. Every status role also has a glyph, underline pattern +or border style. `default` syntax stays monochrome; `extended` stays `proposed`. -**Alternatives.** Enforce the generic prose everywhere, or mark affected -workbench configurations unresolved. +**Why.** Lightness alone cannot separate diagnostics, diffs and status (a +200-line diff cannot be scanned by glyph); the owner's PhpStorm scheme already +uses such hues. Measured contrast is in `exports/contrast.md`. -**Status.** proposed · 2026-09-07. The owner directed application on 2026-09-07; -formal status remains owner-managed. +**Status.** accepted · 2026-09-06 · owner. Superseded in part by D-030 (opt-in +`code.hued.*`; `code.syntax.*` stays monochrome). -## D-016 Pinned release comparison report and historical rendering +## D-003 Text-role corrections -**Decision.** A report (schema version 1) records both immutable revisions, -profile and input digests, separate semantic change categories, explicit -dependency evidence and unsupported historical inputs. Reports and historical -specimen renderings are build artifacts in `dist/releases/`; canonical exports -keep their contract. History is read from Git, never executed as a build or -imported as a module. The shared specimen renderer draws each side's maintained -markup and styles (documented renderer version, matched conditions): a -reconstructed reference, not evidence that an old site's JavaScript or an -external port ran. Browser captures are run evidence with environment and -artifact hashes; missing evidence stays not run. A rename needs an explicit -mapping naming both revisions; equal values do not establish one. +**Decision.** `text.subtle` = `#AD7175` for metadata, comments and line numbers. +`text.disabled` = `#8A5559` (exempt under WCAG 1.4.3, at least 3:1 by house +policy). `#A3676B` stays as `border.control`, `icon.decorative`, +`status.neutral.fill` and `chart.series.4` (non-text, at least 3:1); `#7D1310` +only as `border.disabled`, `code.whitespace` and minor grid lines, never text. +`heritage-ansi` keeps the original assignments, flagged `$deprecated`. -**Why.** Run metadata must stay out of deterministic exports, and missing -historical fields must not be read by today's rules. +**Why.** `#A3676B` (the site's `--quiet`) measures 4.45:1 on `#0C0909` and +`#7D1310` (`--inactive`) 1.86:1, yet the site used `#7D1310` for line numbers; +its suggested `#A8403A` measures only 3.27:1. -**Consequences.** No design values, eligibility rules or verification statuses -change. +**Status.** accepted · 2026-09-06 · owner. -**Alternatives.** A raw file diff (no semantic categories) or running historical -applications (a wider trust boundary). +## D-007 Control boundary colour -**Status.** proposed · 2026-09-08. Issue #2 authorizes derived release -diagnostics; formal status and all theme approvals remain owner-managed. +**Decision.** `border.control` = `#A3676B`. -## D-017 Private framework parity evidence +**Why.** Control boundaries need 3:1 against their surface (WCAG 1.4.11); +`#531310` (1.39) and `#9E231F` (2.56) fail, and `#C81A1A` (3.42) is too loud for +every input at rest. -**Decision.** An independently authored private harness takes an -operator-supplied licensed target and an explicit license review, copies only -declared template inputs into a new private fixture directory, uses synthetic -examples and records exact theme, template, framework, dependency and fixture -identities. The target and its application behavior stay outside its write scope; browser captures, copied -vendor inputs and detailed results stay private; missing prerequisites give -not-run output. +**Status.** proposed · 2026-09-06. -**Consequences.** A successful diagnostic run is not a verified port or a claim -of complete visual parity. +## D-008 Hairlines, sunken surface, overlay border -**Alternatives.** A public vendor copy (breaks the license boundary) or a -generic mock presented as template evidence. +**Decision.** The site's six near-identical hairlines (`#290D0C`, `#24100F`, +`#321110`, `#38100F`, `#190B0B`, `#2B0E0D`) fold into `border.divider` = +`#2B0E0D`. `#0A0707` becomes `surface.sunken`. Every floating layer (dialog, +drawer, menu, popover, toast) takes a 1px `border.overlay` = `#E53935`. The +dunst frame `#AE1914` survives only in `heritage-ansi`. -**Status.** proposed · 2026-09-08. Issue #3 authorizes the harness; approval -statuses and license boundaries are unchanged. - -## D-018 Declared port capabilities and fresh import evidence - -**Decision.** Optional `capabilities.json` refines each mapped/unmapped role -into mapped, inherited, unsupported, out-of-scope or not-implemented, with a -surface and reason; legacy unmapped reasons stay unclassified, never guessed. -Import verification is separate from mapping state and declared status: verified -output needs a recorded real-import protocol bound to current target metadata, -canonical tokens, mappings, capabilities and artifact bytes. Relevant changes -make evidence stale; failed or missing checks cannot pass. One generated -catalogue feeds summaries, drill-downs and task kits; private parity records -never enter it automatically. - -**Alternatives.** A hand-maintained support matrix, or a parse treated as an -import. - -**Status.** proposed · 2026-09-08. Issue #14 authorizes a derived mapping -explorer; it creates no port, changes no host capability and approves no -profile. - -## D-019 One-way namespaced Figma Variables bridge - -**Decision.** An explicit pinned revision supplies colors and scalar -spacing/radius values, one way. Aliases keep their dependency structure; -dependency-only primitives are hidden from property pickers; unsupported types -and non-approved profiles are reported. One collection and one mode avoid -assuming paid mode capabilities. Dry-run is read-only, apply explicit; import -receipts identify owned IDs and their last observed values; conflicts and manual -edits stop an update or rollback. The bridge never stores ownership in -unsupported plugin data, overwrites unrelated variables or writes back to the -repository. - -**Alternatives.** Manual duplicate maintenance, a paid-only REST workflow, or -flattening aliases/composites. - -**Status.** proposed · 2026-09-08. Issue #15 authorizes this bounded adapter; -approval and eligibility follow the canonical source. - -## D-020 Bounded local validation and recovery workflow - -**Decision.** One executable pattern: editing, invalid, review, busy, success. -Validation runs on explicit submission, keeps values and shows linked errors; -typing does not rewrite live announcements. Review can return to a field; -confirm enters busy, a separate local simulation-completion event enters -success, and no request is made. The workstation example's reserved name and -hostname are local fixture conflicts, not business policy. The contract pins -constituent component content digests and reports automated evidence apart from -manual screen-reader acceptance. - -**Alternatives.** A color-only invalid snapshot, validation on every keystroke, -or a submit click treated as a successful save. - -**Status.** proposed · 2026-09-08. Issue #16 authorizes one pattern from -existing admin-form, field, alert and button rules, without new palette roles. - -## D-021 Local form composition with versioned data - -**Decision.** Five canonical field kinds can be added, edited, removed and -reordered with buttons. Definitions, preview values and validation state are -separate. JSON imports have closed fields, bounded size/counts and unique stable -IDs; a failed import changes nothing. Content identity pins the supplying theme -and component contracts; downloads hold definitions, never entered values. -Rendering and validation reuse D-020. - -**Consequences.** A draft reference component, not a backend platform or native -port. - -**Alternatives.** Arbitrary HTML/schema execution, a conditional workflow -engine, or a second field implementation. - -**Status.** proposed · 2026-09-08. Issue #19 authorizes the deferred -form-builder demonstration. - -## D-022 Local visual selection before agent implementation distribution - -**Decision.** Before canonicalization a local harness compares exactly three -explicit token overlays with Current, using shared specimen rendering and an -original Vue composition. Overlays, reports and review builds stay ignored, -never public profiles or delivery artifacts. The existing alias resolver and -unrounded contrast engine judge candidates without changing canonical values, -historical ANSI slots or waivers. Numbers and browser evidence approve nothing: -the owner selects a concrete candidate before foundation freeze, mass -productization or deployment. See `docs/phase6-visual-review.md`. - -**Why.** Agents need installable or copyable components and compositions with -complete dependencies and pinned contracts, shared by the future package, -documentation portal and Vue application. - -**Alternatives.** Productizing the old palette first, unapproved preview -profiles, or appearance-only snippets. - -**Status.** proposed · 2026-09-08. Issue #37 and the owner's implementation -instruction authorize three local candidates; design approval remains -owner-managed. The selection is D-023. +**Status.** proposed · 2026-09-06. ## D-023 True Black / Rose canonical foundation @@ -453,94 +305,34 @@ panels use `#100c0c`. The two new values become `color.primitive.ink.14` and Everything else stays exactly as reviewed (rose/white foreground, red actions, focus, borders, selections, status and chart roles); raised/overlay stay `#241010`, alternate chrome `#1c0a09`. The historical profile keeps its previous -surfaces. +surfaces. This approves these surfaces only, not other pending decisions, new +colors or accessibility waivers; the A–I candidate reviews stay historical local +evidence, not public profiles. It ships in 1.0.0 under the major-version rule; +existing pins stay immutable. **Why.** The owner explicitly selected the reviewed candidate I: "use the True Black / Rose theme and make it permanent for j3w1/theme". -**Consequences.** Approves these surfaces only, not other pending decisions, new -colors or accessibility waivers. The rejected A/B/C, revised D/E/F and final -G/H/I reviews are historical local evidence, not public profiles. Foundation for -the Phase 6 package, copy distributions, static portal and Vue showcase; ships -in 1.0.0 under the major-version rule, existing pins immutable. - **Status.** accepted · 2026-09-08 · owner, who also authorized the remaining Phase 6 implementation. Superseded in part only: D-024 (`text.link`), D-026 (`action.primary.bg`), D-027 (`surface.raised`, `interaction.selection.bg`, `text.placeholder`). -## D-024 Distinguish links from body text and headings - -**Decision.** `color.text.link` maps to the existing strong red `#f73f35`, -keeping the persistent red underline and near-white hover text on the strong -dark-red hover fill. Visited links keep color and underline; current-page and -selected navigation keep their on-fill roles; body and heading colors are -unchanged. - -**Why.** In the implementation preview the owner asked for links more -distinguishable from normal text, using different colors. - -**Consequences.** No new primitive, status hue, contrast exception or focus -rule; the historical profile keeps the old link; ships in the same unreleased -1.0.0. - -**Alternatives.** Bright rose (the heading color) or blue/purple (an unrelated -hue). - -**Status.** accepted · 2026-09-08 · owner, correcting D-023 for links only. -D-027 later moves link hover to `interaction.hover.bg`. - -## D-025 Theme interactive controls throughout the portal and demo - -**Decision.** The maintained select renders its single-choice popup and -multiple-choice list in theme-owned DOM with the existing selection, surface, -text, border and focus roles; the native select remains the form-value and -constraint source and the no-JavaScript fallback. It follows the select-only -combobox and multiple listbox keyboard patterns, keeps labels, disabled -options/fieldsets, native input/change events, defaults and form reset, and -documents its tested scope. The same enhancement serves existing application -controls, the portal, the Vue demo, consumption docs and copy closures; input, -button, checkbox, radio, range and file chrome is themed too. Date inputs get a -theme-owned text editor and calendar, time inputs text entry and theme-owned -step buttons; native inputs keep constraints and values. Browser-owned system dialogs and -no-JavaScript fallbacks stay native, without platform hacks; native ports keep -their mappings. The command field fills its dialog width below its label. - -**Why.** Seeing native blue selections in the work board and agent-kit picker, -the owner explicitly instructed: "replace mostly all native components like -`` we must use all j3w1 themed", and asked for a properly proportioned +command-search field. Advisory option CSS keeps the blue selection; one-off +dropdowns duplicate behavior. + +**Status.** accepted · 2026-09-09 · owner. + +## D-016 Pinned release comparison report and historical rendering + +**Decision.** A report (schema version 1) records both immutable revisions, +profile and input digests, separate semantic change categories, explicit +dependency evidence and unsupported historical inputs. Reports and historical +specimen renderings are build artifacts in `dist/releases/`; canonical exports +keep their contract. History is read from Git, never executed as a build or +imported as a module. The shared specimen renderer draws each side's maintained +markup and styles (documented renderer version, matched conditions): a +reconstructed reference, not evidence that an old site's JavaScript or an +external port ran. Browser captures are run evidence with environment and +artifact hashes; missing evidence stays not run. A rename needs an explicit +mapping naming both revisions; equal values do not establish one. No design +values, eligibility rules or verification statuses change. + +**Why.** Run metadata must stay out of deterministic exports, and missing +historical fields must not be read by today's rules. A raw file diff has no +semantic categories; running historical applications widens the trust boundary. + +**Status.** proposed · 2026-09-08. Issue #2 authorizes derived release +diagnostics; formal status and all theme approvals remain owner-managed. + +## D-017 Private framework parity evidence + +**Decision.** An independently authored private harness takes an +operator-supplied licensed target and an explicit license review, copies only +declared template inputs into a new private fixture directory, uses synthetic +examples and records exact theme, template, framework, dependency and fixture +identities. The target and its application behavior stay outside its write +scope; browser captures, copied vendor inputs and detailed results stay private; +missing prerequisites give not-run output. A successful diagnostic run is not a +verified port or a claim of complete visual parity. + +**Why.** A public vendor copy breaks the license boundary, and a generic mock +would be presented as template evidence. + +**Status.** proposed · 2026-09-08. Issue #3 authorizes the harness; approval +statuses and license boundaries are unchanged. + +## D-019 One-way namespaced Figma Variables bridge + +**Decision.** An explicit pinned revision supplies colors and scalar +spacing/radius values, one way. Aliases keep their dependency structure; +dependency-only primitives are hidden from property pickers; unsupported types +and non-approved profiles are reported. One collection and one mode avoid +assuming paid mode capabilities. Dry-run is read-only, apply explicit; import +receipts identify owned IDs and their last observed values; conflicts and manual +edits stop an update or rollback. The bridge never stores ownership in +unsupported plugin data, overwrites unrelated variables or writes back to the +repository. + +**Why.** Manual duplicate maintenance, a paid-only REST workflow, and flattening +aliases or composites were the alternatives. + +**Status.** proposed · 2026-09-08. Issue #15 authorizes this bounded adapter; +approval and eligibility follow the canonical source. + +## D-020 Bounded local validation and recovery workflow + +**Decision.** One executable pattern: editing, invalid, review, busy, success. +Validation runs on explicit submission, keeps values and shows linked errors; +typing does not rewrite live announcements. Review can return to a field; +confirm enters busy, a separate local simulation-completion event enters +success, and no request is made. The workstation example's reserved name and +hostname are local fixture conflicts, not business policy. The contract pins +constituent component content digests and reports automated evidence apart from +manual screen-reader acceptance. + +**Why.** A color-only invalid snapshot, validation on every keystroke, or a +submit click treated as a successful save were the alternatives. + +**Status.** proposed · 2026-09-08. Issue #16 authorizes one pattern from +existing admin-form, field, alert and button rules, without new palette roles. + +## D-021 Local form composition with versioned data + +**Decision.** Five canonical field kinds can be added, edited, removed and +reordered with buttons. Definitions, preview values and validation state are +separate. JSON imports have closed fields, bounded size/counts and unique stable +IDs; a failed import changes nothing. Content identity pins the supplying theme +and component contracts; downloads hold definitions, never entered values. +Rendering and validation reuse D-020. A draft reference component, not a backend +platform or native port. + +**Why.** Arbitrary HTML/schema execution, a conditional workflow engine, or a +second field implementation were the alternatives. + +**Status.** proposed · 2026-09-08. Issue #19 authorizes the deferred +form-builder demonstration. + +## D-022 Local visual selection before agent implementation distribution + +**Decision.** Before canonicalization a local harness compares exactly three +explicit token overlays with Current, using shared specimen rendering and an +original Vue composition. Overlays, reports and review builds stay ignored, +never public profiles or delivery artifacts. The existing alias resolver and +unrounded contrast engine judge candidates without changing canonical values, +historical ANSI slots or waivers. Numbers and browser evidence approve nothing: +the owner selects a concrete candidate before foundation freeze, mass +productization or deployment. See `docs/phase6-visual-review.md`. + +**Why.** Agents need installable or copyable components and compositions with +complete dependencies and pinned contracts, shared by the future package, +documentation portal and Vue application. Productizing the old palette first, +unapproved preview profiles, or appearance-only snippets were the alternatives. + +**Status.** proposed · 2026-09-08. Issue #37 and the owner's implementation +instruction authorize three local candidates; design approval remains +owner-managed. The selection is D-023. + +## D-018 Declared port capabilities and fresh import evidence + +**Decision.** Optional `capabilities.json` refines each mapped/unmapped role +into mapped, inherited, unsupported, out-of-scope or not-implemented, with a +surface and reason; legacy unmapped reasons stay unclassified, never guessed. +Import verification is separate from mapping state and declared status: verified +output needs a recorded real-import protocol bound to current target metadata, +canonical tokens, mappings, capabilities and artifact bytes. Relevant changes +make evidence stale; failed or missing checks cannot pass. One generated +catalogue feeds summaries, drill-downs and task kits; private parity records +never enter it automatically. + +**Why.** A hand-maintained support matrix, or a parse treated as an import, were +the alternatives. + +**Status.** proposed · 2026-09-08. Issue #14 authorizes a derived mapping +explorer; it creates no port, changes no host capability and approves no +profile. + +## D-034 Versioned Windows native and Windhawk adapters + +**Decision.** A Windows port uses native settings where sufficient and pinned +Windhawk 2.0 alpha 6 stylers solely as rendering adapters for canonical semantic +tokens: a bounded exception to the unsupported-injection prohibition in +portability. No binary patching, shell replacement, paid tool or third-party +theme is permitted. Unknown shell versions/structures fail closed. Full lifecycle +support includes pinned install/update, verification, original-state restore, +transaction rollback and removal of owned theme assets. User shortcuts, window +management, existing layouts and desktop icons are preserved; cursors and black +wallpaper are included. Native limitations are disclosed, not silently patched. + +**Why.** Native settings cannot represent the full black/rose shell identity, +and the owner explicitly accepted the pinned prerelease to use its upstream CLI. +Private storage edits and UI automation are less reproducible; binary theme +patching was rejected. + +**Status.** accepted · 2026-09-28 · owner, explicit implementation plan approval. From 6c26ea756e2bc62c9a61f7282b09623e923de856 Mon Sep 17 00:00:00 2001 From: j3w1 Date: Wed, 14 Oct 2026 15:37:08 -0500 Subject: [PATCH 03/65] docs: condense the README, consumer protocol and docs The README re-told the identity, the decisions and every portal tool's own page; it is now an entry point with a quick start and links. The Phase 6 documents become short records of what was decided and delivered, the visual review and design mode keep their operational steps, and the consumer protocol keeps every rule, format and marker with shorter prose. Co-Authored-By: Claude Opus 5.5 --- README.md | 426 ++++++------------------------ agents/consume.md | 62 ++--- docs/dependabot-bumps.md | 14 +- docs/design-mode.md | 201 +++++--------- docs/phase6-delivery.md | 266 ++++++------------- docs/phase6-visual-review.md | 141 ++++------ docs/rose-typography-migration.md | 13 +- docs/true-black-rose-migration.md | 47 ++-- docs/ui-architecture.md | 182 ++++++------- 9 files changed, 420 insertions(+), 932 deletions(-) diff --git a/README.md b/README.md index 5f07c84be..2ba21fb9b 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,16 @@ **True-black canvas. Near-black surfaces. Rose text. Red focus. Square components.** -This repository is the versioned specification of the j3w1 look. People and AI -agents use it to build the same theme in websites, apps, editors, terminals and -native theme formats. It publishes: +`j3w1/theme` **defines** the j3w1 look: exact tokens, semantic roles, +interaction states, accessibility limits, component specifications and +portability rules. People and AI agents use it to build the same theme in +websites, apps, editors, terminals and native theme formats. It publishes: - a design-system portal: **https://j3w1.github.io/theme/**; - the complete static specification: **https://j3w1.github.io/theme/reference/**; - an independently written [Vue demo](https://j3w1.github.io/theme/demo/); -- machine-readable exports for agents. +- machine-readable exports for agents, the official `@j3w1/ui` web package and + ready-made application themes. Specification version **4.0.0** (release; default: approved, heritage-ansi: heritage, extended: proposed). @@ -20,12 +22,15 @@ Use the pinned approved default profile. Pending roles in that profile use-and-r Approval and consumption eligibility are separate; see the policy above and `spec/decisions.md` D-013. -## Application theme downloads +## Quick start -Theme files for apps, ready to import. Each file link is pinned to this -version's release tag, and the site serves the same file from its **download** -link. Each port's README under `ports/` gives scope, limits and rollback. -Declared status and import evidence are explained under +Pin a release tag or a full commit, never `main`, and read every file at that +same revision. Releases are tags. + +**Theme an application.** Download a file from the table below. Each link is +pinned to this version's release tag, and the site serves the same file from +its **download** link. Each port's README under `ports/` gives scope, limits +and rollback; declared status and import evidence are under [Application ports](#application-ports). @@ -92,57 +97,29 @@ Declared status and import evidence are explained under | Windows 11 native and Windhawk theme | [j3w1-terminal-chrome.json](https://raw.githubusercontent.com/j3w1/theme/v4.0.0/ports/windows/dist/j3w1-terminal-chrome.json) | [download](https://j3w1.github.io/theme/ports/windows/j3w1-terminal-chrome.json) | Use the single pinned ports/windows/install.ps1 lifecycle; chrome changes share its saved rollback. | experimental; import evidence not verified | -To change how the theme looks, use [design mode](docs/design-mode.md) -(`npm run design`). It shows the real site, built at an anchored commit, next -to the live dev server, so you judge a change against what it replaces. It is -a working tool, not a gate. - -History in brief: - -- The owner chose **True Black / Rose** after the - [local visual-foundation review](docs/phase6-visual-review.md). D-023 records - the seven canonical surface changes; D-024 records the strong-red links the - owner asked for next. See [the migration notes](docs/true-black-rose-migration.md) - and [the delivery record](docs/phase6-delivery.md) for verification status. -- D-025 records the owner's request for themed controls across the portal and - the Vue demo. Since version 1.1.0, single and multiple choices use j3w1 - surfaces and selection colors, keep their native form data and fallback, and - come with a supported enhancement for existing app markup. The shared command - palette puts a full-width search field under its label. - -Forms and design tools: - -- The [validation and recovery composition](https://j3w1.github.io/theme/patterns/validation-recovery/) - and the [draft form builder](https://j3w1.github.io/theme/builder/) show local - form behavior with canonical fields. Definitions are bounded, content-pinned - JSON. Entered values never go into downloads or storage. -- The optional [Figma Variables bridge](https://j3w1.github.io/theme/figma/) - is a reviewed one-way import with dry-run, explicit apply and rollback - receipts. Generate its sample with - `node scripts/figma-bridge.mjs --ref FULL_COMMIT_OR_RELEASE_TAG`. -- Limits and evidence: [form patterns](spec/form-patterns.md), - [builder contract](spec/components/form-builder.md) and - [bridge instructions](spec/figma-bridge.md). - -## What this is, and what it is not - -`j3w1/theme` **defines** the theme: exact tokens, semantic roles, interaction -states, accessibility limits, component specifications and portability rules. -The official `@j3w1/ui` package implements all 67 inventory entries with native -HTML, typed Custom Elements, per-component imports and complete copy -distributions. The [consumption instructions](docs/ui-consumption.md) cover the -package, copy and native mapping routes. `j3w1/j3w1.github.io` stays a separate -downstream app. No purchased template source or assets are included. - -## Where it came from - -The palette began on a Manjaro i3 workstation, preserved in -[`j3w1/1w3j`](https://github.com/j3w1/1w3j), and was named as web roles by -[`j3w1/j3w1.github.io`](https://github.com/j3w1/j3w1.github.io). The full -story is in `spec/identity.md`. Both sources are pinned by revision in -`references/sources.json`. Historical ports (a gedit scheme, an IntelliJ -scheme, tmux, browser extensions) are listed in `references/catalogue.json` -as evidence, not downloads. +**Build a web app.** Use the official `@j3w1/ui` package: all 67 inventory +entries as native HTML, typed Custom Elements, per-component imports and +complete copy distributions. [`docs/ui-consumption.md`](docs/ui-consumption.md) +covers the package, copy and native mapping routes. For the official +implementations, read `packages/ui/dist/index.json`, then the +`contracts/.json` and `examples/.json` you need; the installed +`j3w1-ui kit` command prepares bounded framework, package, copy or mapping +kits. npm publication is still an owner action; until then the portal offers an +installable tarball with integrity metadata. No purchased template source or +assets are included, and `j3w1/j3w1.github.io` stays a separate downstream app. + +**Use the tokens.** `exports/tokens.css` exposes every role as a CSS custom +property and `exports/tokens.resolved.json` holds the resolved values of every +profile. Consume roles, never primitives. + +**Point an agent at it.** Follow [`agents/consume.md`](agents/consume.md): + +1. Read `theme.json`. +2. Read `exports/theme.compact.md`. +3. Read the `exports/components/.json` files you need. +4. Record `theme.lock.json` and report deviations. + +`exports/llms.txt` is a discovery index for tools that look for one. ## The identity in seven values @@ -171,242 +148,39 @@ as evidence, not downloads. Three bounded hues (amber, green, blue) exist for status, diagnostics and diffs (decision D-001), and for opt-in syntax themes through `code.hued.*` (D-030). They are forbidden in surfaces, chrome, buttons, links and selections. The -reference syntax highlighting stays monochrome in the default profile. - -## Profiles - -| Profile | Status | Purpose | -| --- | --- | --- | -| `default` | approved | The everyday composition every implementation targets. | -| `heritage-ansi` | heritage | The sixteen historical terminal slots and assignments, exact, including the ones that fail the contrast floor. | -| `extended` | proposed | Semantic hues for syntax, a full sixteen-slot terminal palette that reaches 4.5:1, coloured chart series. | - -## Using the theme - -**People:** browse the portal's foundations, components, patterns and tools. -The full static reference keeps every state matrix, stress fixture, -non-example, contrast report and coverage ledger. Old homepage hashes redirect -to its sections. - -**Agents:** use the deterministic artifacts. Pin a tag or commit, then follow -[`agents/consume.md`](agents/consume.md): - -1. Read `theme.json`. -2. Read `exports/theme.compact.md`. -3. Read the `exports/components/.json` files you need. -4. Record `theme.lock.json` and report deviations. - -`exports/llms.txt` is a discovery index for tools that look for one. For the -official implementations, read `packages/ui/dist/index.json`, then the -`contracts/.json` and `examples/.json` you need. The installed -`j3w1-ui kit` command prepares bounded framework, package, copy or mapping -kits. npm publication is still an owner action; until then the portal offers -an installable tarball with integrity metadata. - -**Contributors:** read [`AGENTS.md`](AGENTS.md). `CLAUDE.md` imports it. - -### Tools on the portal - -- **Shared specimen markup.** State matrices use - `scripts/lib/specimen-markup.mjs` for native state attributes and hidden-cell - focus handling. Its parsed ID-reference rewriting is shared with recipe - instances through `scripts/lib/markup.mjs`. Recipes reject unresolved local - references; matrices keep their documented fixture links. Keep these - transformations shared when you add specimen tools. -- **[Component workbench](https://j3w1.github.io/theme/workbench/).** Live - controls for button, text field, checkbox, tabs and dialog, plus table and - sidebar navigation previews. Pick a maintained variant and starting state, - then check real iframe widths, density, language and RTL. Comparison frames - can use different environments. The anatomy inspector keeps declared roles, - resolved values and browser measurements apart; it reports mismatches - without correcting the specimen. Forced visual states are labelled and do - not replace keyboard interaction or form validation. -- **Contrast comparisons** use the existing unrounded contrast engine. Pick - the declared pair, or an explicit text/UI context and an opaque underlay. - Eligibility and waivers stay separate from the number. -- **Motion controls** replay only maintained transitions. Static endpoints and - reduced motion take precedence. These diagnostic tools do not certify - accessibility. -- **Share links.** Copy a configuration or preview link to reproduce its - starting state. Links name the actual build and source digest; a revision - that is not available is reported with a pinned source link. Entered - specimen text is left out unless you include it in the shown share payload. - Nothing is saved to browser storage. -- **Issue drafts.** Component and token pages link to a reviewed public issue - draft. A draft includes the actual build, profile and public anchor, and - never includes entered specimen text. If a draft is longer than the - 8,000-character portable URL budget, copy it and paste it into GitHub's - composer. Opening the composer never submits an issue. - -Canonical specimens, normative content and direct reporting links all work -without JavaScript. - -`schemas/playground.mjs` defines the closed configuration choices, and -`site/workbench.json` binds controls to maintained specimen parts. The build -checks each binding in every variant. Preview routes and state matrices share -the parsed renderer: add new bindings and coverage instead of writing another -specimen implementation. - -### Choosing a semantic role - -Use the [token usage explorer](https://j3w1.github.io/theme/tokens/), or follow -a token-name link from the specification. - -- Filter by role group, component, part, state, variant, profile, status and - surface. All selected usage filters must match the same declaration; an - unknown relationship matches nothing. -- Exact path, CSS-variable and hex searches still work, and equal values keep - their separate roles. -- Filter URLs can be shared. The explorer stores no preferences and sends no - searches to a service. - -Each token has its own page with every profile value, eligibility, pending -decisions, alias dependencies, provenance, component and port references, and -contrast declarations. Profile tables and details work without JavaScript. -Copy controls copy the role path or the CSS variable. In hosted builds, source -links use the build's full commit and the parsed source line; local builds show -checkout-relative locations and claim no published revision. - -Agents can also fetch `exports/token-usage.json` at the same pinned revision as -the other contracts. This schema-version-1 reverse index comes from source -mappings, not from colour similarity. - -- Variant references are included only when a mapped part's prefix equals a - declared variant id. -- Missing port consumers stay unknown. -- The index is digest-covered and uses `schemas/json/token-usage.schema.json`. - After you edit source mappings, regenerate it with `npm run generate`. -- The usage and port-capability indexes keep complete JSON schemas and data, - with one usage or capability record per line to reduce transfer size and - diff noise. Consume them as JSON; source locations still refer to maintained - source files, not the index's presentation. Other exports retain their format. - -### Standalone component recipes - -The [recipe source viewer](https://j3w1.github.io/theme/recipes/) packages the -default button, text-field and dialog straight from the maintained demo and -CSS sources. Each component section links to its source and standalone HTML. - -1. Download `example.html` to run it without Astro, or include `tokens.css`, - `foundation.css` and `component.css`, in that order, with `markup.html`. -2. Pick a unique instance prefix in the viewer for each copy. Labels and ARIA - references are rewritten together. `two-instances.html` shows two copies - side by side. - -Styles stay inside `.j3w1-recipe`. The dialog is an open visual reference: -modal lifecycle, close actions, focus trapping and focus return are the host's -job. No behavior module or font binary is bundled. - -`site/recipes.json` declares the inputs; `npm run generate` writes and -drift-checks `exports/recipes/`. Source and output digests name the exact -bytes. Use these paths at one pinned commit; the hosted viewer shows the -revision it came from. Recipe markup keeps the specimen's CC BY 4.0 licence and -attribution; CSS keeps its MIT notices. Each recipe's manifest, README and -LICENSE list its dependencies, pending decisions and limits. - -Browser checks use port 4173 by default. If another checkout is testing, set -`PW_PORT` to a free port before `npm run test:browser` and -`npm run test:verification`; both use the same server configuration. For -example, PowerShell: `$env:PW_PORT = '4174'`; POSIX shells: -`PW_PORT=4174 npm run test:browser`. Finish the build before you start tests. - -### Task-scoped implementation kits - -With the [task-kit builder](https://j3w1.github.io/theme/kit/): - -1. Select components. -2. Describe the authorized task and give an integration ID, version and kind. -3. Download a ZIP, or copy the complete Markdown package. - -Inputs stay in the browser; no model service, backend or storage is used. -Without JavaScript, use the CLI from a checkout at a committed revision: - -```sh -npm run task:kit -- --components text-field,checkbox,button,dialog --task "Implement a settings form" --integration-id settings --integration-version 1 --out ../settings-kit -``` - -- The CLI uses the current full commit by default. `--ref` takes a full commit - or a release tag, never a branch. Every input is read from that Git revision. -- The browser embeds its source revision and the expected file digests, and - rejects mixed deployment bytes. A pinned build needs committed generated - inputs and `GITHUB_SHA` set to that full commit. An ordinary unpinned local - build shows the workflow but turns packaging off. -- Standard mode includes the available standalone recipes; `--mode minimal` - leaves out only the optional recipes. Both keep the selected JSON and - specification contracts, all shared global rules and foundations, the - required token/alias closure, the consumer contract, the lock schema and a - bounded prompt. Briefs of unselected components are removed from the derived - compact file. -- `KIT.json` keeps upstream hashes apart from the derived compact/subset - hashes. The lock's `resolvedAt` is the source commit's timestamp, so the same - inputs give the same output. An empty starting deviation list does not - certify a downstream implementation. - -Output must be a new local directory under an existing parent that is not -redirected. Existing destinations, symbolic links, Windows reparse points and -unsafe file names fail closed. The writer never erases a destination -recursively; a failed write leaves partial output for inspection. Keep the -parent directory stable while writing: this is not an OS sandbox against -concurrent changes. The legacy `consumption:kit` command uses the same writer -and refuses existing directories. Its default path and its `--strict` -omission of `tokens.resolved.json` are unchanged; pick a new `--out` for each -rerun. - -The original [single-component protocol](tests/consumption/PROTOCOL.md) and -the [composed task-kit protocol](tests/consumption/TASK-KITS.md) are separate -acceptance exercises. A generated kit does not run an agent or prove that the -consumer's implementation conforms. - -## Pinned release comparison - -The [release comparison](https://j3w1.github.io/theme/releases/) compares two -published revisions from `site/releases.json`. The catalogue pins every tag to -its full commit and tells a release apart from a published commit checkpoint. -Builds need those Git objects locally (`fetch-depth: 0` in CI). Building and -viewing the comparison never fetch a moving branch. - -```sh -npm run release:compare -- --from v0.1.0 --to b601998b3711dcd62949d497ed828af2089f9544 --out ../release-comparison -``` - -- Both arguments take only release tags or full commits. `--profile` picks one - common historical profile. -- The output is a new directory under an existing parent that is not - redirected, written by the same guarded writer as task kits. It holds - JSON/Markdown migration reports and reconstructed before/after specimens. -- It never builds historical code, upgrades consumers or certifies a port. -- An optional `--migrations` JSON file follows the generated - `release-migration` schema and names both commits plus explicit role renames. - Equal values alone never imply a rename. - -How the report reads history: - -- Each historical export is checked against its own digest ledger. Missing or - unsupported historical contracts stay unsupported. -- Missing usage indexes are disclosed; direct component/port mappings, where - present, still give bounded dependency evidence. Missing historical - eligibility fields stay unknown. -- Reports separate value, alias, status/decision, component/state, - portability and appearance-source changes. "Known affected" means a declared - dependency or contract changed, not an observed regression in an app. - Unregistered consumers stay unknown, and an empty port catalogue stays empty. - -The visual reference reuses the parsed specimen renderer with historical -markup/CSS for the workbench's seven components and their variants and states. -Both sides use 640 × 480 frames, comfortable density, LTR and static motion -endpoints. No historical JavaScript and no remote font or asset requests are -allowed. Fixture changes are disclosed; fonts depend on the shared browser and -machine. The frames are reconstructed references, not historical runtime -evidence. Browser tests capture matching specimens and attach their real -environment, while the report itself says truthfully that visual execution is -not run. Other engines, physical devices, manual accessibility and unlisted -component captures stay unverified. Report and specimen outputs live in -`dist/releases/`, outside the committed canonical exports, and are covered by -the ordinary built-artifact evidence. - -To add a published revision, add a reviewed catalogue pin and pass the usual -generate/check/build/dist/browser/evidence gates. Adding a comparison changes -no palette and approves nothing. D-016 records the report schema boundary. +reference syntax highlighting stays monochrome in the default profile. Where +the palette came from, and the three profiles (`default`, `heritage-ansi`, +`extended`), are in [`spec/identity.md`](spec/identity.md). + +## Read further + +- **Specification:** [identity](spec/identity.md), + [foundations](spec/foundations.md), [accessibility](spec/accessibility.md), + [portability](spec/portability.md), the [decision log](spec/decisions.md), + [form patterns](spec/form-patterns.md), the + [Figma bridge](spec/figma-bridge.md) and one file per component under + `spec/components/`. +- **Portal tools:** the + [component workbench](https://j3w1.github.io/theme/workbench/), the + [token usage explorer](https://j3w1.github.io/theme/tokens/), + [standalone recipes](https://j3w1.github.io/theme/recipes/), the + [task-kit builder](https://j3w1.github.io/theme/kit/), the + [release comparison](https://j3w1.github.io/theme/releases/), the + [port capability explorer](https://j3w1.github.io/theme/ports/), the + [validation and recovery pattern](https://j3w1.github.io/theme/patterns/validation-recovery/), + the [form builder](https://j3w1.github.io/theme/builder/) and the + [Figma Variables bridge](https://j3w1.github.io/theme/figma/). Each page + states its own limits; canonical specimens, normative content and reporting + links work without JavaScript. +- **Implementation:** [`docs/ui-consumption.md`](docs/ui-consumption.md) and + [`docs/ui-architecture.md`](docs/ui-architecture.md). +- **Ports:** [`ports/README.md`](ports/README.md) says which guide you need. +- **History:** [`CHANGELOG.md`](CHANGELOG.md), the decision log and the + migration notes for [True Black / Rose](docs/true-black-rose-migration.md) + and [rose typography](docs/rose-typography-migration.md). +- **Contributing:** [`AGENTS.md`](AGENTS.md); `CLAUDE.md` imports it. To change + how the theme looks, use [design mode](docs/design-mode.md) + (`npm run design`), a working tool, not a gate. ## Repository map @@ -419,6 +193,7 @@ no palette and approves nothing. D-016 records the report schema boundary. | `schemas/` | zod schema factories shared by the scripts and the site; `schemas/json/` is generated | | `scripts/` | Validators and generators (`npm run validate`, `npm run generate`, `npm run check`); `scripts/lib/` is hashed into the package identities, `scripts/tooling/` holds local-tooling helpers that are not | | `exports/` | Generated, committed: resolved tokens, semantic usage index, CSS custom properties, contrast report, coverage ledger, per-component JSON and briefs, compact and full Markdown, `llms.txt`, digests | +| `packages/ui/` | The `@j3w1/ui` package; `packages/ui/dist/` is generated | | `site/` | The Astro source of the design-system portal, complete reference and token tools, built to `dist/` and deployed to `/theme/` by CI | | `references/` | Pinned provenance, catalogued historical implementations, excerpts, and any reference screenshots with their provenance | | `ports/` | One folder per app, each with a manifest, mapping, generated theme file and evidence; Orca, Claude Code and Codex also hold their installer and one guide (`ports/README.md` says which one you need) | @@ -427,40 +202,12 @@ no palette and approves nothing. D-016 records the report schema boundary. ## Application ports -The [capability explorer](https://j3w1.github.io/theme/ports/) builds its -summary, role-to-native-key rows, artifact links and evidence state from the -same committed port inputs. `exports/port-capabilities.json` is digest-covered -and included in task kits. It keeps mapped, inherited, unsupported, -out-of-scope and not-implemented roles apart from import verification. Legacy -unmapped roles keep their reason, with no guessed classification. An empty -catalogue publishes no app support. - -`ports/README.md` describes the optional capability metadata and the exact -evidence fingerprint. A stale artifact token digest hides its claimed resolved -values. Changing targets, mappings, capabilities or artifact bytes makes -import evidence stale. Static tables and JSON work without JavaScript. - -### Private framework parity - -With no licensed target supplied, `npm run parity:private` prints a useful -**not run** prerequisite record. Public validation, builds and browser tests -never need a private target. To run the bounded seven-component experiment: - -1. Follow [the private harness protocol](templates/private-parity/README.md). -2. Pass an operator-owned JSON file from outside this repository: - - ```sh - npm run parity:private -- --config /private/location/parity.json - ``` - -The protocol checks the installed versions against the target package and -lock. It copies only the selected script/style inputs into a new private -directory. It captures native references and real framework controls with the -recorded environment, input hashes, property differences and screenshots. It -never starts the target app's backend or runs its package scripts. Finished -diagnostics may report differences; they do not certify an app port. Private -sources, configuration and results stay out of Git and the public site, also -when verification fails. +The [capability explorer](https://j3w1.github.io/theme/ports/) and +`exports/port-capabilities.json` keep mapped, inherited, unsupported, +out-of-scope and not-implemented roles apart from import verification (D-018). +Changing targets, mappings, capabilities or artifact bytes makes import +evidence stale. `ports/README.md` describes the capability metadata and the +evidence fingerprint. | Port | Format | Declared status | Import evidence | Theme | Tested on | Supported / inherited / unsupported | @@ -481,16 +228,9 @@ when verification fails. *Specified* means the component's specification validates. *Demonstrated* means its demo renders every declared variant on the site. *Test implemented* means a browser test exists for it. Real outcomes are published separately in -the linked verification report, with exact scope, configuration and digests. -The ledger is generated from the sources. - -The shared browser evidence fixture records the real browser/OS, the final -viewport, and the page root's declared profile and density when the test ends. -A missing declaration is recorded as `not-declared`; a page context that is -not available is reported explicitly. These fields do not infer a mode for -every nested specimen. Protocols that exercise several local modes describe -them in their verification annotation instead of labelling every run as -comfortable. +the linked verification report, with exact scope, configuration and digests +(`spec/accessibility.md`, Verification evidence). The ledger is generated from +the sources. | Component | Family | Priority | Specified | Demonstrated | Test implemented | @@ -581,6 +321,6 @@ note. Releases are tags; consumers pin them. ## Licence MIT for code, tokens, schemas, scripts and generated JSON/CSS; CC BY 4.0 for -specification prose and specimens; reference screenshots all rights reserved. -See [`LICENSE.md`](LICENSE.md). No fonts are distributed; the recommended -family is named in `theme.json`. +specification prose and specimens; reference screenshots all rights reserved +(D-004). See [`LICENSE.md`](LICENSE.md). No fonts are distributed; the +recommended family is named in `theme.json`. diff --git a/agents/consume.md b/agents/consume.md index 8126df171..2d317fdf9 100644 --- a/agents/consume.md +++ b/agents/consume.md @@ -1,12 +1,10 @@ # Consuming j3w1/theme (for agents and integrators) -This document is for people and agents who apply the theme to another project. -The contributor workflow for this repository is in `AGENTS.md`. - -You are consuming **design data and optional official implementations**. The -consumer project's own instructions (its `AGENTS.md`, `CLAUDE.md`, security, -architecture and operational rules) always win over anything in this -repository. +For people and agents who apply the theme to another project; contributors +to this repository read `AGENTS.md`. You are consuming **design data and +optional official implementations**. The consumer project's own instructions +(its `AGENTS.md`, `CLAUDE.md`, security, architecture and operational rules) +always win over anything in this repository. ## Official web implementations @@ -22,20 +20,19 @@ bundles are also supported. ``` Choose `copy` to own the full source, or `mapping` for a host the package does -not fit. Native hosts need mapping mode. Kits include the canonical contracts, -their dependency closure and the shared accessibility/identity rules. They do +not fit; native hosts need mapping mode. Kits include the canonical contracts, +their dependency closure and the shared accessibility/identity rules; they do not declare your app verified. `docs/ui-consumption.md` has the exact -installation, framework binding and runtime checks. npm publication is an -owner release action; until then, use the release tarball and its published -integrity metadata. For canonical mappings, keep the lock and deviation -workflow below. +installation, framework binding and runtime checks. Until npm publication (an +owner release action), use the release tarball and its published integrity +metadata. Canonical mappings keep the lock and deviation workflow below. ## 0. Pin a revision first -`` is a release tag (`v0.1.0`) or a full 40-character commit SHA. Never -`main`, never a branch name, never "latest". Resolve a tag to its commit before -you read anything, and use the same `` in every URL below. Mixing -revisions breaks the contract. +`` is a release tag (`v0.1.0`) or a full 40-character commit SHA, never +`main`, a branch name or "latest". Resolve a tag to its commit before you read +anything, and use the same `` in every URL below; mixing revisions breaks +the contract. ``` GET https://api.github.com/repos/j3w1/theme/git/ref/tags/ → object.sha @@ -65,10 +62,10 @@ Use the pinned approved default profile. Pending roles in that profile use-and-r The policy block above is generated. Each resolved token lists its pending -decision IDs in `eligibility.decisionIds`, including alias dependencies. -Report those IDs together with any real deviations. Using an authorized -pending value is a disclosure, not an invented substitution. A blocked action -implies no replacement. A profile preview does not authorize delivered work. +decision IDs, alias dependencies included, in `eligibility.decisionIds`; report +them with any real deviations. Using an authorized pending value is a +disclosure, not an invented substitution. A blocked action implies no +replacement, and a profile preview does not authorize delivered work. ## 4. Read only what you need, in this order @@ -81,18 +78,17 @@ https://raw.githubusercontent.com/j3w1/theme//exports/digests.json Optional: `exports/theme.full.md` for the whole specification; `exports/tokens.css` for a ready-made custom-property sheet. The website -`https://j3w1.github.io/theme/` is for visual confirmation only. It is not a -source of values, and screenshots never override tokens. +`https://j3w1.github.io/theme/` is for visual confirmation only, never a source +of values; screenshots never override tokens. ## 5. Inspect the target before changing anything 1. Name the integration kind: `css-vars`, `vuetify`, `tailwind`, `jetbrains-icls`, `gtk-css`, `terminal-16` or `other`. -2. List which specified surfaces the target can express natively, and which - it cannot (for example, a framework with no read-only field style, or a - sixteen-colour terminal that cannot show hover). -3. Anything the target cannot express becomes a documented deviation in step - 7, never an invented approximation. +2. List which specified surfaces the target can and cannot express natively + (for example, no read-only field style, or a sixteen-colour terminal that + cannot show hover). Each one it cannot express becomes a documented + deviation in step 7, never an invented approximation. ## 6. Implement the mapping @@ -104,8 +100,8 @@ source of values, and screenshots never override tokens. - Keep host accessibility at least as strong as before: never remove a focus indicator, never lower a contrast ratio the host already met, never set `outline: none` without drawing the specified ring. -- Radii are 0, borders 1px, the family is monospace. A host that forbids one - of these gets a deviation, not a redesign. +- Radii are 0, borders 1px, the family is monospace; a host that forbids one + gets a deviation, not a redesign. - Selection is a fill; focus is a ring. On fills, the ring takes the colour the component JSON declares for that state (D-015). Status roles keep their glyphs. @@ -118,10 +114,10 @@ source of values, and screenshots never override tokens. ## What you may not do -- Invent, blend, lighten, darken or "harmonise" colours. Use resolved values +- Invent, blend, lighten, darken or "harmonise" colours; use resolved values only. - Use a blocked value, deliver a proposed profile, or leave out the required - pending-decision disclosures. Historical-only values are not approved UI + pending-decision disclosures; historical-only values are not approved UI roles. - Take values from the site's HTML, from screenshots or from memory. - Touch unrelated components, layouts, copy, dependencies or build @@ -158,7 +154,7 @@ lock: ## theme.lock.json -A small file, committed next to the integration code and validated by +Committed next to the integration code and validated by `schemas/json/theme.lock.schema.json`. It is not a package manager: no graph, no install, no auto-update. To update the theme, change `ref`, `revision`, `version` and `exports`, rerun the consumer's own checks, and write the diff --git a/docs/dependabot-bumps.md b/docs/dependabot-bumps.md index fb2e45f9c..dd8b0b838 100644 --- a/docs/dependabot-bumps.md +++ b/docs/dependabot-bumps.md @@ -1,11 +1,11 @@ # Reviewing Dependabot npm bumps -For a Dependabot PR that changes `package.json`, a workspace `package.json`, or `package-lock.json`, the read-only `dependabot-refresh` job checks out the **PR head SHA**, installs locked dependencies, runs `npm run generate` and `npm run check`, and offers a patch if committed generated files changed. It does not commit to the branch. The normal selected checks and `release-gate` still decide whether the bump is compatible. A patch is a proposed change, not execution evidence or a passing check. +For a Dependabot PR that changes `package.json`, a workspace `package.json`, or `package-lock.json`, the read-only `dependabot-refresh` job checks out the **PR head SHA**, installs locked dependencies, runs `npm run generate` and `npm run check`, and offers a patch if committed generated files changed. It never commits to the branch. A patch is a proposed change, not execution evidence or a passing check: the selected checks and `release-gate` still decide whether the bump is compatible. -1. Read the job summary. **No generated drift** means there is no artifact to apply; the required checks must still pass. A failed install, generation, generated-file check, or unexpected modification needs investigation and produces no patch. An API or behavior failure in selected checks needs a compatibility fix; never apply a patch to hide that failure. -2. When the summary names `dependabot-generated-patch`, download that artifact from the PR's workflow run (or run `gh run download -n dependabot-generated-patch -D .cache/dependabot-download`). Extract it if downloading from the browser; the file is `dependabot-refresh.patch`. The artifact expires after seven days. -3. Check out the PR branch (`gh pr checkout `). Require `git status --short` to be empty and compare `git rev-parse HEAD` with the **exact PR head SHA in the job summary**. If they differ, use a newer run's patch; do not apply an old patch to a moved head. -4. From the repository root, run `git apply --check .cache/dependabot-download/dependabot-refresh.patch` and then `git apply .cache/dependabot-download/dependabot-refresh.patch` (use the actual path where you downloaded it). Review `git diff --check`, `git diff --stat` and `git diff` including additions and removals. Never apply blindly or commit unrelated files. -5. With Node 24, run `npm ci`, `npm run check` (the applied patch should already be current), `npm run generate`, then `npm run validate`, `npm run check` and the checks selected by `node scripts/ci/select.mjs --event pull_request --base origin/main --head HEAD`. For a dependency bump this normally means the full unit, build, browser and consumer gates; `npm run test:all` is the local full-suite command after browser dependencies are installed. Commit only the reviewed generated changes and any separately justified compatibility fix to the PR branch if you have permission to push. Otherwise arrange a reviewable follow-up change; do not give PR code a write token. +1. Read the job summary. **No generated drift** means there is nothing to apply; the required checks must still pass. A failed install, generation or generated-file check, or an unexpected modification, needs investigation and produces no patch. An API or behavior failure in the selected checks needs a compatibility fix; never apply a patch to hide it. +2. When the summary names `dependabot-generated-patch`, download that artifact from the PR's workflow run (or `gh run download -n dependabot-generated-patch -D .cache/dependabot-download`) and extract `dependabot-refresh.patch`. The artifact expires after seven days. +3. Check out the PR branch (`gh pr checkout `). `git status --short` must be empty and `git rev-parse HEAD` must equal the **exact PR head SHA in the job summary**; if they differ, use a newer run's patch. +4. From the repository root, run `git apply --check .cache/dependabot-download/dependabot-refresh.patch`, then `git apply .cache/dependabot-download/dependabot-refresh.patch` (use your actual download path). Review `git diff --check`, `git diff --stat` and the whole `git diff`. Never apply blindly or commit unrelated files. +5. With Node 24, run `npm ci`, `npm run check` (the applied patch should already be current), `npm run generate`, then `npm run validate`, `npm run check` and the checks selected by `node scripts/ci/select.mjs --event pull_request --base origin/main --head HEAD`; for a dependency bump that is normally the full unit, build, browser and consumer gates (`npm run test:all` locally, after browser dependencies are installed). Commit only the reviewed generated changes and any separately justified compatibility fix to the PR branch if you may push; otherwise arrange a reviewable follow-up change. Never give PR code a write token. -GitHub Actions-only bumps do not generate a patch; ordinary CI still evaluates them. If regeneration or the compatibility suite fails, do not treat an artifact, a successful informational job, or a subset of checks as a green `release-gate`. \ No newline at end of file +GitHub Actions-only bumps generate no patch; ordinary CI still evaluates them. An artifact, a successful informational job or a subset of checks is never a green `release-gate`. diff --git a/docs/design-mode.md b/docs/design-mode.md index 582cb387b..8a45b233d 100644 --- a/docs/design-mode.md +++ b/docs/design-mode.md @@ -2,16 +2,12 @@ Design mode is the local loop for changing how the theme looks. One screen shows the site twice: **before** is a frozen production build of where the -session started, **after** is the live dev server. You judge a change against -what it replaces before you commit it. - -It is a working tool, not a gate. Nothing it produces is evidence, and it -approves nothing. +session started, **after** is the live dev server, so you judge a change +against what it replaces before you commit it. It is a working tool, not a +gate: nothing it produces is evidence, and it approves nothing. ## Run it -The repository is an npm workspace. Run design mode through npm: - ``` npm ci npm run design:doctor # optional: checks the prerequisites below and stops @@ -20,52 +16,35 @@ npm run design Then open `http://localhost:4400/` (the default). Stop with Ctrl+C. -To use another port, start with `DESIGN_PORT=4500 npm run design`. The frozen -side, the live side and the dev server take the next three ports; -`DESIGN_DEV_PORT` moves only the last. - -The three servers listen first, so the screen answers at once. The first entry -then builds the baseline (`npm run build`) and starts the dev server. Its first -content sync can take about a minute on a cold cache. The status line under the -controls names the running step. Until the dev server is ready, the after frame -shows the frozen build; both frames reload when it is. - -Later entries reuse the baseline whenever `.cache/design-mode/baseline/` and its -`baseline.json` exist, even if `HEAD` has moved. This is deliberate: a session -commits a checkpoint after each accepted change, and rebuilding "before" each -time would destroy what you compare against. The before label names the anchor -commit, plus "working tree" if the tree was dirty then. - -`npm run design:baseline`, or the **Re-anchor before** button, re-anchors the -frozen side to the working tree. Use it to chain comparisons across a long -session. - -### Prerequisites - -`npm run design:doctor` checks each item and names the fix for a failure. -`npm run design` runs the same check before it starts. - -- Node 24 (`engines` in `package.json`). -- `npm ci` has run, so Astro and Vite resolve. -- `packages/ui/dist` holds the package the screen and the live side load - (`index.json`, `styles/controls.css`, `enhance/choice.js`). It is committed; - `npm run generate` rebuilds it. +- `DESIGN_PORT=4500 npm run design` uses another port. The frozen side, the + live side and the dev server take the next three ports; `DESIGN_DEV_PORT` + moves only the last. +- The first entry builds the baseline (`npm run build`) and starts the dev + server; its first content sync can take about a minute on a cold cache. The + status line names the running step, and the after frame shows the frozen + build until the dev server is ready. +- Later entries reuse the baseline whenever `.cache/design-mode/baseline/` and + its `baseline.json` exist, even if `HEAD` has moved, so a checkpoint commit + does not destroy what you compare against. The before label names the anchor + commit, plus "working tree" if the tree was dirty then. +- `npm run design:baseline`, or the **Re-anchor before** button, re-anchors the + frozen side to the working tree, to chain comparisons across a session. + +**Prerequisites** (`npm run design:doctor` checks each and names the fix; +`npm run design` runs the same check first): + +- Node 24 (`engines` in `package.json`), and `npm ci` has run. +- `packages/ui/dist` holds the package (`index.json`, `styles/controls.css`, + `enhance/choice.js`); it is committed and `npm run generate` rebuilds it. - `site/src/styles/tokens.generated.css` exists (`npm run generate`). -- git answers inside the checkout; "before" records the commit it came from. -- The four ports are free. -- npm answers, and `.cache/` is writable. - -### Package manager - -`package.json` declares `"packageManager": "npm@…"`, so pnpm and Yarn refuse to -install or run scripts here. That keeps a second lockfile away from -`package-lock.json`. The baseline build always runs npm, because the workspace -layout and `scripts/pack-ui.mjs` (`npm pack --workspace … --json`) are -npm-specific. Started through `npm run`, it runs that same npm directly (no -`PATH` lookup, no shell). Started another way, such as -`node scripts/design-mode.mjs`, it runs `npm` from `PATH` and says so. +- git answers inside the checkout; the four ports are free; npm answers and + `.cache/` is writable. -Astro's telemetry is disabled for design mode and the processes it starts. +Run it through npm. `package.json` declares `"packageManager": "npm@…"`, so +pnpm and Yarn refuse to run here, and the baseline build always uses npm. +Started another way, such as `node scripts/design-mode.mjs`, it runs `npm` from +`PATH` and says so. Astro's telemetry is disabled for design mode and the +processes it starts. ## What the two sides are @@ -74,70 +53,44 @@ Astro's telemetry is disabled for design mode and the processes it starts. | before | `.cache/design-mode/baseline/`, a frozen `npm run build` | Production-faithful: real base path, inline hex previews, `ui/` and `demo/` present | | after | the dev server, proxied | Vite HMR, so an edit repaints immediately | -The sides use separate origins, so every link, asset and runtime fetch resolves -exactly as on Pages. Cross-origin frames cannot read each other, so each side -has a small injected agent that relays its scroll ratio and route. - -Every Astro integration here hooks `astro:build:done`. Under the dev server, the -`ui/`, `demo/`, `exports/` and `downloads/` trees are missing and the inline hex -previews (D-014) are not applied. Both would look like changes the session did -not make, so the live proxy fixes them: - -- It applies the build's decoration, with the same - `decorateHexHtml`/`tokenColorIndex` pair and route list. -- It falls back to the frozen build for anything the dev server cannot answer. - A fallback response carries `x-design-mode: baseline-fallback`. - -`astro dev` alone cannot start this project. Its CLI gives the forked dev server -30 seconds to report ready, and syncing 67 component collections takes longer on -a cold cache. Design mode uses Astro's JS API, which has no such deadline. - -## Controls - -The screen uses the theme it changes. `enhance/choice` from `packages/ui` -renders the route, width and scale selects as the j3w1 combobox. The comparison -server serves `packages/ui/dist` under `/ui/`, as -`site/integrations/copy-exports.mjs` does under `dist/ui`. - -The route picker must not be an ``. Chrome gives one -`appearance: menulist-button`: it drops the author background and colour, draws -the popup as OS chrome placed by the browser, and filters the options so the -rest of the list disappears after a selection. A `` popup cannot be -styled at all. For the same reason, the text field beside it has no `list` -attribute. +The sides use separate origins, so links, assets and fetches resolve as on +Pages; a small injected agent relays each side's scroll ratio and route. Under +the dev server the `ui/`, `demo/`, `exports/` and `downloads/` trees and the +inline hex previews (D-014) are missing, so the live proxy applies the build's +decoration (`decorateHexHtml`/`tokenColorIndex` and the same route list) and +falls back to the frozen build for anything the dev server cannot answer, with +the header `x-design-mode: baseline-fallback`. Design mode starts the dev +server through Astro's JS API because `astro dev` gives it only 30 seconds to +report ready. + +The route, width and scale selects are the j3w1 combobox from `packages/ui`, +served under `/ui/`. The route picker must not be an ``, and the +text field beside it has no `list` attribute: Chrome draws that popup as +unstyled OS chrome. ## Comparison modes -- **Side by side** — both viewports at their true CSS widths, scroll synced. -- **Swipe** — one clipped over the other at an adjustable split; drag the seam - or use the slider. -- **Blend** — after faded over before; ghosting shows a shift of a few pixels - that a static pair hides. -- **Blink** — the two alternate in place, so any shift reads as a jump. +- **Side by side**: both viewports at their true CSS widths, scroll synced. +- **Swipe**: one clipped over the other; drag the seam or use the slider. +- **Blend**: after faded over before; ghosting shows a shift of a few pixels. +- **Blink**: the two alternate in place, so any shift reads as a jump. Widths match the browser suite's gates: 1440×1000 desktop, 640×500 for 200% -zoom, 360×740 narrow. They are real CSS widths, not scaled screenshots. The -scale control only shrinks the result to fit; it does not emulate device pixel -ratio. +zoom, 360×740 narrow. They are real CSS widths; the scale control only shrinks +the result to fit and does not emulate device pixel ratio. ## Token changes -`site/src/styles/tokens.generated.css` is generated; never hand-edit it. To -change a colour, edit `tokens/`. Design mode watches `tokens/` and runs the real -tokens generator, which rewrites that stylesheet, `exports/tokens.resolved.json` -and `exports/tokens.css`. A shortcut that wrote only the stylesheet would repaint -a swatch while the page still printed the old hex, because printed hexes come -from the exports. - -A DTCG colour carries both `components` and `hex`, and the resolver rejects it if -they disagree. Write both, with `components` as each channel ÷ 255. +`site/src/styles/tokens.generated.css` is generated; to change a colour, edit +`tokens/`. Design mode watches `tokens/` and runs the real tokens generator, +which rewrites that stylesheet, `exports/tokens.resolved.json` and +`exports/tokens.css` (printed hexes come from the exports). A DTCG colour +carries both `components` and `hex`, and the resolver rejects it if they +disagree: write both, with `components` as each channel ÷ 255. -The watcher skips validation and the other fourteen generators. At the end of -the session: - -1. Run `npm run generate`. It brings the contrast report, the usage index, - `schemas/json/`, the README blocks and the digests back into line. -2. Run `npm run check` to prove it. +The watcher skips validation and the other generators. At the end of the +session run `npm run generate` (contrast report, usage index, `schemas/json/`, +README blocks, digests), then `npm run check`. ## The session ledger @@ -149,33 +102,25 @@ node scripts/design-mode.mjs --note "warm the panel surface" --class token --fil ``` `--class` is one of `page-local`, `token`, `spec-rule`, `component` or -`copy/identity`. The class matters: the site is confirmation-only -(`theme.json`), so anything that is not page layout belongs in `tokens/` or -`spec/` and must be reconciled there before the work can merge. - -`npm run design:exit` prints the session by class and counts the changes that -still need reconciling. +`copy/identity`. The site is confirmation-only (`theme.json`), so anything that +is not page layout belongs in `tokens/` or `spec/` and must be reconciled there +before the work can merge. `npm run design:exit` prints the session by class +and counts the changes that still need reconciling. ## Where the code is -- `scripts/design-mode.mjs` wires the servers, live proxy, HMR upgrade, watchers - and regeneration. -- `scripts/tooling/design-mode.mjs` holds the units that need no server, tested - by `tests/design-mode.test.js`: port derivation, route mapping, the frame - agent, baseline metadata, route discovery, the ledger and its report, the - package-manager choice and the prerequisite check. -- Neither file is under `scripts/lib`, so changing design mode does not change - the package identities `scripts/build-ui.mjs` hashes. -- The live side's route list comes from `scripts/lib/hex-routes.mjs`, the list - the build's hex-swatch integration reads. +`scripts/design-mode.mjs` wires the servers, proxy, watchers and regeneration. +`scripts/tooling/design-mode.mjs` holds the server-free units tested by +`tests/design-mode.test.js`. Neither is under `scripts/lib`, so changing design +mode does not change the package identities `scripts/build-ui.mjs` hashes. The +live route list comes from `scripts/lib/hex-routes.mjs`, the list the build's +hex-swatch integration reads. ## Limits -- The ledger, baseline and log live in ignored `.cache/`. None of it is evidence - or published. -- Design mode does not run the check loop or validate, and it decides nothing. - A new colour, a change to an approved value, a new or renamed role, or any - change to the focus, selection or contrast rules still needs a decision entry - in `spec/decisions.md`. Only the owner changes a status. +- The ledger, baseline and log live in ignored `.cache/`; none of it is + evidence or published. +- Design mode does not run the check loop or validate. Changes that need a + decision entry (AGENTS.md) still need one in `spec/decisions.md`. - Automated rendering in two frames is not a manual keyboard or screen-reader result. diff --git a/docs/phase6-delivery.md b/docs/phase6-delivery.md index 9b0e530cd..597c24889 100644 --- a/docs/phase6-delivery.md +++ b/docs/phase6-delivery.md @@ -1,194 +1,80 @@ -# Phase 6 delivery contract and continuation - -This records the owner-directed Phase 6 scope and what was built. The owner -selected True Black / Rose (candidate I); D-023 records it. All 67 inventory -entries have canonical contracts, official implementations, typed APIs and -complete copy distributions. The static portal and the full Vue showcase are -built. Acceptance comes from the separate execution records for the exact -artifact and protocol; this document does not accept a release by itself. - -During the implementation preview, the owner asked for red graphs, distinct -table column-header and body colors, and a stronger title, subtitle and -navigation-group hierarchy. These use existing approved roles: red -`color.chart.series-2`, bright rose column headers, regular rose body values, -near-white page titles, bright section and group headings, muted supporting -text. They add no colors and keep the True Black / Rose foundation. The later -request for a separate link color is D-024: strong red links, persistent -underlines, near-white hover text. - -The selected foundation passed source validation, generation and drift checks, -105 source tests, the static build, nine distribution tests, and the configured -browser suite (204 passed, 124 intentionally skipped). Verification-report -generation kept all 1,866 specimen files; its source and browser checks passed -(six browser passes, three intentional skips). This is automated foundation -evidence, not package acceptance or a manual accessibility pass. - -## Primary success criterion - -An agent building another application can discover, select, install or copy, -use and verify j3w1 elements, components and compositions from pinned -artifacts. It never scrapes page DOM, reads values from screenshots, rebuilds -missing behavior or guesses which CSS and dependencies make a snippet work. - -Design meaning stays in `tokens/` and `spec/`; the package implements it, and -copy bundles, the portal and the Vue application consume that implementation. -None of them is a second specification (see `docs/ui-architecture.md`). - -## Gate order - -1. **6A:** Current plus exactly three local candidates: matched interfaces, - state board, numeric report, real browser evidence and owner selection. -2. **6B:** Make the selected foundation canonical in tokens and spec, record the - owner's decision, keep history, regenerate and validate exports. -3. **6C:** Productize all 67 baseline inventory entries, including R2/L; generate - the package, standalone distributions and machine implementation mapping. -4. **6D:** Build the multi-page portal and the complete Vue showcase with - consumption docs, live implementation examples and agent-kit entry points. -5. **6E:** Verify external consumers, publish evidence, prepare tarballs and - migration docs, then deploy the tested artifacts. npm publication stays an - owner release action. - -The owner must select between 6A and 6B. Show a requested hybrid as one combined -candidate first. Never infer approval from a recommendation or green checks. -Identity changes outside the selected foundation go back to the owner. - -## Official package and copy distributions - -Create the publishable `@j3w1/ui` npm workspace package: modular ESM, typed -public APIs, separate class and registration exports, per-component imports, safe -repeated registration, semantic token CSS and documented styling extension -points. Native semantics, real forms, properties, attributes, slots and events -are the default vocabulary. Choose light or Shadow DOM per component from its -semantics, static content, composition and real interoperability. - -Every inventory entry must map to an official consumable implementation. Deferred -entries get complete behavior contracts first. Patterns and developer views get -bounded APIs that fit their meaning. The form builder stays the existing bounded -model, not an application framework. - -Each component or pattern has three integration routes: - -| Mode | Required deliverable | -| --- | --- | -| Package | Exact install, import, registration, CSS, markup, event/property binding and framework example | -| Copy | All required markup, CSS, behavior, dependencies, notices and integration instructions in a standalone bundle | -| Mapping | Existing compact canonical contract and portability/deviation workflow for incompatible or native hosts | - -Prefer package mode when compatible; copy mode is first-class. Multi-file -widgets must include their transitive dependencies and must never be called a -self-contained snippet. Reuse the maintained implementation and generators; do -not fork behavior for the site, recipes or framework examples. Validate multiple -instances and coexistence with host styles. - -Add an implementation manifest to the deterministic machine exports: component -ID, canonical version, package and export identity, recipe path, framework -examples, variants and states, token dependencies. Keep run evidence in separate -artifacts with freshness identities. Show implementation, package, copyability, -showcase and verification as separate facts. - -Add target framework and consumption mode to discovery indexes and task kits. A -small task gets only the selected implementations, their complete dependency -closure and the shared rules. Keep existing integration and lock formats -working; record official package use apart from custom mappings. Agents pin -one immutable revision and keep the required eligibility and decision -disclosures. - -## Portal and documentation - -A short design-system orientation page replaces the long homepage. It still -reads as a UI theme specification, with exact values, state rules and evidence. -The full reference moves to `/theme/reference/`, with tested migration of the -old anchors. Core routes: foundations, components, patterns, tokens, tools, -implement, agents, ports and releases. Keep essential and normative content in -the first static HTML; ordinary pages must load no catalogue-wide JS. - -Every component page combines a live official implementation with anatomy, -tokens, states, variants, interaction and keyboard rules, accessibility, -evidence, responsive behavior, generated API tables and minimal runnable usage. -It offers package instructions, complete copy files, framework examples, machine -contract links, an agent-kit action and links to realistic showcase compositions. - -Document installation, registration, per-component loading, font fallback, -density, attributes versus properties, custom events, native slots, forms, -validation, focus, lifecycle cleanup, allowed customization, browser limits, -troubleshooting, upgrades, pinning and migration. Code in the docs must come from -maintained examples run against the packed artifact in clean fixtures. - -The command palette is an official component used by the portal: a compact, -square, floating Unix utility panel with one prompt, dense vertical rows, a -category column, the canonical selection and focus roles, and local -deterministic search. The later issue comment replaces the original full-width -top-bar direction. - -## Full Vue showcase - -Use Vue 3 JavaScript single-file components, Vite and Vue Router to consume the -framework-agnostic package. Do not build a parallel Vue-native component -library. All public code, content, assets and data are written independently. - -- Analytics, CRM, commerce, academy and logistics dashboards. -- Product, order, customer, user and invoice list/detail/edit workflows. -- Email, chat, calendar and kanban layouts with bounded local actions. -- Profile/settings, a permissions demo, authentication/recovery examples, - pricing/help and utility/error pages. -- Basic/advanced forms, validation recovery, wizards, uploads, charts, developer - views, the bounded form builder and the complete component gallery. - -Use deterministic synthetic data, resettable in-memory state and working local -interactions. Say which screens depend on a service, and state what they cannot demonstrate without it. Give drag interactions a -keyboard alternative. The agreed breadth covers application categories; -it does not require every external reference route or real backend services. - -## Acceptance and hosting - -Prove install and copy into separate applications with no access to private -source paths. Test packed consumers in HTML, Vue, Astro and React. Cover basic -element copying, the full interactive lifecycle, composition dependency closure, -host-style coexistence, multiple instances, bounded task kits and pinned -upgrades. Keep scripted fixtures separate from real agent-run consumption -acceptance. - -Complete the repository gates, package/copy/documentation checks, all-inventory -coverage, representative cross-browser flows, accessibility/input/lifecycle -checks and revision-aware evidence. Set payload budgets from measured builds. -Never claim a manual screen-reader or physical-device pass without its protocol. - -GitHub Pages hosts the static portal and `/theme/demo/` by default, with hash -routing for the Vue application. If a proven Pages limit blocks the agreed -experience, deploy the demo to Vercel and link it from the portal. Hosting never -justifies cutting the agreed scope. After the visual-selection and quality gates, -check that deployed bytes match the tested artifacts. - -## Implemented delivery surfaces and evidence +# Phase 6 delivery record + +Phase 6 made the theme installable: an agent building another application can +discover, select, install or copy, use and verify j3w1 elements, components and +compositions from pinned artifacts, without scraping page DOM, reading values +from screenshots, rebuilding missing behavior or guessing which CSS and +dependencies make a snippet work. Design meaning stays in `tokens/` and +`spec/`; the package implements it, and copy bundles, the portal and the Vue +application consume that implementation (`docs/ui-architecture.md`). This +record does not accept a release by itself; acceptance comes from the separate +execution records for the exact artifact and protocol. + +## Decided + +- **6A, foundation selection.** Current plus exactly three local candidates + ([visual review](phase6-visual-review.md), D-022). The owner selected + True Black / Rose, candidate I (D-023); approval is never inferred from a + recommendation or green checks. +- **Preview corrections.** Red graphs (`color.chart.series-2`), bright rose + column headers over regular rose values, near-white page titles, bright + section and group headings and muted supporting text use existing approved + roles and add no colors. Links became strong red (D-024). +- **6B–6E.** Make the foundation canonical; productize all 67 inventory + entries, including R2/L; build the portal and the Vue showcase; verify + external consumers, publish evidence and deploy the tested artifacts. npm + publication stays an owner release action. +- **Integration routes.** Every component or pattern has three: *package* + (install, import, registration, CSS, markup, binding, framework example), + *copy* (a standalone bundle with all markup, CSS, behavior, dependencies, + notices and instructions) and *mapping* (the compact canonical contract and + the deviation workflow, for incompatible or native hosts). Multi-file widgets + include their transitive dependencies and are never called a self-contained + snippet. +- **Portal.** A short orientation page replaced the long homepage; the full + reference moved to `/theme/reference/` with tested migration of old anchors. + Normative content stays in the first static HTML, and ordinary pages load no + catalogue-wide JavaScript. The command palette is a compact floating panel, + not the original full-width top bar. +- **Vue showcase.** Vue 3 JavaScript SFCs, Vite and Vue Router consume the + framework-agnostic package; there is no parallel Vue component library. + Synthetic, resettable data; drag interactions have a keyboard alternative; + screens that depend on a service say what they cannot demonstrate. GitHub + Pages hosts it at `/theme/demo/` with hash routing; Vercel only if a proven + Pages limit blocks the agreed experience. + +## Delivered - `packages/ui/`: modular ESM classes and registration, native forms and lifecycle, generated API and token dependency metadata, complete copy - distributions, and framework/mode task kits with the selected canonical - contracts and shared rules. -- `site/src/pages/`: static portal, all 67 component pages, foundations, - patterns, tools, implementation guide, agent-kit preparation and the complete - reference. The packaged command palette loads its generated navigation index - on first use and searches components, token values, canonical documents, - decisions, tools, patterns, agent routes, ports and releases. Token values use - the shared inline hex presentation; static section navigation is the fallback. -- `apps/demo/`: Vue 3 JavaScript SFCs with hash routing, five dashboard - contexts, five record workflows, four productivity apps, forms, developer and - utility screens, resettable synthetic data and the whole component gallery. -- `docs/ui-consumption.md` and the maintained framework sources: installation, - binding, lifecycle, native form behavior, copy closure, pinning and migration. -- `npm run ui:consumers` and `npm run test:ui`: install a real tarball in + distributions, and framework/mode task kits. +- `site/src/pages/`: the portal, all 67 component pages, foundations, + patterns, tools, the implementation guide, agent-kit preparation and the + complete reference. The command palette loads its generated navigation index + on first use. +- `apps/demo/`: five dashboard contexts, five record workflows, four + productivity apps, forms, developer and utility screens and the whole + component gallery. +- `docs/ui-consumption.md`: installation, binding, lifecycle, native form + behavior, copy closure, pinning and migration. + +## Evidence + +- At selection, the foundation passed source validation, generation and drift + checks, 105 source tests, the static build, nine distribution tests and the + configured browser suite (204 passed, 124 intentionally skipped). + Verification-report generation kept all 1,866 specimen files. This is + automated foundation evidence, not package acceptance or a manual + accessibility pass. +- `npm run ui:consumers` and `npm run test:ui` install a real tarball in isolated HTML/Vue/React/Astro apps, compile declarations and test three - engines. -- `npm run ui:report` keeps sanitized artifact, fixture and protocol identities - and the recorded environments. `npm run ui:publish-evidence` checks that report - against the downloadable tarball before it publishes `verification/ui.json`. -- The specification evidence pipeline keeps the exact built specimen bytes. CI - requires the package checks and the full site checks before Pages deployment. - Failed runs stay evidence of failure; no manual pass is inferred. - -The gallery axe protocol respects the documented decorative whitespace waiver in -`spec/components/code-editor.md`; real code text is still scanned. Native -validation tests move keyboard focus out of the invalid field before checking -pointer activation, because native validation UI can swallow a click. Payload -gates measure the initial static-import closure apart from lazy chunks; see -`docs/ui-architecture.md` for the measured budgets. + engines. `npm run ui:report` records artifact, fixture and protocol + identities; `npm run ui:publish-evidence` checks that report against the + downloadable tarball before it publishes `verification/ui.json`. +- CI requires the package checks and the full site checks before Pages + deployment. Failed runs stay evidence of failure; no manual pass is inferred. +- The gallery axe protocol respects the decorative whitespace waiver in + `spec/components/code-editor.md`. Native validation tests move focus out of + the invalid field before checking pointer activation, because native + validation UI can swallow a click. Payload budgets are in + `docs/ui-architecture.md`. diff --git a/docs/phase6-visual-review.md b/docs/phase6-visual-review.md index 561535a32..d6ad152fa 100644 --- a/docs/phase6-visual-review.md +++ b/docs/phase6-visual-review.md @@ -1,11 +1,9 @@ # Phase 6A local visual review -Phase 6 exists so agents can install or copy complete elements, components and -compositions into another application, with pinned contracts, explicit -dependencies and verified instructions. The official web package, the -multi-page portal and the full Vue showcase serve that goal. This checkpoint -builds only the local foundation-selection gate from issue #37. It publishes no -package and does not change the canonical palette. +The local foundation-selection gate from issue #37 (D-022). It compares Current +with exactly three candidate token overlays, publishes no package and does not +change the canonical palette. The owner selected candidate I (D-023); this +document stays because the review can be reproduced. ## Run the review @@ -18,53 +16,42 @@ package and does not change the canonical palette. Routes are `/review/current/`, `/review/conservative/`, `/review/balanced/`, `/review/maximum-legibility/`, `/review/compare/` and `/review/report/`. Each -candidate also has `foundations/` and `components/` routes. `components/` -renders every existing specification's variant/state combinations with the -shared parsed specimen renderer. Forced states are appearance references, not -implemented behavior or keyboard evidence. Deferred inventory stays outside the -productization claim at this checkpoint. - -The Vue scene selector covers dashboard, records, settings, controls, developer -views and a consumption-documentation composition. The comparison page syncs -scene, query, filter, form, density, direction and launcher state across four -same-origin frames. Frame widths are real CSS widths, not scaled screenshots. A -640px frame is equivalent reflow evidence, not proof of a manual browser zoom. -Native OS controls and font fallback still depend on the recorded environment. +candidate also has `foundations/` and `components/` routes; `components/` +renders every specification's variant/state combinations with the shared +parsed specimen renderer. Forced states are appearance references, not +implemented behavior or keyboard evidence. + +The comparison page syncs the Vue scene (dashboard, records, settings, +controls, developer views, consumption documentation), query, filter, form, +density, direction and launcher state across four same-origin frames. Frame +widths are real CSS widths, not scaled screenshots; a 640px frame is +equivalent reflow evidence, not proof of a manual browser zoom. Native OS +controls and font fallback depend on the recorded environment. ## Local candidate inputs -Candidate data is ignored on purpose. It is never copied into `dist/`, -`exports/`, public assets, canonical token profiles or a package. This review -checkout holds these files under `.cache/phase6a/inputs/`: - -- `conservative.json` -- `balanced.json` -- `maximum-legibility.json` - -A fresh checkout without them stops with a prerequisite message. Do not invent -or download candidates. Supply the owner-selected local inputs before -reproducing this review. - -Each input follows `overlaySchema` in `scripts/lib/visual-review.mjs`: +Candidate data is ignored on purpose and never copied into `dist/`, +`exports/`, public assets, canonical token profiles or a package. The review +reads `.cache/phase6a/inputs/conservative.json`, `balanced.json` and +`maximum-legibility.json`. A fresh checkout without them stops with a +prerequisite message; do not invent or download candidates. -- version 1; -- the exact baseline digest; -- candidate ID, a summary, and an optional display name; -- a role-keyed changes object, each with an sRGB hex value, rationale and tradeoff. - -Values replace existing opaque color declarations before the canonical alias -resolver runs. Unknown roles, non-color roles, historical ANSI primitive changes, -stale baselines and malformed input fail. Inputs never change approval metadata. +Each input follows `overlaySchema` in `scripts/lib/visual-review.mjs`: version +1, the exact baseline digest, candidate ID, a summary, an optional display name, +and a role-keyed changes object, each with an sRGB hex value, rationale and +tradeoff. Values replace existing opaque color declarations before the +canonical alias resolver runs. Unknown roles, non-color roles, historical ANSI +primitive changes, stale baselines and malformed input fail. Inputs never +change approval metadata. `npm run phase6:visual-build` regenerates the local output without starting the -server. The same source and input bytes give the same output. The report -contains input identities, specimen identity, perceptual OKLCH deltas, affected -components, all declared contrast pairs, untouched roles and unchanged waivers. -It shows unwaived failures rather than fixing or hiding them. Contrast comes -from unrounded sRGB values through the existing engine. A recommendation is a -design hypothesis, not approval. Browser results are recorded separately. +server; the same source and input bytes give the same output. The report holds +input and specimen identities, perceptual OKLCH deltas, affected components, +all declared contrast pairs (unrounded, from the existing engine), untouched +roles and unchanged waivers, and shows unwaived failures rather than hiding +them. A recommendation is a design hypothesis, not approval. -## Verification and limitations +## Verification and limits 1. Run `npm run phase6:visual-test` after the local build. It uses the shared environment fixture, writes local Playwright results and captures matched @@ -73,49 +60,19 @@ design hypothesis, not approval. Browser results are recorded separately. The tests cover synchronization, form recovery, launcher keyboard and focus, responsive layout, RTL, motion, forced colors, static boards and isolation from -public distribution. The ordinary repository check loop still applies; its -evidence describes the public site, not these local candidates. - -The full public browser suite also checks revision-pinned source links and -task-kit packaging. For that gate: - -1. Use a clean committed candidate. -2. Set `GITHUB_SHA` to its full commit before `npm run build`, as hosted CI does. - -An ordinary unpinned local build omits those links and disables packaging on -purpose, so it cannot pass the pinned-link assertions. If you missed this step, -keep the failed run and rebuild from the committed candidate. Do not weaken the -assertions or stamp a dirty build as a published revision. - -No font is downloaded or bundled. No private reference source or asset is -copied. The Vue screen is an original preview built from canonical roles and -existing component CSS; its controls are not presented as the future official -package. The consumption-page actions describe future deliverables instead of -offering package or download links that do not exist. All data is synthetic, -updates stay in memory, and no remote services run. - -## Owner gate and continuation - -1. Present the three current input names, the report, the matched local review - URLs and the evidence-weighted recommendation. -2. Keep stable route IDs across review rounds; display names identify the - current directions. -3. Archive rejected inputs, output and evidence together before replacing them. - Never carry a rejected round's recommendation into a new report. -4. Wait for explicit selection. Consolidate a requested hybrid and show it again. -5. Do not canonicalize, merge, deploy, tag or publish a candidate before - selection. - -After selection: - -1. Freeze the canonical foundation with owner decision provenance. -2. Productize every baseline inventory entry. -3. Generate install and copy distributions from the maintained implementation. -4. Build the static-first portal with API and consumption examples. -5. Build the full Vue showcase. -6. Verify external consumer fixtures and documentation. -7. Release tested artifacts. - -The portal replaces the long homepage, keeps the complete reference at a -secondary route and keeps machine contracts as the agent entry point. Pages is -the default host; the demo may use Vercel if a real hosting limit requires it. +public distribution. The repository check loop still applies; its evidence +describes the public site, not these local candidates. + +No font is downloaded or bundled and no private reference source or asset is +copied. The Vue screen is an original preview from canonical roles and existing +component CSS. All data is synthetic, updates stay in memory, and no remote +services run. + +## Owner gate + +Present the input names, the report, the matched review URLs and the +evidence-weighted recommendation. Keep stable route IDs across rounds. Archive +rejected inputs, output and evidence together before replacing them, and never +carry a rejected round's recommendation into a new report. Wait for explicit +selection; show a requested hybrid again as one candidate. Do not canonicalize, +merge, deploy, tag or publish a candidate before selection. diff --git a/docs/rose-typography-migration.md b/docs/rose-typography-migration.md index bd099e4f3..09e1bf5c5 100644 --- a/docs/rose-typography-migration.md +++ b/docs/rose-typography-migration.md @@ -1,9 +1,8 @@ # Rose typography migration — 4.0.0 -D-033 corrects the canonical text hierarchy. Ordinary interface and prose are -`#e99499`; brighter labels are `#ffa2a7`; content titles and H1–H6 use the new -`color.text.heading` (`#f4eeee`). `color.text.highlight` is an explicit rare -highlight. Bold inherits context and never chooses a foreground by weight. +D-033 makes ordinary interface and prose text rose and gives content headings +`color.text.heading`; bold inherits its context. This audit classifies every +former near-white use. ## Near-white audit @@ -21,9 +20,9 @@ highlight. Bold inherits context and never chooses a foreground by weight. | heritage-ansi prompt and extended terminal slot 15 | Historical/profile-specific terminal semantics; retain | | Historical decisions, releases and reference evidence | Historical truth; do not rewrite | -Every port classifies the new roles; unsupported host hooks are disclosed. -Generated values change through tokens and mappings only. No global replacement -of white literals or changes to syntax/diagnostic palettes is performed. +Every port classifies the new roles and discloses unsupported host hooks. +Values change through tokens and mappings only: no global replacement of white +literals, and no change to syntax or diagnostic palettes. ## Upgrade diff --git a/docs/true-black-rose-migration.md b/docs/true-black-rose-migration.md index 0433a880e..cdf8ee0d8 100644 --- a/docs/true-black-rose-migration.md +++ b/docs/true-black-rose-migration.md @@ -1,8 +1,8 @@ # True Black / Rose migration -The owner selected the exact locally reviewed candidate I and approved its -permanent adoption; D-023 records it. Version 1.0.0 follows the repository's -major-version rule for changing approved values. +Version 1.0.0 adopts the owner-selected candidate I (D-023), a major version +under the rule for changing approved values. Seven surfaces change; the +heritage profile keeps its prior surface assignments. | Semantic role | Previous value | Selected value | | --- | --- | --- | @@ -14,17 +14,13 @@ major-version rule for changing approved values. | color.surface.chrome | #100909 | #090707 | | color.surface.default | #160b0b | #100c0c | -The later owner-requested link change (D-024) moves `color.text.link` from -`#ffa2a7` to the existing strong red `#f73f35`. Visited links keep that color; -persistent underlines and near-white hover text mark navigation. The heritage -profile keeps the previous link assignment. - -All other token values are unchanged: rose body text, pink headings, white -prose, red borders/actions/focus/selection, and the status, chart, code and -terminal assignments stay as reviewed. `color.code.bg` and `color.terminal.bg` -keep their original assignments; do not confuse them with `color.surface.code` -and `color.surface.terminal`. The heritage profile keeps its prior surface -assignments. +`color.code.bg` and `color.terminal.bg` keep their original assignments; do not +confuse them with `color.surface.code` and `color.surface.terminal`. Two new +primitives hold the chrome and panel values; applications still consume +semantic roles, never primitive keys. In the same release `color.text.link` +moved from `#ffa2a7` to strong red `#f73f35` (D-024); the heritage profile keeps +the previous link. Later releases changed more roles: see D-026, D-027 and +D-033 and the [rose typography migration](rose-typography-migration.md). ## Update a consumer @@ -37,23 +33,16 @@ Do not overwrite user customization or silently edit another repository. Native import verification and manual accessibility records apply only to their recorded source and artifact digests. -## What else changed +## Package and site changes in 1.0.0 -The change adds two primitives for the selected chrome and panel values. -Applications still consume semantic roles, never these primitive keys. This -change approves no pending decision outside the selected foundation. +The package and complete copy bundles implement all 67 inventory entries; +existing mappings and lock formats still work. When you adopt them, install one +exact version, update its tokens and component styles together, and review the +full dependency closure when you replace copied source. The CLI refuses to +overwrite an old copy: create a fresh directory and merge your application +changes by hand. -The portal replaces the long homepage; the full static state reference is now +The portal replaces the long homepage; the full static reference is `/theme/reference/`. Old homepage hashes move there with JavaScript, and the static full-reference link works without it. The Vue demo uses `/theme/demo/#/...` so direct links work on GitHub Pages. - -The new package and complete copy bundles implement all 67 inventory entries. -Existing mappings and lock formats still work. When you adopt the package or copy bundles: - -1. Install one exact version. -2. Update its tokens and component styles together. -3. Review the full dependency closure when you replace copied source. - -The CLI refuses to overwrite an old copy. Create a fresh directory and merge -your application changes carefully, by hand. diff --git a/docs/ui-architecture.md b/docs/ui-architecture.md index e184e79e3..e302330f2 100644 --- a/docs/ui-architecture.md +++ b/docs/ui-architecture.md @@ -1,8 +1,8 @@ # Official web implementation architecture -Status: all 67 inventory entries, copy distributions, the static portal and Vue -showcase are implemented. This document describes the architecture. Actual -acceptance and deployment are in the separate delivery and execution records. +All 67 inventory entries, copy distributions, the static portal and the Vue +showcase are implemented. This document describes the architecture; acceptance +and deployment are in the separate delivery and execution records. ## Ownership @@ -11,75 +11,67 @@ acceptance and deployment are in the separate delivery and execution records. - The build combines that behavior, the canonical component styles and the maintained usage examples into the package and the complete copy distributions. -- The portal and Vue showcase consume those outputs. They carry no second +- The portal and Vue showcase consume those outputs and carry no second component implementation. -**Site chrome.** The portal is built from the same components it documents. -Chrome uses `comfortable` density and only canonical component classes: actions -are `.button` in one of the four tones, navigation is `.link`, calls to action -are `.link-standalone`. Forced states appear only inside specimens. - -UI builds keep stable entry paths under `.cache/ui-build` so emitted bytes and -implementation identities are reproducible. An exclusive `.cache/ui-build.lock` -coordinates concurrent build and check processes; each waits for the prior -process to finish before clearing or reading that stage. The lock is released -on success or a caught failure. A wait longer than 60 seconds fails. If a process -is forcibly stopped, confirm no UI build is running before removing its lock. - -**Choices (D-025).** Theme-rendered choices are the default web implementation. -The shared `internal/choice.js` renderer draws single comboboxes and multiple -listboxes. The original select keeps FormData, constraints, defaults and events. - -- The package Select uses the renderer directly; component compositions enhance - their own bare controls. -- The public `enhance/choice` entry watches only the application root you pass - it, and skips controls owned by another j3w1 component. It never moves the - native select out of its framework-owned DOM position. -- Destroy disconnects observers and listeners and restores the native control - and its label relationship. -- The Vue application and portal use this public entry; they keep no separate - dropdown implementations. Native no-JavaScript fallbacks stay visible. +**Site chrome.** The portal is built from the components it documents. Chrome +uses `comfortable` density and only canonical component classes: actions are +`.button` in one of the four tones, navigation is `.link`, calls to action are +`.link-standalone`. Forced states appear only inside specimens. + +**Build lock.** UI builds keep stable entry paths under `.cache/ui-build` so +emitted bytes and implementation identities are reproducible. An exclusive +`.cache/ui-build.lock` serializes concurrent build and check processes; it is +released on success or a caught failure, and a wait longer than 60 seconds +fails. If a process is forcibly stopped, confirm no UI build is running before +removing its lock. + +**Choices (D-025).** The shared `internal/choice.js` renderer draws single +comboboxes and multiple listboxes; the original select keeps FormData, +constraints, defaults and events. The package Select uses the renderer +directly; component compositions enhance their own bare controls. The public +`enhance/choice` entry watches only the application root you pass it, skips +controls owned by another j3w1 component and never moves the native select out +of its framework-owned DOM position. Destroy disconnects observers and +listeners and restores the native control and its label relationship. The Vue +application and portal use this public entry, with no separate dropdowns. **Control styles.** The standalone `styles/controls.css` is generated from the same canonical `site/src/styles/themed-controls.css` that component and copy distributions use. It is separate because component styles are scoped to their custom-element tag, while application enhancement is scoped to -`data-j3w1-controls`. The canonical stylesheet also puts generic control chrome -behind that enhancement boundary, so importing component reference CSS cannot -change unrelated native specimens, forced-state examples or standalone recipes. - -Historical specimen and private comparison rendering resolve this CSS closure -from the selected Git revision, then apply the existing resource and behavior -checks. Relative imports stay inside that revision's style tree. External, -missing, cyclic and escaping dependencies fail closed. - -**Inventory.** The inventory is the finite list in `spec/inventory.json`. Package -generation fails if an entry has no canonical contract or implementation -mapping. Contract maturity stays separate from implementation and verification -status; productization does not quietly approve pending design decisions. +`data-j3w1-controls`. Generic control chrome sits behind that enhancement +boundary, so importing component reference CSS cannot change unrelated native +specimens, forced-state examples or standalone recipes. Historical specimen and +private comparison rendering resolve this CSS closure from the selected Git +revision; relative imports stay inside that revision's style tree, and +external, missing, cyclic and escaping dependencies fail closed. + +**Inventory.** The inventory is the finite list in `spec/inventory.json`. +Package generation fails if an entry has no canonical contract or +implementation mapping. Contract maturity stays separate from implementation +and verification status; productization does not approve pending decisions. ## Native content and lifecycle Components use light DOM where native semantics, form ownership, static content -and composition benefit. Each implementation manifest entry records the reason. - -- A field's input stays the successful native form control; the wrapper submits - no duplicate hidden value. -- Labels, fieldsets, constraint validation and reset keep browser behavior. -- Custom widgets must implement their complete canonical keyboard and accessibility - contracts. +and composition benefit; each implementation manifest entry records the +reason. A field's input stays the successful native form control, and the +wrapper submits no duplicate hidden value. Labels, fieldsets, constraint +validation and reset keep browser behavior. Custom widgets implement their +complete canonical keyboard and accessibility contracts. Registration: -- Class imports are separate from browser registration. -- Each registration module includes its component dependencies. +- Class imports are separate from browser registration; each registration + module includes its component dependencies, and the root registration module + registers the complete catalogue on purpose. - Registering again with the same constructor, or the identical generated implementation identity, is safe, including across independent copy directories. A different version or foreign definition is an error. - The implementation identity hashes the component's definition and the exact emitted modules its class reaches, so it changes only when that runtime code changes. -- The root registration module registers the complete catalogue on purpose. - Server renderers import class definitions only when needed and register in the browser. Native child markup is the static and server-rendered content. @@ -88,69 +80,57 @@ Lifecycle: - Connected listeners use a connection-scoped AbortSignal. Disconnect aborts them and runs controller cleanup for timers, observers and document-level effects. -- Writable controller properties survive reconnection. Properties set before - custom-element upgrade are replayed after connection. +- Writable controller properties survive reconnection; properties set before + upgrade are replayed after connection. - Call `refresh()` after replacing a component's native child structure. Reactive changes to existing native children need no remount. Properties change state without inventing user input events. Native input and -change events stay available. Documented `j3w1-*` custom events bubble across -component boundaries and carry structured details. Navigation, persistence, +change events stay available; documented `j3w1-*` custom events bubble across +component boundaries with structured details. Navigation, persistence, authorization and network services belong to the consuming application. ## Styles and complete copying -- Token CSS comes from the selected canonical profile. -- Component styles come from canonical CSS, shared inherited rules and - maintained behavior selectors. +- Token CSS comes from the selected canonical profile; component styles from + canonical CSS, shared inherited rules and maintained behavior selectors. - Distribution selectors are scoped to the custom-element name. They keep real states and drop forced-state specimen selectors. -- Light DOM is intentional; it does not claim immunity to overriding host CSS. - Semantic variables and anatomy classes are the documented extension points. +- Light DOM does not claim immunity to overriding host CSS. Semantic variables + and anatomy classes are the documented extension points. -Per-component CSS includes transitive composition dependencies. Per-component -ESM includes the complete runtime dependency closure. The build parses emitted -module imports with `es-module-lexer`, follows literal relative imports, and -rejects unbundled bare imports and non-literal dynamic dependencies. Import-like -text inside strings or comments cannot become a dependency by accident. +Per-component CSS includes transitive composition dependencies, and +per-component ESM the complete runtime dependency closure. The build parses +emitted imports with `es-module-lexer`, follows literal relative imports, and +rejects unbundled bare imports and non-literal dynamic dependencies; +import-like text in strings or comments is never a dependency. Each copy directory contains runnable HTML, element markup, CSS, token CSS, -runtime modules, notices, instructions and file digests. - -- The CLI checks every selected file before creating a destination. -- It refuses an existing destination, unsafe paths and symlink destinations. -- Multi-component kits keep complete standalone component directories. -- Consumers keep the required code licenses and specimen attribution; shipping - code next to prose does not relicense it. +runtime modules, notices, instructions and file digests. The CLI checks every +selected file before creating a destination and refuses an existing +destination, unsafe paths and symlink destinations. Multi-component kits keep +complete standalone component directories. Consumers keep the required code +licenses and specimen attribution; shipping code next to prose does not +relicense it. ## Build and verification commands -The workspace uses Node 24 and npm. - 1. `npm run ui:build` builds the package. 2. `npm run ui:pack` prepares its tarball. -3. `npm run ui:consumers` packs the real package and installs it into - independent temporary HTML, Vue, React and Astro applications. They import - public package paths, compile declarations, build their applications and run - the installed copy CLI. They have no workspace source imports. +3. `npm run ui:consumers` installs the packed package into independent + temporary HTML, Vue, React and Astro applications that import public package + paths only, compile declarations, build and run the installed copy CLI. 4. `npm run test:ui` runs the served artifacts in Chromium, Firefox and WebKit. -Generated outputs are checked for drift, including orphaned files. These -commands need the complete implementation catalogue and maintained examples; -infrastructure alone is not a release. Passing scripted fixtures is reported -separately from real agent-run acceptance. - Source checks, generated drift checks, static build checks, browser execution, packed installation, copying and release deployment are separate gates. Site -evidence stays tied to the exact built specimen bytes. Package evidence also -identifies the packed tarball and the external fixture bytes. Manual -screen-reader and physical-device results need their own recorded protocols; -automated browser runs do not establish them. +evidence is tied to the exact built specimen bytes; package evidence also +identifies the packed tarball and the external fixture bytes. Scripted fixtures +are reported apart from real agent-run acceptance, and manual screen-reader and +physical-device results need their own recorded protocols. ## Payload budgets -Distribution checks cap these sizes: - | Measure | Cap | | --- | --- | | Initial Vue JavaScript | 64 KiB gzip | @@ -158,20 +138,16 @@ Distribution checks cap these sizes: | Each lazy Vue chunk | 192 KiB gzip | | Complete installable tarball | 2 MiB | -First measurements were about 46 KiB for the Vue entry and 140 KiB for the -lazily loaded bounded form builder, which includes its schema and HTML-parsing -dependencies. These are transfer-size estimates, not a claim that the static -host enables a particular compression setting. The test follows static imports -and keeps optional dynamic imports separate. Per-component imports avoid loading -the full catalogue on ordinary pages. +The distribution test follows static imports and keeps optional dynamic imports +separate. First measurements were about 46 KiB for the Vue entry and 140 KiB +for the lazily loaded form builder. These are transfer-size estimates, not a +claim about the static host's compression. ## Standards consulted -The implementation uses the native form and custom-element platform contracts: -[custom elements](https://html.spec.whatwg.org/multipage/custom-elements.html), +[Custom elements](https://html.spec.whatwg.org/multipage/custom-elements.html), [form infrastructure](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html), -and [Vue's custom-element integration](https://vuejs.org/guide/extras/web-components). -Custom widgets follow their canonical component specification and the linked -[APG keyboard guidance](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/). -These are living documents consulted during implementation; the package's real -browser evidence defines the exercised compatibility. +[Vue's custom-element integration](https://vuejs.org/guide/extras/web-components) +and the [APG keyboard guidance](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/). +They are living documents; the package's real browser evidence defines the +exercised compatibility. From 62cd1a43fd27521e7e76caa3cd3c616dc32b51bb Mon Sep 17 00:00:00 2001 From: j3w1 Date: Wed, 14 Oct 2026 15:37:08 -0500 Subject: [PATCH 04/65] chore: regenerate Source digests, the full Markdown export, the packaged consumer rules and the form identity follow the condensed decision log and docs. Co-Authored-By: Claude Opus 5.5 --- exports/components/admin-form.brief.txt | 2 +- exports/components/admin-form.json | 2 +- exports/components/alert.brief.txt | 2 +- exports/components/alert.json | 2 +- exports/components/avatar.brief.txt | 2 +- exports/components/avatar.json | 2 +- exports/components/badge.brief.txt | 2 +- exports/components/badge.json | 2 +- exports/components/breadcrumbs.brief.txt | 2 +- exports/components/breadcrumbs.json | 2 +- exports/components/button-group.brief.txt | 2 +- exports/components/button-group.json | 2 +- exports/components/button.brief.txt | 2 +- exports/components/button.json | 2 +- exports/components/card.brief.txt | 2 +- exports/components/card.json | 2 +- exports/components/chart.brief.txt | 2 +- exports/components/chart.json | 2 +- exports/components/checkbox.brief.txt | 2 +- exports/components/checkbox.json | 2 +- exports/components/chip.brief.txt | 2 +- exports/components/chip.json | 2 +- exports/components/code-editor.brief.txt | 2 +- exports/components/code-editor.json | 2 +- exports/components/combobox.brief.txt | 2 +- exports/components/combobox.json | 2 +- exports/components/command-palette.brief.txt | 2 +- exports/components/command-palette.json | 2 +- .../components/compact-dashboard.brief.txt | 2 +- exports/components/compact-dashboard.json | 2 +- exports/components/data-table.brief.txt | 2 +- exports/components/data-table.json | 2 +- exports/components/date-picker.brief.txt | 2 +- exports/components/date-picker.json | 2 +- exports/components/description-list.brief.txt | 2 +- exports/components/description-list.json | 2 +- exports/components/diagnostics.brief.txt | 2 +- exports/components/diagnostics.json | 2 +- exports/components/dialog.brief.txt | 2 +- exports/components/dialog.json | 2 +- exports/components/diff-view.brief.txt | 2 +- exports/components/diff-view.json | 2 +- exports/components/disclosure.brief.txt | 2 +- exports/components/disclosure.json | 2 +- exports/components/drawer.brief.txt | 2 +- exports/components/drawer.json | 2 +- exports/components/editor-search.brief.txt | 2 +- exports/components/editor-search.json | 2 +- exports/components/empty-state.brief.txt | 2 +- exports/components/empty-state.json | 2 +- exports/components/error-state.brief.txt | 2 +- exports/components/error-state.json | 2 +- exports/components/field.brief.txt | 2 +- exports/components/field.json | 2 +- exports/components/fieldset.brief.txt | 2 +- exports/components/fieldset.json | 2 +- exports/components/file-browser.brief.txt | 2 +- exports/components/file-browser.json | 2 +- exports/components/file-input.brief.txt | 2 +- exports/components/file-input.json | 2 +- exports/components/filterable-table.brief.txt | 2 +- exports/components/filterable-table.json | 2 +- exports/components/form-builder.brief.txt | 2 +- exports/components/form-builder.json | 2 +- exports/components/i3-window-frame.brief.txt | 2 +- exports/components/i3-window-frame.json | 2 +- exports/components/icon-button.brief.txt | 2 +- exports/components/icon-button.json | 2 +- exports/components/kbd.brief.txt | 2 +- exports/components/kbd.json | 2 +- exports/components/link.brief.txt | 2 +- exports/components/link.json | 2 +- exports/components/list.brief.txt | 2 +- exports/components/list.json | 2 +- .../components/loading-indicator.brief.txt | 2 +- exports/components/loading-indicator.json | 2 +- exports/components/menu.brief.txt | 2 +- exports/components/menu.json | 2 +- exports/components/multiselect.brief.txt | 2 +- exports/components/multiselect.json | 2 +- exports/components/number-field.brief.txt | 2 +- exports/components/number-field.json | 2 +- exports/components/pagination.brief.txt | 2 +- exports/components/pagination.json | 2 +- exports/components/popover.brief.txt | 2 +- exports/components/popover.json | 2 +- exports/components/progress.brief.txt | 2 +- exports/components/progress.json | 2 +- exports/components/radio-group.brief.txt | 2 +- exports/components/radio-group.json | 2 +- exports/components/range.brief.txt | 2 +- exports/components/range.json | 2 +- exports/components/repeater.brief.txt | 2 +- exports/components/repeater.json | 2 +- exports/components/search-field.brief.txt | 2 +- exports/components/search-field.json | 2 +- .../components/segmented-control.brief.txt | 2 +- exports/components/segmented-control.json | 2 +- exports/components/select.brief.txt | 2 +- exports/components/select.json | 2 +- exports/components/settings-panel.brief.txt | 2 +- exports/components/settings-panel.json | 2 +- exports/components/sidebar-nav.brief.txt | 2 +- exports/components/sidebar-nav.json | 2 +- exports/components/skeleton.brief.txt | 2 +- exports/components/skeleton.json | 2 +- exports/components/skip-link.brief.txt | 2 +- exports/components/skip-link.json | 2 +- exports/components/switch.brief.txt | 2 +- exports/components/switch.json | 2 +- exports/components/table.brief.txt | 2 +- exports/components/table.json | 2 +- exports/components/tabs.brief.txt | 2 +- exports/components/tabs.json | 2 +- exports/components/terminal.brief.txt | 2 +- exports/components/terminal.json | 2 +- exports/components/text-field.brief.txt | 2 +- exports/components/text-field.json | 2 +- exports/components/textarea.brief.txt | 2 +- exports/components/textarea.json | 2 +- exports/components/time-picker.brief.txt | 2 +- exports/components/time-picker.json | 2 +- exports/components/timeline.brief.txt | 2 +- exports/components/timeline.json | 2 +- exports/components/toast.brief.txt | 2 +- exports/components/toast.json | 2 +- exports/components/toolbar.brief.txt | 2 +- exports/components/toolbar.json | 2 +- exports/components/tooltip.brief.txt | 2 +- exports/components/tooltip.json | 2 +- exports/components/tree.brief.txt | 2 +- exports/components/tree.json | 2 +- exports/components/wizard.brief.txt | 2 +- exports/components/wizard.json | 2 +- exports/digests.json | 278 ++-- exports/forms/identity.json | 2 +- exports/patterns/validation-recovery.json | 20 +- exports/task-inputs.json | 138 +- exports/theme.compact.md | 2 +- exports/theme.full.md | 1253 ++++++++--------- packages/ui/dist/canonical/admin-form.json | 2 +- packages/ui/dist/canonical/alert.json | 2 +- packages/ui/dist/canonical/avatar.json | 2 +- packages/ui/dist/canonical/badge.json | 2 +- packages/ui/dist/canonical/breadcrumbs.json | 2 +- packages/ui/dist/canonical/button-group.json | 2 +- packages/ui/dist/canonical/button.json | 2 +- packages/ui/dist/canonical/card.json | 2 +- packages/ui/dist/canonical/chart.json | 2 +- packages/ui/dist/canonical/checkbox.json | 2 +- packages/ui/dist/canonical/chip.json | 2 +- packages/ui/dist/canonical/code-editor.json | 2 +- packages/ui/dist/canonical/combobox.json | 2 +- .../ui/dist/canonical/command-palette.json | 2 +- .../ui/dist/canonical/compact-dashboard.json | 2 +- packages/ui/dist/canonical/data-table.json | 2 +- packages/ui/dist/canonical/date-picker.json | 2 +- .../ui/dist/canonical/description-list.json | 2 +- packages/ui/dist/canonical/diagnostics.json | 2 +- packages/ui/dist/canonical/dialog.json | 2 +- packages/ui/dist/canonical/diff-view.json | 2 +- packages/ui/dist/canonical/disclosure.json | 2 +- packages/ui/dist/canonical/drawer.json | 2 +- packages/ui/dist/canonical/editor-search.json | 2 +- packages/ui/dist/canonical/empty-state.json | 2 +- packages/ui/dist/canonical/error-state.json | 2 +- packages/ui/dist/canonical/field.json | 2 +- packages/ui/dist/canonical/fieldset.json | 2 +- packages/ui/dist/canonical/file-browser.json | 2 +- packages/ui/dist/canonical/file-input.json | 2 +- .../ui/dist/canonical/filterable-table.json | 2 +- packages/ui/dist/canonical/form-builder.json | 2 +- .../ui/dist/canonical/i3-window-frame.json | 2 +- packages/ui/dist/canonical/icon-button.json | 2 +- packages/ui/dist/canonical/kbd.json | 2 +- packages/ui/dist/canonical/link.json | 2 +- packages/ui/dist/canonical/list.json | 2 +- .../ui/dist/canonical/loading-indicator.json | 2 +- packages/ui/dist/canonical/menu.json | 2 +- packages/ui/dist/canonical/multiselect.json | 2 +- packages/ui/dist/canonical/number-field.json | 2 +- packages/ui/dist/canonical/pagination.json | 2 +- packages/ui/dist/canonical/popover.json | 2 +- packages/ui/dist/canonical/progress.json | 2 +- packages/ui/dist/canonical/radio-group.json | 2 +- packages/ui/dist/canonical/range.json | 2 +- packages/ui/dist/canonical/repeater.json | 2 +- packages/ui/dist/canonical/search-field.json | 2 +- .../ui/dist/canonical/segmented-control.json | 2 +- packages/ui/dist/canonical/select.json | 2 +- .../ui/dist/canonical/settings-panel.json | 2 +- packages/ui/dist/canonical/sidebar-nav.json | 2 +- packages/ui/dist/canonical/skeleton.json | 2 +- packages/ui/dist/canonical/skip-link.json | 2 +- packages/ui/dist/canonical/switch.json | 2 +- packages/ui/dist/canonical/table.json | 2 +- packages/ui/dist/canonical/tabs.json | 2 +- packages/ui/dist/canonical/terminal.json | 2 +- packages/ui/dist/canonical/text-field.json | 2 +- packages/ui/dist/canonical/textarea.json | 2 +- packages/ui/dist/canonical/time-picker.json | 2 +- packages/ui/dist/canonical/timeline.json | 2 +- packages/ui/dist/canonical/toast.json | 2 +- packages/ui/dist/canonical/toolbar.json | 2 +- packages/ui/dist/canonical/tooltip.json | 2 +- packages/ui/dist/canonical/tree.json | 2 +- packages/ui/dist/canonical/wizard.json | 2 +- ...r-C5Kx5G9b.js => form-builder-BXNafoR0.js} | 2 +- ...r-C6Rhfsz6.js => form-builder-CFAdHM30.js} | 4 +- packages/ui/dist/components/form-builder.js | 2 +- packages/ui/dist/contracts/form-builder.json | 2 +- .../ui/dist/copy/form-builder/manifest.json | 10 +- ...r-C5Kx5G9b.js => form-builder-BXNafoR0.js} | 2 +- ...r-C6Rhfsz6.js => form-builder-CFAdHM30.js} | 4 +- .../runtime/register/form-builder.js | 2 +- packages/ui/dist/enhance/form-builder.js | 2 +- packages/ui/dist/index.js | 2 +- packages/ui/dist/manifest.json | 8 +- packages/ui/dist/register/form-builder.js | 2 +- packages/ui/dist/rules/consume.md | 62 +- 220 files changed, 1043 insertions(+), 1156 deletions(-) rename packages/ui/dist/chunks/{form-builder-C5Kx5G9b.js => form-builder-BXNafoR0.js} (99%) rename packages/ui/dist/chunks/{form-builder-C6Rhfsz6.js => form-builder-CFAdHM30.js} (92%) rename packages/ui/dist/copy/form-builder/runtime/chunks/{form-builder-C5Kx5G9b.js => form-builder-BXNafoR0.js} (99%) rename packages/ui/dist/copy/form-builder/runtime/chunks/{form-builder-C6Rhfsz6.js => form-builder-CFAdHM30.js} (92%) diff --git a/exports/components/admin-form.brief.txt b/exports/components/admin-form.brief.txt index 01b75f138..7543a7105 100644 --- a/exports/components/admin-form.brief.txt +++ b/exports/components/admin-form.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — admin-form -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/admin-form.json spec: spec/components/admin-form.md site: https://j3w1.github.io/theme/reference/#c-admin-form maturity: stable priority: R1 diff --git a/exports/components/admin-form.json b/exports/components/admin-form.json index d9c2f0098..b99624816 100644 --- a/exports/components/admin-form.json +++ b/exports/components/admin-form.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "admin-form", "family": "composed", "maturity": "stable", diff --git a/exports/components/alert.brief.txt b/exports/components/alert.brief.txt index 9113e82f1..29639bf45 100644 --- a/exports/components/alert.brief.txt +++ b/exports/components/alert.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — alert -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/alert.json spec: spec/components/alert.md site: https://j3w1.github.io/theme/reference/#c-alert maturity: stable priority: R1 diff --git a/exports/components/alert.json b/exports/components/alert.json index b89f74eb8..613807cda 100644 --- a/exports/components/alert.json +++ b/exports/components/alert.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "alert", "family": "feedback", "maturity": "stable", diff --git a/exports/components/avatar.brief.txt b/exports/components/avatar.brief.txt index 313c2b7f8..6eef1ec23 100644 --- a/exports/components/avatar.brief.txt +++ b/exports/components/avatar.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — avatar -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/avatar.json spec: spec/components/avatar.md site: https://j3w1.github.io/theme/reference/#c-avatar maturity: stable priority: R2 diff --git a/exports/components/avatar.json b/exports/components/avatar.json index b87bc4ba6..8fb177dac 100644 --- a/exports/components/avatar.json +++ b/exports/components/avatar.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "avatar", "family": "display", "maturity": "stable", diff --git a/exports/components/badge.brief.txt b/exports/components/badge.brief.txt index 9ce190f47..2809b530c 100644 --- a/exports/components/badge.brief.txt +++ b/exports/components/badge.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — badge -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/badge.json spec: spec/components/badge.md site: https://j3w1.github.io/theme/reference/#c-badge maturity: stable priority: R1 diff --git a/exports/components/badge.json b/exports/components/badge.json index e8fb3f1d9..c660e8edf 100644 --- a/exports/components/badge.json +++ b/exports/components/badge.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "badge", "family": "display", "maturity": "stable", diff --git a/exports/components/breadcrumbs.brief.txt b/exports/components/breadcrumbs.brief.txt index 33822fe3b..76dccb9db 100644 --- a/exports/components/breadcrumbs.brief.txt +++ b/exports/components/breadcrumbs.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — breadcrumbs -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/breadcrumbs.json spec: spec/components/breadcrumbs.md site: https://j3w1.github.io/theme/reference/#c-breadcrumbs maturity: stable priority: R1 diff --git a/exports/components/breadcrumbs.json b/exports/components/breadcrumbs.json index 4ad9f0157..8f76b51f2 100644 --- a/exports/components/breadcrumbs.json +++ b/exports/components/breadcrumbs.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "breadcrumbs", "family": "navigation", "maturity": "stable", diff --git a/exports/components/button-group.brief.txt b/exports/components/button-group.brief.txt index 3572c5af6..64ac9f953 100644 --- a/exports/components/button-group.brief.txt +++ b/exports/components/button-group.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — button-group -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/button-group.json spec: spec/components/button-group.md site: https://j3w1.github.io/theme/reference/#c-button-group maturity: stable priority: R2 diff --git a/exports/components/button-group.json b/exports/components/button-group.json index c9ff24fe3..ac743e2f9 100644 --- a/exports/components/button-group.json +++ b/exports/components/button-group.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "button-group", "family": "actions", "maturity": "stable", diff --git a/exports/components/button.brief.txt b/exports/components/button.brief.txt index d7c1d3d8d..776137cab 100644 --- a/exports/components/button.brief.txt +++ b/exports/components/button.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — button -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/button.json spec: spec/components/button.md site: https://j3w1.github.io/theme/reference/#c-button maturity: stable priority: R1 diff --git a/exports/components/button.json b/exports/components/button.json index 09365a973..5caf187ae 100644 --- a/exports/components/button.json +++ b/exports/components/button.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "button", "family": "actions", "maturity": "stable", diff --git a/exports/components/card.brief.txt b/exports/components/card.brief.txt index 893c55853..50932af16 100644 --- a/exports/components/card.brief.txt +++ b/exports/components/card.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — card -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/card.json spec: spec/components/card.md site: https://j3w1.github.io/theme/reference/#c-card maturity: stable priority: R1 diff --git a/exports/components/card.json b/exports/components/card.json index 32e6c7b3b..ecf5d77ba 100644 --- a/exports/components/card.json +++ b/exports/components/card.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "card", "family": "display", "maturity": "stable", diff --git a/exports/components/chart.brief.txt b/exports/components/chart.brief.txt index 2c4a7dc20..2a45f9c28 100644 --- a/exports/components/chart.brief.txt +++ b/exports/components/chart.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — chart -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/chart.json spec: spec/components/chart.md site: https://j3w1.github.io/theme/reference/#c-chart maturity: stable priority: R2 diff --git a/exports/components/chart.json b/exports/components/chart.json index c9589d641..91e5be004 100644 --- a/exports/components/chart.json +++ b/exports/components/chart.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "chart", "family": "display", "maturity": "stable", diff --git a/exports/components/checkbox.brief.txt b/exports/components/checkbox.brief.txt index cf9bbe6d5..33ca41b46 100644 --- a/exports/components/checkbox.brief.txt +++ b/exports/components/checkbox.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — checkbox -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/checkbox.json spec: spec/components/checkbox.md site: https://j3w1.github.io/theme/reference/#c-checkbox maturity: stable priority: R1 diff --git a/exports/components/checkbox.json b/exports/components/checkbox.json index 062776314..0b1ec0370 100644 --- a/exports/components/checkbox.json +++ b/exports/components/checkbox.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "checkbox", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/chip.brief.txt b/exports/components/chip.brief.txt index 5658aa138..7a0b6a583 100644 --- a/exports/components/chip.brief.txt +++ b/exports/components/chip.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — chip -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/chip.json spec: spec/components/chip.md site: https://j3w1.github.io/theme/reference/#c-chip maturity: stable priority: R1 diff --git a/exports/components/chip.json b/exports/components/chip.json index e3455073c..cc9ef264e 100644 --- a/exports/components/chip.json +++ b/exports/components/chip.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "chip", "family": "display", "maturity": "stable", diff --git a/exports/components/code-editor.brief.txt b/exports/components/code-editor.brief.txt index 863fa0ab6..5e890e1b6 100644 --- a/exports/components/code-editor.brief.txt +++ b/exports/components/code-editor.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — code-editor -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/code-editor.json spec: spec/components/code-editor.md site: https://j3w1.github.io/theme/reference/#c-code-editor maturity: stable priority: R1 diff --git a/exports/components/code-editor.json b/exports/components/code-editor.json index e9dfeed82..8f62c5855 100644 --- a/exports/components/code-editor.json +++ b/exports/components/code-editor.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "code-editor", "family": "developer", "maturity": "stable", diff --git a/exports/components/combobox.brief.txt b/exports/components/combobox.brief.txt index 21a400051..ebe20c84e 100644 --- a/exports/components/combobox.brief.txt +++ b/exports/components/combobox.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — combobox -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/combobox.json spec: spec/components/combobox.md site: https://j3w1.github.io/theme/reference/#c-combobox maturity: stable priority: R1 diff --git a/exports/components/combobox.json b/exports/components/combobox.json index 853b48f08..75398e378 100644 --- a/exports/components/combobox.json +++ b/exports/components/combobox.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "combobox", "family": "forms-advanced", "maturity": "stable", diff --git a/exports/components/command-palette.brief.txt b/exports/components/command-palette.brief.txt index cf506f177..3b54fab8b 100644 --- a/exports/components/command-palette.brief.txt +++ b/exports/components/command-palette.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — command-palette -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/command-palette.json spec: spec/components/command-palette.md site: https://j3w1.github.io/theme/reference/#c-command-palette maturity: stable priority: R2 diff --git a/exports/components/command-palette.json b/exports/components/command-palette.json index 43037bcb9..9296007b6 100644 --- a/exports/components/command-palette.json +++ b/exports/components/command-palette.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "command-palette", "family": "navigation", "maturity": "stable", diff --git a/exports/components/compact-dashboard.brief.txt b/exports/components/compact-dashboard.brief.txt index 01ab15244..ac0fb2f92 100644 --- a/exports/components/compact-dashboard.brief.txt +++ b/exports/components/compact-dashboard.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — compact-dashboard -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/compact-dashboard.json spec: spec/components/compact-dashboard.md site: https://j3w1.github.io/theme/reference/#c-compact-dashboard maturity: stable priority: R2 diff --git a/exports/components/compact-dashboard.json b/exports/components/compact-dashboard.json index a4a93d2d4..1f4d14721 100644 --- a/exports/components/compact-dashboard.json +++ b/exports/components/compact-dashboard.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "compact-dashboard", "family": "composed", "maturity": "stable", diff --git a/exports/components/data-table.brief.txt b/exports/components/data-table.brief.txt index c5f721588..137666e43 100644 --- a/exports/components/data-table.brief.txt +++ b/exports/components/data-table.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — data-table -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/data-table.json spec: spec/components/data-table.md site: https://j3w1.github.io/theme/reference/#c-data-table maturity: stable priority: R1 diff --git a/exports/components/data-table.json b/exports/components/data-table.json index cfb7375ef..f84349c46 100644 --- a/exports/components/data-table.json +++ b/exports/components/data-table.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "data-table", "family": "display", "maturity": "stable", diff --git a/exports/components/date-picker.brief.txt b/exports/components/date-picker.brief.txt index 63718618b..b138288e4 100644 --- a/exports/components/date-picker.brief.txt +++ b/exports/components/date-picker.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — date-picker -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/date-picker.json spec: spec/components/date-picker.md site: https://j3w1.github.io/theme/reference/#c-date-picker maturity: stable priority: R1 diff --git a/exports/components/date-picker.json b/exports/components/date-picker.json index 66f885ab6..435aea5c7 100644 --- a/exports/components/date-picker.json +++ b/exports/components/date-picker.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "date-picker", "family": "forms-advanced", "maturity": "stable", diff --git a/exports/components/description-list.brief.txt b/exports/components/description-list.brief.txt index a9777ac63..ec2c16b61 100644 --- a/exports/components/description-list.brief.txt +++ b/exports/components/description-list.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — description-list -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/description-list.json spec: spec/components/description-list.md site: https://j3w1.github.io/theme/reference/#c-description-list maturity: stable priority: R2 diff --git a/exports/components/description-list.json b/exports/components/description-list.json index 3cfa86b3f..41625feaa 100644 --- a/exports/components/description-list.json +++ b/exports/components/description-list.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "description-list", "family": "display", "maturity": "stable", diff --git a/exports/components/diagnostics.brief.txt b/exports/components/diagnostics.brief.txt index dd3f4848c..f5fafa99b 100644 --- a/exports/components/diagnostics.brief.txt +++ b/exports/components/diagnostics.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — diagnostics -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/diagnostics.json spec: spec/components/diagnostics.md site: https://j3w1.github.io/theme/reference/#c-diagnostics maturity: stable priority: R1 diff --git a/exports/components/diagnostics.json b/exports/components/diagnostics.json index ad8d2b2a6..6ba9e0fe1 100644 --- a/exports/components/diagnostics.json +++ b/exports/components/diagnostics.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "diagnostics", "family": "developer", "maturity": "stable", diff --git a/exports/components/dialog.brief.txt b/exports/components/dialog.brief.txt index f094849ec..b33fb100b 100644 --- a/exports/components/dialog.brief.txt +++ b/exports/components/dialog.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — dialog -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/dialog.json spec: spec/components/dialog.md site: https://j3w1.github.io/theme/reference/#c-dialog maturity: stable priority: R1 diff --git a/exports/components/dialog.json b/exports/components/dialog.json index e08cffa9e..59af8ad13 100644 --- a/exports/components/dialog.json +++ b/exports/components/dialog.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "dialog", "family": "feedback", "maturity": "stable", diff --git a/exports/components/diff-view.brief.txt b/exports/components/diff-view.brief.txt index 81907a036..5cf891f80 100644 --- a/exports/components/diff-view.brief.txt +++ b/exports/components/diff-view.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — diff-view -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/diff-view.json spec: spec/components/diff-view.md site: https://j3w1.github.io/theme/reference/#c-diff-view maturity: stable priority: R1 diff --git a/exports/components/diff-view.json b/exports/components/diff-view.json index b6b685ce3..d7a2f1b34 100644 --- a/exports/components/diff-view.json +++ b/exports/components/diff-view.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "diff-view", "family": "developer", "maturity": "stable", diff --git a/exports/components/disclosure.brief.txt b/exports/components/disclosure.brief.txt index 3e9286645..2c0165379 100644 --- a/exports/components/disclosure.brief.txt +++ b/exports/components/disclosure.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — disclosure -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/disclosure.json spec: spec/components/disclosure.md site: https://j3w1.github.io/theme/reference/#c-disclosure maturity: stable priority: R2 diff --git a/exports/components/disclosure.json b/exports/components/disclosure.json index b283693d6..b98d6d441 100644 --- a/exports/components/disclosure.json +++ b/exports/components/disclosure.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "disclosure", "family": "navigation", "maturity": "stable", diff --git a/exports/components/drawer.brief.txt b/exports/components/drawer.brief.txt index 2db724982..8a2d80037 100644 --- a/exports/components/drawer.brief.txt +++ b/exports/components/drawer.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — drawer -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/drawer.json spec: spec/components/drawer.md site: https://j3w1.github.io/theme/reference/#c-drawer maturity: stable priority: R1 diff --git a/exports/components/drawer.json b/exports/components/drawer.json index 2da96c96d..2f845a850 100644 --- a/exports/components/drawer.json +++ b/exports/components/drawer.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "drawer", "family": "feedback", "maturity": "stable", diff --git a/exports/components/editor-search.brief.txt b/exports/components/editor-search.brief.txt index be02293cd..4ba5d35b1 100644 --- a/exports/components/editor-search.brief.txt +++ b/exports/components/editor-search.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — editor-search -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/editor-search.json spec: spec/components/editor-search.md site: https://j3w1.github.io/theme/reference/#c-editor-search maturity: stable priority: R2 diff --git a/exports/components/editor-search.json b/exports/components/editor-search.json index c20a77318..70d6c2d47 100644 --- a/exports/components/editor-search.json +++ b/exports/components/editor-search.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "editor-search", "family": "developer", "maturity": "stable", diff --git a/exports/components/empty-state.brief.txt b/exports/components/empty-state.brief.txt index 7e4c1861a..c11798241 100644 --- a/exports/components/empty-state.brief.txt +++ b/exports/components/empty-state.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — empty-state -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/empty-state.json spec: spec/components/empty-state.md site: https://j3w1.github.io/theme/reference/#c-empty-state maturity: stable priority: R1 diff --git a/exports/components/empty-state.json b/exports/components/empty-state.json index 73066fccb..06075bb9e 100644 --- a/exports/components/empty-state.json +++ b/exports/components/empty-state.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "empty-state", "family": "feedback", "maturity": "stable", diff --git a/exports/components/error-state.brief.txt b/exports/components/error-state.brief.txt index 6342f010b..27f5d6791 100644 --- a/exports/components/error-state.brief.txt +++ b/exports/components/error-state.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — error-state -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/error-state.json spec: spec/components/error-state.md site: https://j3w1.github.io/theme/reference/#c-error-state maturity: stable priority: R2 diff --git a/exports/components/error-state.json b/exports/components/error-state.json index d3e8aa202..de1e89b10 100644 --- a/exports/components/error-state.json +++ b/exports/components/error-state.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "error-state", "family": "feedback", "maturity": "stable", diff --git a/exports/components/field.brief.txt b/exports/components/field.brief.txt index ce6583a2b..0fd437f02 100644 --- a/exports/components/field.brief.txt +++ b/exports/components/field.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — field -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/field.json spec: spec/components/field.md site: https://j3w1.github.io/theme/reference/#c-field maturity: stable priority: R1 diff --git a/exports/components/field.json b/exports/components/field.json index 422db0182..d1a572914 100644 --- a/exports/components/field.json +++ b/exports/components/field.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "field", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/fieldset.brief.txt b/exports/components/fieldset.brief.txt index 9905df349..edc8c79db 100644 --- a/exports/components/fieldset.brief.txt +++ b/exports/components/fieldset.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — fieldset -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/fieldset.json spec: spec/components/fieldset.md site: https://j3w1.github.io/theme/reference/#c-fieldset maturity: stable priority: R1 diff --git a/exports/components/fieldset.json b/exports/components/fieldset.json index e4207c56e..0a37d71ed 100644 --- a/exports/components/fieldset.json +++ b/exports/components/fieldset.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "fieldset", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/file-browser.brief.txt b/exports/components/file-browser.brief.txt index a3ba5cd9b..eab9060b3 100644 --- a/exports/components/file-browser.brief.txt +++ b/exports/components/file-browser.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — file-browser -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/file-browser.json spec: spec/components/file-browser.md site: https://j3w1.github.io/theme/reference/#c-file-browser maturity: stable priority: R2 diff --git a/exports/components/file-browser.json b/exports/components/file-browser.json index 3a2728dc5..d3a073ae9 100644 --- a/exports/components/file-browser.json +++ b/exports/components/file-browser.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "file-browser", "family": "composed", "maturity": "stable", diff --git a/exports/components/file-input.brief.txt b/exports/components/file-input.brief.txt index b08d47350..572ab95cf 100644 --- a/exports/components/file-input.brief.txt +++ b/exports/components/file-input.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — file-input -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/file-input.json spec: spec/components/file-input.md site: https://j3w1.github.io/theme/reference/#c-file-input maturity: stable priority: R1 diff --git a/exports/components/file-input.json b/exports/components/file-input.json index ef0ebdf9d..7c61f2ecb 100644 --- a/exports/components/file-input.json +++ b/exports/components/file-input.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "file-input", "family": "forms-advanced", "maturity": "stable", diff --git a/exports/components/filterable-table.brief.txt b/exports/components/filterable-table.brief.txt index 7fcc1a081..074ffdac3 100644 --- a/exports/components/filterable-table.brief.txt +++ b/exports/components/filterable-table.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — filterable-table -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/filterable-table.json spec: spec/components/filterable-table.md site: https://j3w1.github.io/theme/reference/#c-filterable-table maturity: stable priority: R1 diff --git a/exports/components/filterable-table.json b/exports/components/filterable-table.json index 4f4972eb9..addce53fb 100644 --- a/exports/components/filterable-table.json +++ b/exports/components/filterable-table.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "filterable-table", "family": "composed", "maturity": "stable", diff --git a/exports/components/form-builder.brief.txt b/exports/components/form-builder.brief.txt index a09e3da9d..24af6f5b6 100644 --- a/exports/components/form-builder.brief.txt +++ b/exports/components/form-builder.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — form-builder -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/form-builder.json spec: spec/components/form-builder.md site: https://j3w1.github.io/theme/reference/#c-form-builder maturity: draft priority: L diff --git a/exports/components/form-builder.json b/exports/components/form-builder.json index 05f599f70..0875f0a4f 100644 --- a/exports/components/form-builder.json +++ b/exports/components/form-builder.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "form-builder", "family": "forms-advanced", "maturity": "draft", diff --git a/exports/components/i3-window-frame.brief.txt b/exports/components/i3-window-frame.brief.txt index ee095d8ad..5c51fcceb 100644 --- a/exports/components/i3-window-frame.brief.txt +++ b/exports/components/i3-window-frame.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — i3-window-frame -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/i3-window-frame.json spec: spec/components/i3-window-frame.md site: https://j3w1.github.io/theme/reference/#c-i3-window-frame maturity: stable priority: R1 diff --git a/exports/components/i3-window-frame.json b/exports/components/i3-window-frame.json index 5f97c9ab6..c030660c9 100644 --- a/exports/components/i3-window-frame.json +++ b/exports/components/i3-window-frame.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "i3-window-frame", "family": "composed", "maturity": "stable", diff --git a/exports/components/icon-button.brief.txt b/exports/components/icon-button.brief.txt index be5237830..f9215568b 100644 --- a/exports/components/icon-button.brief.txt +++ b/exports/components/icon-button.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — icon-button -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/icon-button.json spec: spec/components/icon-button.md site: https://j3w1.github.io/theme/reference/#c-icon-button maturity: stable priority: R1 diff --git a/exports/components/icon-button.json b/exports/components/icon-button.json index a531d358a..840c93885 100644 --- a/exports/components/icon-button.json +++ b/exports/components/icon-button.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "icon-button", "family": "actions", "maturity": "stable", diff --git a/exports/components/kbd.brief.txt b/exports/components/kbd.brief.txt index 0072c1b55..23fb14042 100644 --- a/exports/components/kbd.brief.txt +++ b/exports/components/kbd.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — kbd -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/kbd.json spec: spec/components/kbd.md site: https://j3w1.github.io/theme/reference/#c-kbd maturity: stable priority: R2 diff --git a/exports/components/kbd.json b/exports/components/kbd.json index f95f82cec..d56b6d41a 100644 --- a/exports/components/kbd.json +++ b/exports/components/kbd.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "kbd", "family": "display", "maturity": "stable", diff --git a/exports/components/link.brief.txt b/exports/components/link.brief.txt index 4e57e7967..57356c788 100644 --- a/exports/components/link.brief.txt +++ b/exports/components/link.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — link -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/link.json spec: spec/components/link.md site: https://j3w1.github.io/theme/reference/#c-link maturity: stable priority: R1 diff --git a/exports/components/link.json b/exports/components/link.json index 4432d9d60..b3afc794d 100644 --- a/exports/components/link.json +++ b/exports/components/link.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "link", "family": "actions", "maturity": "stable", diff --git a/exports/components/list.brief.txt b/exports/components/list.brief.txt index 7d2bbe884..37f52a1c6 100644 --- a/exports/components/list.brief.txt +++ b/exports/components/list.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — list -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/list.json spec: spec/components/list.md site: https://j3w1.github.io/theme/reference/#c-list maturity: stable priority: R1 diff --git a/exports/components/list.json b/exports/components/list.json index ee36d4e78..fbb3e14cd 100644 --- a/exports/components/list.json +++ b/exports/components/list.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "list", "family": "display", "maturity": "stable", diff --git a/exports/components/loading-indicator.brief.txt b/exports/components/loading-indicator.brief.txt index bd7245285..8794990bc 100644 --- a/exports/components/loading-indicator.brief.txt +++ b/exports/components/loading-indicator.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — loading-indicator -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/loading-indicator.json spec: spec/components/loading-indicator.md site: https://j3w1.github.io/theme/reference/#c-loading-indicator maturity: stable priority: R1 diff --git a/exports/components/loading-indicator.json b/exports/components/loading-indicator.json index 4fd9e2a5c..c17ccd4e4 100644 --- a/exports/components/loading-indicator.json +++ b/exports/components/loading-indicator.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "loading-indicator", "family": "feedback", "maturity": "stable", diff --git a/exports/components/menu.brief.txt b/exports/components/menu.brief.txt index 655b159fe..1a5307787 100644 --- a/exports/components/menu.brief.txt +++ b/exports/components/menu.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — menu -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/menu.json spec: spec/components/menu.md site: https://j3w1.github.io/theme/reference/#c-menu maturity: stable priority: R1 diff --git a/exports/components/menu.json b/exports/components/menu.json index 01aa7ef1d..442a4968c 100644 --- a/exports/components/menu.json +++ b/exports/components/menu.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "menu", "family": "navigation", "maturity": "stable", diff --git a/exports/components/multiselect.brief.txt b/exports/components/multiselect.brief.txt index 058bc1f22..805c2e398 100644 --- a/exports/components/multiselect.brief.txt +++ b/exports/components/multiselect.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — multiselect -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/multiselect.json spec: spec/components/multiselect.md site: https://j3w1.github.io/theme/reference/#c-multiselect maturity: stable priority: R2 diff --git a/exports/components/multiselect.json b/exports/components/multiselect.json index 978d31ad5..c19f765f4 100644 --- a/exports/components/multiselect.json +++ b/exports/components/multiselect.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "multiselect", "family": "forms-advanced", "maturity": "stable", diff --git a/exports/components/number-field.brief.txt b/exports/components/number-field.brief.txt index d3d67a5df..e6b8937f0 100644 --- a/exports/components/number-field.brief.txt +++ b/exports/components/number-field.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — number-field -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/number-field.json spec: spec/components/number-field.md site: https://j3w1.github.io/theme/reference/#c-number-field maturity: stable priority: R1 diff --git a/exports/components/number-field.json b/exports/components/number-field.json index bfe51d25a..fe690652d 100644 --- a/exports/components/number-field.json +++ b/exports/components/number-field.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "number-field", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/pagination.brief.txt b/exports/components/pagination.brief.txt index 8c5ec2f23..14886d414 100644 --- a/exports/components/pagination.brief.txt +++ b/exports/components/pagination.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — pagination -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/pagination.json spec: spec/components/pagination.md site: https://j3w1.github.io/theme/reference/#c-pagination maturity: stable priority: R1 diff --git a/exports/components/pagination.json b/exports/components/pagination.json index 597aae01a..b9f8696fb 100644 --- a/exports/components/pagination.json +++ b/exports/components/pagination.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "pagination", "family": "navigation", "maturity": "stable", diff --git a/exports/components/popover.brief.txt b/exports/components/popover.brief.txt index b5a526b0f..7595c81e8 100644 --- a/exports/components/popover.brief.txt +++ b/exports/components/popover.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — popover -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/popover.json spec: spec/components/popover.md site: https://j3w1.github.io/theme/reference/#c-popover maturity: stable priority: R2 diff --git a/exports/components/popover.json b/exports/components/popover.json index f675faca6..9009dc0c8 100644 --- a/exports/components/popover.json +++ b/exports/components/popover.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "popover", "family": "feedback", "maturity": "stable", diff --git a/exports/components/progress.brief.txt b/exports/components/progress.brief.txt index 87490fe0e..55bbb3294 100644 --- a/exports/components/progress.brief.txt +++ b/exports/components/progress.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — progress -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/progress.json spec: spec/components/progress.md site: https://j3w1.github.io/theme/reference/#c-progress maturity: stable priority: R1 diff --git a/exports/components/progress.json b/exports/components/progress.json index 590a3996a..3451e3b67 100644 --- a/exports/components/progress.json +++ b/exports/components/progress.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "progress", "family": "feedback", "maturity": "stable", diff --git a/exports/components/radio-group.brief.txt b/exports/components/radio-group.brief.txt index 3fc2f6c4d..52c0b1ca1 100644 --- a/exports/components/radio-group.brief.txt +++ b/exports/components/radio-group.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — radio-group -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/radio-group.json spec: spec/components/radio-group.md site: https://j3w1.github.io/theme/reference/#c-radio-group maturity: stable priority: R1 diff --git a/exports/components/radio-group.json b/exports/components/radio-group.json index af3e3f65d..dfb208091 100644 --- a/exports/components/radio-group.json +++ b/exports/components/radio-group.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "radio-group", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/range.brief.txt b/exports/components/range.brief.txt index 9c3e52baa..f05fd98ff 100644 --- a/exports/components/range.brief.txt +++ b/exports/components/range.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — range -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/range.json spec: spec/components/range.md site: https://j3w1.github.io/theme/reference/#c-range maturity: stable priority: R2 diff --git a/exports/components/range.json b/exports/components/range.json index b29548f1a..7c395d9c6 100644 --- a/exports/components/range.json +++ b/exports/components/range.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "range", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/repeater.brief.txt b/exports/components/repeater.brief.txt index c1f87e376..049dfc73c 100644 --- a/exports/components/repeater.brief.txt +++ b/exports/components/repeater.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — repeater -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/repeater.json spec: spec/components/repeater.md site: https://j3w1.github.io/theme/reference/#c-repeater maturity: stable priority: R2 diff --git a/exports/components/repeater.json b/exports/components/repeater.json index 92632a4bb..c6225ff54 100644 --- a/exports/components/repeater.json +++ b/exports/components/repeater.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "repeater", "family": "forms-advanced", "maturity": "stable", diff --git a/exports/components/search-field.brief.txt b/exports/components/search-field.brief.txt index ddd067bb1..9c5092236 100644 --- a/exports/components/search-field.brief.txt +++ b/exports/components/search-field.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — search-field -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/search-field.json spec: spec/components/search-field.md site: https://j3w1.github.io/theme/reference/#c-search-field maturity: stable priority: R1 diff --git a/exports/components/search-field.json b/exports/components/search-field.json index 4ce060cc1..604ee375a 100644 --- a/exports/components/search-field.json +++ b/exports/components/search-field.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "search-field", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/segmented-control.brief.txt b/exports/components/segmented-control.brief.txt index b296fd3fa..81bef8efb 100644 --- a/exports/components/segmented-control.brief.txt +++ b/exports/components/segmented-control.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — segmented-control -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/segmented-control.json spec: spec/components/segmented-control.md site: https://j3w1.github.io/theme/reference/#c-segmented-control maturity: stable priority: R2 diff --git a/exports/components/segmented-control.json b/exports/components/segmented-control.json index e08fc9601..ab01ed966 100644 --- a/exports/components/segmented-control.json +++ b/exports/components/segmented-control.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "segmented-control", "family": "actions", "maturity": "stable", diff --git a/exports/components/select.brief.txt b/exports/components/select.brief.txt index 66903a2d0..b9fad34f2 100644 --- a/exports/components/select.brief.txt +++ b/exports/components/select.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — select -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/select.json spec: spec/components/select.md site: https://j3w1.github.io/theme/reference/#c-select maturity: stable priority: R1 diff --git a/exports/components/select.json b/exports/components/select.json index 715260847..18463c9ec 100644 --- a/exports/components/select.json +++ b/exports/components/select.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "select", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/settings-panel.brief.txt b/exports/components/settings-panel.brief.txt index 7d1d07bf5..db86b268e 100644 --- a/exports/components/settings-panel.brief.txt +++ b/exports/components/settings-panel.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — settings-panel -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/settings-panel.json spec: spec/components/settings-panel.md site: https://j3w1.github.io/theme/reference/#c-settings-panel maturity: stable priority: R1 diff --git a/exports/components/settings-panel.json b/exports/components/settings-panel.json index 0d365f760..296529fb9 100644 --- a/exports/components/settings-panel.json +++ b/exports/components/settings-panel.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "settings-panel", "family": "composed", "maturity": "stable", diff --git a/exports/components/sidebar-nav.brief.txt b/exports/components/sidebar-nav.brief.txt index 1f9397eac..0a6ab12a6 100644 --- a/exports/components/sidebar-nav.brief.txt +++ b/exports/components/sidebar-nav.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — sidebar-nav -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/sidebar-nav.json spec: spec/components/sidebar-nav.md site: https://j3w1.github.io/theme/reference/#c-sidebar-nav maturity: stable priority: R1 diff --git a/exports/components/sidebar-nav.json b/exports/components/sidebar-nav.json index fb4dad9bf..b3e994688 100644 --- a/exports/components/sidebar-nav.json +++ b/exports/components/sidebar-nav.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "sidebar-nav", "family": "navigation", "maturity": "stable", diff --git a/exports/components/skeleton.brief.txt b/exports/components/skeleton.brief.txt index 9cc80ee0c..16b297dca 100644 --- a/exports/components/skeleton.brief.txt +++ b/exports/components/skeleton.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — skeleton -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/skeleton.json spec: spec/components/skeleton.md site: https://j3w1.github.io/theme/reference/#c-skeleton maturity: stable priority: R2 diff --git a/exports/components/skeleton.json b/exports/components/skeleton.json index e9101ab3e..ee4ef28c9 100644 --- a/exports/components/skeleton.json +++ b/exports/components/skeleton.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "skeleton", "family": "feedback", "maturity": "stable", diff --git a/exports/components/skip-link.brief.txt b/exports/components/skip-link.brief.txt index 14dadba49..1d6cb8f14 100644 --- a/exports/components/skip-link.brief.txt +++ b/exports/components/skip-link.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — skip-link -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/skip-link.json spec: spec/components/skip-link.md site: https://j3w1.github.io/theme/reference/#c-skip-link maturity: stable priority: R1 diff --git a/exports/components/skip-link.json b/exports/components/skip-link.json index eb5f58930..081d99298 100644 --- a/exports/components/skip-link.json +++ b/exports/components/skip-link.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "skip-link", "family": "navigation", "maturity": "stable", diff --git a/exports/components/switch.brief.txt b/exports/components/switch.brief.txt index aa4ed8643..e377f6fd2 100644 --- a/exports/components/switch.brief.txt +++ b/exports/components/switch.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — switch -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/switch.json spec: spec/components/switch.md site: https://j3w1.github.io/theme/reference/#c-switch maturity: stable priority: R1 diff --git a/exports/components/switch.json b/exports/components/switch.json index 3e5bb8974..256e5fd9c 100644 --- a/exports/components/switch.json +++ b/exports/components/switch.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "switch", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/table.brief.txt b/exports/components/table.brief.txt index 8bd041232..cefb158d1 100644 --- a/exports/components/table.brief.txt +++ b/exports/components/table.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — table -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/table.json spec: spec/components/table.md site: https://j3w1.github.io/theme/reference/#c-table maturity: stable priority: R1 diff --git a/exports/components/table.json b/exports/components/table.json index a4ff2f9d6..2d7c4baaf 100644 --- a/exports/components/table.json +++ b/exports/components/table.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "table", "family": "display", "maturity": "stable", diff --git a/exports/components/tabs.brief.txt b/exports/components/tabs.brief.txt index c7d3da52d..87b81b884 100644 --- a/exports/components/tabs.brief.txt +++ b/exports/components/tabs.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — tabs -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/tabs.json spec: spec/components/tabs.md site: https://j3w1.github.io/theme/reference/#c-tabs maturity: stable priority: R1 diff --git a/exports/components/tabs.json b/exports/components/tabs.json index 865b1b258..aba1c33e2 100644 --- a/exports/components/tabs.json +++ b/exports/components/tabs.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "tabs", "family": "navigation", "maturity": "stable", diff --git a/exports/components/terminal.brief.txt b/exports/components/terminal.brief.txt index 35baa7144..ec43247d6 100644 --- a/exports/components/terminal.brief.txt +++ b/exports/components/terminal.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — terminal -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/terminal.json spec: spec/components/terminal.md site: https://j3w1.github.io/theme/reference/#c-terminal maturity: stable priority: R1 diff --git a/exports/components/terminal.json b/exports/components/terminal.json index f7e9bba1a..960592e7e 100644 --- a/exports/components/terminal.json +++ b/exports/components/terminal.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "terminal", "family": "developer", "maturity": "stable", diff --git a/exports/components/text-field.brief.txt b/exports/components/text-field.brief.txt index 00531521e..ceb290d8d 100644 --- a/exports/components/text-field.brief.txt +++ b/exports/components/text-field.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — text-field -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/text-field.json spec: spec/components/text-field.md site: https://j3w1.github.io/theme/reference/#c-text-field maturity: stable priority: R1 diff --git a/exports/components/text-field.json b/exports/components/text-field.json index 719e1ea0c..9760fb66c 100644 --- a/exports/components/text-field.json +++ b/exports/components/text-field.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "text-field", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/textarea.brief.txt b/exports/components/textarea.brief.txt index 1da02c43d..a7795e8da 100644 --- a/exports/components/textarea.brief.txt +++ b/exports/components/textarea.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — textarea -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/textarea.json spec: spec/components/textarea.md site: https://j3w1.github.io/theme/reference/#c-textarea maturity: stable priority: R1 diff --git a/exports/components/textarea.json b/exports/components/textarea.json index e28cba603..63d57598a 100644 --- a/exports/components/textarea.json +++ b/exports/components/textarea.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "textarea", "family": "forms-basic", "maturity": "stable", diff --git a/exports/components/time-picker.brief.txt b/exports/components/time-picker.brief.txt index e797bbf59..bdf06f015 100644 --- a/exports/components/time-picker.brief.txt +++ b/exports/components/time-picker.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — time-picker -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/time-picker.json spec: spec/components/time-picker.md site: https://j3w1.github.io/theme/reference/#c-time-picker maturity: stable priority: R1 diff --git a/exports/components/time-picker.json b/exports/components/time-picker.json index 9621c6b91..c4f67245a 100644 --- a/exports/components/time-picker.json +++ b/exports/components/time-picker.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "time-picker", "family": "forms-advanced", "maturity": "stable", diff --git a/exports/components/timeline.brief.txt b/exports/components/timeline.brief.txt index b7605dabb..18b0bff9d 100644 --- a/exports/components/timeline.brief.txt +++ b/exports/components/timeline.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — timeline -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/timeline.json spec: spec/components/timeline.md site: https://j3w1.github.io/theme/reference/#c-timeline maturity: stable priority: R2 diff --git a/exports/components/timeline.json b/exports/components/timeline.json index 65d07dcf2..62bb66ba8 100644 --- a/exports/components/timeline.json +++ b/exports/components/timeline.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "timeline", "family": "display", "maturity": "stable", diff --git a/exports/components/toast.brief.txt b/exports/components/toast.brief.txt index 5a1ea4945..b9139eac0 100644 --- a/exports/components/toast.brief.txt +++ b/exports/components/toast.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — toast -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/toast.json spec: spec/components/toast.md site: https://j3w1.github.io/theme/reference/#c-toast maturity: stable priority: R1 diff --git a/exports/components/toast.json b/exports/components/toast.json index e628b3eb1..6c6af299a 100644 --- a/exports/components/toast.json +++ b/exports/components/toast.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "toast", "family": "feedback", "maturity": "stable", diff --git a/exports/components/toolbar.brief.txt b/exports/components/toolbar.brief.txt index c2a1b7df1..457d47c3c 100644 --- a/exports/components/toolbar.brief.txt +++ b/exports/components/toolbar.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — toolbar -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/toolbar.json spec: spec/components/toolbar.md site: https://j3w1.github.io/theme/reference/#c-toolbar maturity: stable priority: R1 diff --git a/exports/components/toolbar.json b/exports/components/toolbar.json index 4ce267549..0bc86e21d 100644 --- a/exports/components/toolbar.json +++ b/exports/components/toolbar.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "toolbar", "family": "navigation", "maturity": "stable", diff --git a/exports/components/tooltip.brief.txt b/exports/components/tooltip.brief.txt index 37f2c931a..8e645b723 100644 --- a/exports/components/tooltip.brief.txt +++ b/exports/components/tooltip.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — tooltip -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/tooltip.json spec: spec/components/tooltip.md site: https://j3w1.github.io/theme/reference/#c-tooltip maturity: stable priority: R1 diff --git a/exports/components/tooltip.json b/exports/components/tooltip.json index 0037674f6..d8b337596 100644 --- a/exports/components/tooltip.json +++ b/exports/components/tooltip.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "tooltip", "family": "feedback", "maturity": "stable", diff --git a/exports/components/tree.brief.txt b/exports/components/tree.brief.txt index 63e6400c7..0ea1c1d1f 100644 --- a/exports/components/tree.brief.txt +++ b/exports/components/tree.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — tree -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/tree.json spec: spec/components/tree.md site: https://j3w1.github.io/theme/reference/#c-tree maturity: stable priority: R2 diff --git a/exports/components/tree.json b/exports/components/tree.json index f84767084..1bcfdec76 100644 --- a/exports/components/tree.json +++ b/exports/components/tree.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "tree", "family": "navigation", "maturity": "stable", diff --git a/exports/components/wizard.brief.txt b/exports/components/wizard.brief.txt index 2b0a620d2..cba0b3cb7 100644 --- a/exports/components/wizard.brief.txt +++ b/exports/components/wizard.brief.txt @@ -1,5 +1,5 @@ j3w1/theme implementation brief — wizard -theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc= +theme: j3w1-theme 4.0.0 profile: default sourceDigest: sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg= pin: https://raw.githubusercontent.com/j3w1/theme/v4.0.0/exports/components/wizard.json spec: spec/components/wizard.md site: https://j3w1.github.io/theme/reference/#c-wizard maturity: stable priority: R1 diff --git a/exports/components/wizard.json b/exports/components/wizard.json index 54bce18a8..7e13b51e0 100644 --- a/exports/components/wizard.json +++ b/exports/components/wizard.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "wizard", "family": "forms-advanced", "maturity": "stable", diff --git a/exports/digests.json b/exports/digests.json index d2131d960..3b852eeea 100644 --- a/exports/digests.json +++ b/exports/digests.json @@ -4,148 +4,148 @@ "version": "4.0.0", "algorithm": "sha256 over the file bytes with LF line endings, base64", "files": { - "exports/components/admin-form.brief.txt": "sha256-NAAwvQu4a8OjZrJys+KOZEgYU00bKuc1Fapl7IqW4mM=", - "exports/components/admin-form.json": "sha256-cMCzZ7Y6R5vDQhUKroYjVSLFkJHU3Gli08YeWYYWjMc=", - "exports/components/alert.brief.txt": "sha256-eQwb0CZfTNRQaaQFDNKn3G49wlkgo26nvHx8KmyZgk0=", - "exports/components/alert.json": "sha256-SDyyVlrQ4zCsh1k9d6euBFC5H1XTIXNlwApLZ28huDs=", - "exports/components/avatar.brief.txt": "sha256-yb2E1WYCMFgBlOcQbvmepU3c5w6mhHwH+8xdPbmAffw=", - "exports/components/avatar.json": "sha256-hUNV+6XmlXrHWL6Tic/4F2BgAkQDiplqsBttX7wyBVo=", - "exports/components/badge.brief.txt": "sha256-zTAyOHPX25UjjwGpRZsVWiSmS6faViq2VfnAzbsdobM=", - "exports/components/badge.json": "sha256-J6LygawZXw+gAxgIfKKMtKinZWxdT4fQ7JbeHvOxI7Q=", - "exports/components/breadcrumbs.brief.txt": "sha256-OuXoanuYkjAwlqhnU6De8YxF335ZGg6c/8IxknSz9ss=", - "exports/components/breadcrumbs.json": "sha256-ZEltkBqhykUx1c98sp1AnzBLBOL38xfDyJvOTwm4Sh4=", - "exports/components/button-group.brief.txt": "sha256-CtMpbJZqC4+Bm8c7w5v6zNOkGV8nvpNRSVVkFdwWPf4=", - "exports/components/button-group.json": "sha256-Sq8vsc8jJEpMDIaHTq3UMiJ7LDvSiv5vmDoAuxQX7Wk=", - "exports/components/button.brief.txt": "sha256-X1uJkp22e9mSRPJEfasvID82Ad8Z0C3bErTrPO05CVU=", - "exports/components/button.json": "sha256-ZlEnd0u5yLcxzB1C8tOCxvA8w2H5K9kB6SkPgTufJuk=", - "exports/components/card.brief.txt": "sha256-I0soQzxkKl2Nixtd3Kt2pBtF8VNuVUTHGU5vqK5DfiY=", - "exports/components/card.json": "sha256-sjtZLyhgdgrEFnSySdcpLFbLyZkWKnIa1jsxlIVK71o=", - "exports/components/chart.brief.txt": "sha256-+kw0iLzQaOGGpsuLFKvCRCWOn1lIu6moXm/OT6Oplc4=", - "exports/components/chart.json": "sha256-BasdUdA3MzGo0Rmmrmj+E6bMOtudFa8Xxcdb51Nizp0=", - "exports/components/checkbox.brief.txt": "sha256-pLrJ+lzBro8KDitL8XF5XdRQuWy5oGNHrADg6NUwO98=", - "exports/components/checkbox.json": "sha256-lTwSQVmvHYgltg/LQk97oB/0JbAKuE3b4vjU8EE/mHk=", - "exports/components/chip.brief.txt": "sha256-heS1/C2lQhgqsukPT8EXAGRYFH62hv1OBRZPpMtgbEY=", - "exports/components/chip.json": "sha256-BfTPtwtzIh8BFij9jAuBYFOI1OOsIa/QqxGxoSvruBQ=", - "exports/components/code-editor.brief.txt": "sha256-0JevPIfQ08Byu1c5tM6j3Z7N4v4IBKELg697r3/fR6g=", - "exports/components/code-editor.json": "sha256-9LKz74FqUL7zWtnvvJ/AAzTZkLqpiZk6fmDkxJGzlgg=", - "exports/components/combobox.brief.txt": "sha256-Djz6nfunQW/lHucE3M1DGnpxcYNGhGltjM4l9wwnVKs=", - "exports/components/combobox.json": "sha256-slabxERChhxzMG1On6USB3ilVP2/GZ86qPGxrKtyd/I=", - "exports/components/command-palette.brief.txt": "sha256-P4i1HqelXuwSWLo+fJFbRaPbfULuvq3Z0xI6E1EdLjE=", - "exports/components/command-palette.json": "sha256-kjl20b57OaZaKaOyQYMLeCMiiJtqygpnPayE03RaF9E=", - "exports/components/compact-dashboard.brief.txt": "sha256-AzIJ/y+V4p4pK2jfVVJ5z4SDyPXpkwKTio2tyV36aKo=", - "exports/components/compact-dashboard.json": "sha256-mdvkqeJBaUpbi1OZalkU9nibADqwIXoBlEn7k1c9QK4=", - "exports/components/data-table.brief.txt": "sha256-FzuDtGOqf2PNIP4FAnQ2jtPo3JPZyQI5SHac3M2sI/o=", - "exports/components/data-table.json": "sha256-GtiL/MsfUQrKkEhOX2LBO39gDmHItEupAGUcxO9S7so=", - "exports/components/date-picker.brief.txt": "sha256-xV4lktbb0ewFh7lcEyjGeFoCCBez1VRg12YLrJd5lCg=", - "exports/components/date-picker.json": "sha256-I7/+SFQ5Etf2XhC1KC2zKnJoBuuUfQ+XBwSvzIIM9G4=", - "exports/components/description-list.brief.txt": "sha256-Fdhf8PR6Bbz9jLC8qNyZOFk3MdlA0GLnx8JHKuYqFtM=", - "exports/components/description-list.json": "sha256-TcAgWaXIqrh7GnyY4Fh1sxw18w3Z64obPXXecZjM9PA=", - "exports/components/diagnostics.brief.txt": "sha256-KZtrkyZnan2krY54/TJ3AFhBubQxOnYXMXOtQl1wkBU=", - "exports/components/diagnostics.json": "sha256-XEiEML9kKK1Sx0WE7ntiSRf1x/LsJV0WRD7Ld7KIRBI=", - "exports/components/dialog.brief.txt": "sha256-wZOaSsoMO/4ixbHN5K6nyF+qsoBIBjaX4bE5SUwM2c0=", - "exports/components/dialog.json": "sha256-iW1JIM20K7jbEJPsZT44sXsMWUbFYnoH8MKe+xSwKno=", - "exports/components/diff-view.brief.txt": "sha256-z5YKZZODTo+ZyUSOswS4nVk0oWh8Z7/3MrOXnYSsbUw=", - "exports/components/diff-view.json": "sha256-UV7sIl990iqjdYQ+70hGI5AnnZVgdnk2glZ2TGeMBh0=", - "exports/components/disclosure.brief.txt": "sha256-mKqWXDpZ62MPZq6jbXXtxuHOLyMiv3HAlDT/4U/l0E8=", - "exports/components/disclosure.json": "sha256-9XecJvyNgfoZEOW2s0oYxV0wASigN5AcdFQ5jSvLFl8=", - "exports/components/drawer.brief.txt": "sha256-DmoQYGx/ld4LQpTZ2oIJcp+iVwiJW/89AfH2tWRlwvQ=", - "exports/components/drawer.json": "sha256-UWZZjgftkOkdmmGie3aC6ygvdyubUx31slprKBMVXco=", - "exports/components/editor-search.brief.txt": "sha256-yrbH7rHPERVh+hwA304lqHZAUGDeQwDCUI2W4LZW5gM=", - "exports/components/editor-search.json": "sha256-9OA9zuYcg6E9odzsrjVymAg0bXpA/YrgHDPTF+ZX3fc=", - "exports/components/empty-state.brief.txt": "sha256-9lyNLRfUjcu65/vMMretZMciCRyZzq57dv4BSXlxd5A=", - "exports/components/empty-state.json": "sha256-9jQ+/tMzpDMWDn1FdHFsY5MvGelrQ7ChHrdJgDpPO2Y=", - "exports/components/error-state.brief.txt": "sha256-0peAl3UrEEaj5KcKcjHT3fnZ9qozHdJ2aUgpFj1A728=", - "exports/components/error-state.json": "sha256-vgS8frriX3mDe18TFJsu8qMJ5vGa8pSmryajo5TX8Z0=", - "exports/components/field.brief.txt": "sha256-RdC7dRp8BPZiQ8qQJlPC69gHGgmgB/kEeKy6c8zCmWI=", - "exports/components/field.json": "sha256-/mkJI+8jB6gTFIo3KiYT8xkFsr/YATG/S6dC68UXBL8=", - "exports/components/fieldset.brief.txt": "sha256-kUm5y+ZV2VUb0iW9ciZwBCOMRIs5gF0TMLF2SA2951Y=", - "exports/components/fieldset.json": "sha256-UwVGiS3NbUzuJsIir7uaYz0WnWsR6xBT7/qEBYIX8RI=", - "exports/components/file-browser.brief.txt": "sha256-f5cEc7dJEWxh+5Ekp+sCBL6myZTtmpF5tN9c4ClQdK4=", - "exports/components/file-browser.json": "sha256-5Zla/4ImfqmxvuIKDJDxEQodvH9GaqSc25g7SMLGyMs=", - "exports/components/file-input.brief.txt": "sha256-WJOZu5jgt5O42n6EfQ1pvYgO6queoeEe/85EjED/m/M=", - "exports/components/file-input.json": "sha256-2BPV00mPYWRZwpGSypAWLwmyzqBlF5/h2S4H5pq/2Qc=", - "exports/components/filterable-table.brief.txt": "sha256-UftlMM3WBBZZz+JieQuFR6ssvsZg6/+Zn+FRSSxatFM=", - "exports/components/filterable-table.json": "sha256-t59LtzesMFhdRKldod6ybMMKusCmRLNz4lbCOopPYrg=", - "exports/components/form-builder.brief.txt": "sha256-3tIVMSkQRa81Tj+YbXmv6bj02jjBPR+4A17NAv2EmO8=", - "exports/components/form-builder.json": "sha256-4mIniVSwqBN9xrQw+5U3yNtrlk/aRH8jZPKuY0aIcFo=", - "exports/components/i3-window-frame.brief.txt": "sha256-kDv+CEtJRryjxTwv1PnG48Cv8+gRciQc/tEfZpxam8E=", - "exports/components/i3-window-frame.json": "sha256-HE2yLQP/EeCfukaO9TmrjuntEfxBg45zTLfMTv8dV+w=", - "exports/components/icon-button.brief.txt": "sha256-o07kxhxYhgUsOhGfFHRoF+6W4kJMBNERyPe7lxSyIrc=", - "exports/components/icon-button.json": "sha256-sNwIKljbVPU+JhJSwXGW7HAJqD+603MQomnt9DXiGfg=", - "exports/components/kbd.brief.txt": "sha256-5Lm4w94KsxpfKR47Iv1/sAfRWFO5WGsdFgOwsa2vurE=", - "exports/components/kbd.json": "sha256-qtJdAYhDBzZPtmFspChfruWyiMDL9twSz9dLREQCMQw=", - "exports/components/link.brief.txt": "sha256-FE6d6A4591c35YAVb7659bY2GzDnq3M4DlhzXGH44Nw=", - "exports/components/link.json": "sha256-Ve/sgeCPW8kcWLJQRARNL0CZ6+8QnNZ3pfX5Yy2tjSA=", - "exports/components/list.brief.txt": "sha256-FPhPO7+5z5fR0JzqgVGz3iR8t3dm4IEnFiLv2ZZnrdE=", - "exports/components/list.json": "sha256-ayifS2PLlnD94AVUVt5LUutQj2M8RmG/kLVPtqTuAkY=", - "exports/components/loading-indicator.brief.txt": "sha256-vW2mZkV2Ms3YrQTdCW/OmMHnEnGZz0xnJVh7rnGXKow=", - "exports/components/loading-indicator.json": "sha256-shFLUs9MXfCP4POg3WBzqxyPjk47+79iE82UK5M1V6M=", - "exports/components/menu.brief.txt": "sha256-JnUcFs0FyTXUQe1vIy335Sm6uxRNkoW1OwY82LZsAe8=", - "exports/components/menu.json": "sha256-vxb+FTeoH6TkYXfE0DDg7xcAntQBy94waPLnLqUiB4Y=", - "exports/components/multiselect.brief.txt": "sha256-ttvBKdDsZT/jfCBRe1aqq6/r2pNdDG4PjSu2AFdEouM=", - "exports/components/multiselect.json": "sha256-UiDVzUHMqLI+ruP4XdGhBuhdbP+5baB4PPlvNWBrlw4=", - "exports/components/number-field.brief.txt": "sha256-1UHv+wezTtDaru3yAfHFU4NNUiwwrB0P1YjUbcmiB7U=", - "exports/components/number-field.json": "sha256-CYDT5nidQgoqOlXEDX8P4MMWaVY5gtgr0XoeBFYIFLY=", - "exports/components/pagination.brief.txt": "sha256-HS3XYgnqdUZRhJS3pV+/ONBPPKk/PP3UxB27JeKAC/M=", - "exports/components/pagination.json": "sha256-vFyBtSE4gjXCH2sQZbtvZNAlK2UZRRoX7ogz76srgG4=", - "exports/components/popover.brief.txt": "sha256-MX27nm2zjgLET/8TJVEsmg8L5ZCXcNjlhtHf5tjWORA=", - "exports/components/popover.json": "sha256-mTckWzUiz2rRahydiFa/ONiXepSRsdEbdYRvaJ92k54=", - "exports/components/progress.brief.txt": "sha256-3UWVDj7fnZU6Kg/Loq65nxUOeZ8Ic6EUIsxqSyUx/tI=", - "exports/components/progress.json": "sha256-DQMvp+PkVdptaRd9LjZ19GAiQVgMa0awWfpqeGfMV0o=", - "exports/components/radio-group.brief.txt": "sha256-SYwy36nlfY793FyEc+WJAiElXQ90F3uAzt9MZXkSW1w=", - "exports/components/radio-group.json": "sha256-Ybo2AlA1UgFQjRgOGq07P5lxGTsO4dP+D8wFo3c3qOU=", - "exports/components/range.brief.txt": "sha256-sgmKsutNV3KGyxLykARDuCuKvvKuETnV2nZEA4/x7jc=", - "exports/components/range.json": "sha256-WIF2ZWvwloqTUB+95IHl9aTeKIuaSxFCo/GK3oKxqPo=", - "exports/components/repeater.brief.txt": "sha256-jcLf1GCz7BjgJA+6Y4smUA6uMNLm1mn0Xx1ZdGLndrw=", - "exports/components/repeater.json": "sha256-YW1BZL3NCKzxpyHd/oX4fmkbNzwZIeDh5ImXEZuTlo4=", - "exports/components/search-field.brief.txt": "sha256-5l9Z7TJQTtMS/SNzhI7ccsyqrVJzduADbU/+8cml0sE=", - "exports/components/search-field.json": "sha256-gOrIeIfgFkPVcFjUBIrmT69tTA0ucPhyFpv9/9NLFNY=", - "exports/components/segmented-control.brief.txt": "sha256-3Ezt2/z1kXR8Ymb9XrNx41pCanGPnmpgSIj2DMOgLfY=", - "exports/components/segmented-control.json": "sha256-L4OU1sHlD4fDrmyShueCt1NH9/xM2b71QmPjDetz7Ys=", - "exports/components/select.brief.txt": "sha256-JvqyEwXcadpAK0nKrODCcE4Bfi8iOZzRbn4yzitdxH8=", - "exports/components/select.json": "sha256-yL+LqAY+oEKvdS7BUSSuv0a/z1RpMCc9DH2QhdgJ2JA=", - "exports/components/settings-panel.brief.txt": "sha256-u/BbvlwJJSZQEh7Scpv6qBahcFBzsvyamRL2VOH+CU8=", - "exports/components/settings-panel.json": "sha256-tZqQ8ue4o/6aX+gIHuAw7U7+KfnO1KR+5b/KbqzidzQ=", - "exports/components/sidebar-nav.brief.txt": "sha256-gU1i20+fje2trojd9s/WFrSibLgh/FlJjW+qAwabC+A=", - "exports/components/sidebar-nav.json": "sha256-9M/9axST95VbeHYLN2FsITzn819QUURTBFzeFZ7w3eU=", - "exports/components/skeleton.brief.txt": "sha256-c4VRPqzIplCsFjwHJfHWUkPGOpsRFqZvOimogc4c73s=", - "exports/components/skeleton.json": "sha256-nM5bEtPXQluMleeSjUbHKRiLicp4xKgCshJTmeAE2TQ=", - "exports/components/skip-link.brief.txt": "sha256-ZAdAxqgDih7VyyLLxyZhmVQEfBzbV5sPUMO4E7tXe3I=", - "exports/components/skip-link.json": "sha256-wfbZNR4N5PUEmEQQ7ustM2ZZkw4F4OOgo2uylcTpQA0=", - "exports/components/switch.brief.txt": "sha256-vsKXPfBVqmo9e9x7NLSCUzNO0JlG4ax4zmXgfuM2+MA=", - "exports/components/switch.json": "sha256-+qLnIwiesw3n677GRmUYDQnLQyF7caiVcrQ43qWDqco=", - "exports/components/table.brief.txt": "sha256-JxG4wxtVl+ZA9AI90sTY4Ss9sX8yD1RCOeJoBDnXOI4=", - "exports/components/table.json": "sha256-Y/Q057zrmXpCMHe71Dk+XFeRwLNu0QkE+JJQMgvVwqs=", - "exports/components/tabs.brief.txt": "sha256-qkuyQOiim867uAODSkHU9y6Ni0ljKESlZnJUfZ5EMoo=", - "exports/components/tabs.json": "sha256-4uEKjf6Pcl6epXayzGG7Rb6szfuzs1JaRdBHjSWx28U=", - "exports/components/terminal.brief.txt": "sha256-hW1OOu6uEZ7hs7p94UMI/YMsQxSDZhLOb9L/3wLCLqs=", - "exports/components/terminal.json": "sha256-tmO1tF2j9qKaUBaCWKbLDbwc6RvjOeH/0QsD0HBHuyg=", - "exports/components/text-field.brief.txt": "sha256-GvPsSJHyRwsCbsoEK8FsX3tppSclBhJOFZVzP2sXQPM=", - "exports/components/text-field.json": "sha256-VP6pzK4iEpJYP1z956Hy0l1cuQwtWdF13P3pTkc7hcA=", - "exports/components/textarea.brief.txt": "sha256-bIsyJdMRbA1M2dtJ5FuYPSwZRDoKgIU8/hmr57tLfA8=", - "exports/components/textarea.json": "sha256-soblNoXVqwwH4841ku6gvoWpKHO9aZpUgbKZEdG0UcQ=", - "exports/components/time-picker.brief.txt": "sha256-4qP0ypJVbUPzaw6mrmW8A7FmngUAUuSD/6EenCEtfCY=", - "exports/components/time-picker.json": "sha256-aN3mUcCZMpc0H3B6cGSep2AEEUblbSurbtYZ+4c3voQ=", - "exports/components/timeline.brief.txt": "sha256-YbCNxIhNLizNi9SOPEw/6HvkWPawmiO1/vPLHWuIrFE=", - "exports/components/timeline.json": "sha256-Lrmu0cnFU8OjQU20yskQ+wUPDZIeKHNyt1QL57Hpq8o=", - "exports/components/toast.brief.txt": "sha256-/9Taj+JdvkvseZ44DHzzhmHan6/PBf10nmjSGiJLoyw=", - "exports/components/toast.json": "sha256-kEViFGDQbl6zuTVQWQAkR9uhmJChDetGK+VHu7R7/R4=", - "exports/components/toolbar.brief.txt": "sha256-FfqBUcrrYUYn/XD7rWQIET5om5HoDvKFuMMeg7qlG4Y=", - "exports/components/toolbar.json": "sha256-HR1PNVg/kEeT2sPQLICqlHh2Jpwgmjz2ISDyKNbOnfA=", - "exports/components/tooltip.brief.txt": "sha256-dyNwGTmWnZ/hhUIqb62CnzkylWFOGZp3JA+lzzs4Y2U=", - "exports/components/tooltip.json": "sha256-W6/wWbuwFVhv7bacwRrT7HpcYnZIO0lq7M4l6wET6/4=", - "exports/components/tree.brief.txt": "sha256-D7ZcIgsMm8R2iOjfe3GB+bRj5A35WljbutcciE8Pkm4=", - "exports/components/tree.json": "sha256-oUHCGdl1TrWMb2+5kqpcUru1cUe4isv3d+K5i8m9GBo=", - "exports/components/wizard.brief.txt": "sha256-gRybOypZwtIhzkE9KVcez6ROtQ5/lUJsWaTwPOIikaQ=", - "exports/components/wizard.json": "sha256-gm/Ax9KeTuUiV1krYNzcz6m57jB7lC4lRu3+W+QuZrA=", + "exports/components/admin-form.brief.txt": "sha256-x1LbnK9Qs9US7T2ksAChnEuCVER5YFHztzEk2oRBWPU=", + "exports/components/admin-form.json": "sha256-mAFCR+xrmkneq362ZIjiIzqy3MEHbSq7K2pZCBc8M8Q=", + "exports/components/alert.brief.txt": "sha256-Znivgui0UpXAdSwyJt21OtLbQaZDBCebc+9FRlIES4U=", + "exports/components/alert.json": "sha256-V2pNLjS0HP52R1DcXAD+e7y5gtxN4yVAqtBTlQaSEE4=", + "exports/components/avatar.brief.txt": "sha256-VgAWYMYtOFpwIUIPD8ANaj+cgecjOfYZoEV8QQpckGY=", + "exports/components/avatar.json": "sha256-RA3Pu+xDIHyOk6G8T+hi2EegLb60YZ6zcRzzj9pB9sg=", + "exports/components/badge.brief.txt": "sha256-9rTx90/tke7JhKBZZLrxpvIz1+TD/xoATZcB4NnTUp0=", + "exports/components/badge.json": "sha256-fNCf1ucOy924OTdhh8VzzOdeOhAJZDPXbVoWH49ozXk=", + "exports/components/breadcrumbs.brief.txt": "sha256-LR1qUcyh3GECwLvjaRR3o5bq9LNMr2XlNU7hdt0OvIo=", + "exports/components/breadcrumbs.json": "sha256-HKZovzFwthHtZitxchseA9wsKYZrCroZ6k/K7hH1Pek=", + "exports/components/button-group.brief.txt": "sha256-VL4cHIlGHq2YvE0doSuu3hBMOxYVCyAqzB4LNrYZ13s=", + "exports/components/button-group.json": "sha256-3k2A1T3AgcMWuPu/Mj9WOhaoyGyEOOgzptf4DdE1eBo=", + "exports/components/button.brief.txt": "sha256-TPUfUWUnEhlK7Me4b08Je1m+80u/k6DnlnFRdxHxYQk=", + "exports/components/button.json": "sha256-2i8SWTGy0yxV2DVp+BfPl74DDprhEO6TpTsKIOe5im8=", + "exports/components/card.brief.txt": "sha256-9OIQHMLWfReM+JwWXon52i49zJiZkwrkQglQ84O8E60=", + "exports/components/card.json": "sha256-JMAwjwR46Ljwut8wyVtBU9aTCR+Atca8nigCFF4owGo=", + "exports/components/chart.brief.txt": "sha256-VMSx3Me/blv42pLbhw6V97z0sD01YCwryHlL+a1KcxY=", + "exports/components/chart.json": "sha256-FYEeXPsVgFCDGrk6zBGMbHfkDAVxKMQ3UaD1fzHaJ5k=", + "exports/components/checkbox.brief.txt": "sha256-ngBeX5vxWizmhHyA5TEM+0PxdQp8DUH+gbgXtxYiMoM=", + "exports/components/checkbox.json": "sha256-YAYWkcNs6/jIIgqy+jx6gmlDu/3U+4Gg47qHfYfCG18=", + "exports/components/chip.brief.txt": "sha256-0xJ4J3fNVO1DzUEB254t4n0onNComjKyZQKFqIY7bII=", + "exports/components/chip.json": "sha256-I7KD3NTRR0IqBS2QOEzZBrtwN01HPGPZhVu6c/oVEZ0=", + "exports/components/code-editor.brief.txt": "sha256-6todMojZH8huAKNTJ9Irx93F8e1zNcbiYQ+M+iYlBfE=", + "exports/components/code-editor.json": "sha256-fmKxx1DFhnRPkNRh1CrE7G54fFOfQWK1fK8yGaySxK8=", + "exports/components/combobox.brief.txt": "sha256-7KNW5at851gjE81muoVtd+0nURBqayqcTD6u2msTy/U=", + "exports/components/combobox.json": "sha256-TSWQmiy38f9R1L1J3m402BJYYVcTEVT2Ul8+D8WFgHc=", + "exports/components/command-palette.brief.txt": "sha256-otWHPpI/uEssq7Ve0yzcYfq51Xbl2n7SqsCyYCM9ogk=", + "exports/components/command-palette.json": "sha256-viPl0XmZASYliCak18F27AYYi3eekx/AXkV4SUwJ//I=", + "exports/components/compact-dashboard.brief.txt": "sha256-sTedYMFUyynHeOEzWNVLJylha01OdG9fV8jvjoVXbVo=", + "exports/components/compact-dashboard.json": "sha256-PepxTe+vIvd4SadpjZtQleHEhx8k4cthnqk1RWxc2uQ=", + "exports/components/data-table.brief.txt": "sha256-J7JbB3MEPNMlGDG0yEZBK7nSoniX8JF1I4+Dk55rEH8=", + "exports/components/data-table.json": "sha256-hpajRXSSKbUabQx7SpjnL3X9WGEHlkfwjbVTETGl+2A=", + "exports/components/date-picker.brief.txt": "sha256-QDOOytLJHsjulZdtVRBC7fk9obRRrPA8FFUhKN91/Ig=", + "exports/components/date-picker.json": "sha256-Ai1Jw+SBBKqdlUT09SW83IwF0sG1Hk3KNqL+RGHCxB0=", + "exports/components/description-list.brief.txt": "sha256-cu50kXpv5FnejyYv9IJkDD/H9m5fnRws6P67HiaFr+w=", + "exports/components/description-list.json": "sha256-BN9M9J+MvHvhsjJY6T2Fnh+O+bHOTZkTiy4Lvzq2ERc=", + "exports/components/diagnostics.brief.txt": "sha256-YHfKNLqkeOxS2D991OpXsOCjedAqzbAqKh6lPsHQKp8=", + "exports/components/diagnostics.json": "sha256-Zw27ng7HW3gu3viOs+CthP8U3/dHfjQKkH9ayymrArE=", + "exports/components/dialog.brief.txt": "sha256-SeXk77ECq3VUmdqCFh1BKMDHwZmKgk4xfdW0SYoxizU=", + "exports/components/dialog.json": "sha256-d8aIBftfoG5OqpCEMjwnn66SGTniK6lDKeMpepUMa1c=", + "exports/components/diff-view.brief.txt": "sha256-WykdeHGoZ4dqNGzoLlm0iv1VLCu3cMN55Z+1+bVYlN4=", + "exports/components/diff-view.json": "sha256-aM/LNu2jcBVzsy39dMihY60GzhMvRb9HC/ecLiP8PSg=", + "exports/components/disclosure.brief.txt": "sha256-jDvBebgiCudoVhKYQCn098plukmzetcAySY9H29GGLg=", + "exports/components/disclosure.json": "sha256-CfLtg1//IHO75gTLFrDUxaXnENRkCdbgGMbCk5SNdSU=", + "exports/components/drawer.brief.txt": "sha256-BXvc+1Anwt1ObuHj/Ek3trYcFReGyotws6bu1925nmk=", + "exports/components/drawer.json": "sha256-E2kcY0OlSe2UjMG2E0HSuUR2OTAk/jkTm5zBbO+RWg4=", + "exports/components/editor-search.brief.txt": "sha256-UTolcGIg1ujE9n9IgWCwWL5xYPVeKKRSzCHAh75Ne0E=", + "exports/components/editor-search.json": "sha256-Mag45ddEDZEV+Y+jURUlPoQeTzv0JvCEHVsaPABj+vc=", + "exports/components/empty-state.brief.txt": "sha256-H9QYE8tThj8FGufL18A383n0XJDR2vGxOr3k+Qg63cA=", + "exports/components/empty-state.json": "sha256-FWlvstG5NMgv9Q735VMhGNyPqacPWB/+pyCTpYWfrAQ=", + "exports/components/error-state.brief.txt": "sha256-ua1xmMxn/Wlp4/Q/47z8rUx6Gjvm+oC2y31wS5iX5SQ=", + "exports/components/error-state.json": "sha256-NtAU+K+pqZDwmAwGCSSCkEhjSsRJIHJwM0caNw05jXs=", + "exports/components/field.brief.txt": "sha256-JJo//UagO+qcQkedvb5RmJ07J2k9bJP0XWHPE/1FG8I=", + "exports/components/field.json": "sha256-Rx5W9AoFNYMMW8A9ho1o4hRuE/ENB/gpnNOTRQRhNRI=", + "exports/components/fieldset.brief.txt": "sha256-AX7n4Pk/HryQzFMyOVlBSZ+rjtOjV4YuGLW1iqhV76I=", + "exports/components/fieldset.json": "sha256-V66tdC0Z7htW1lGkI6RhpGcCKpEm7uNQsAaqQ0A4dUs=", + "exports/components/file-browser.brief.txt": "sha256-i1XuuYQvkhA0oU4AKvD2+8e8Hk/PI61nIXHGvBmvmAU=", + "exports/components/file-browser.json": "sha256-HSGTIbtR79vmgI7tYLzZHijwqpGtKskWySNoF9/w/zE=", + "exports/components/file-input.brief.txt": "sha256-8hjxdIiXlYTlpd17a+BEcqFvfeemY6xdP53RPIYjrFo=", + "exports/components/file-input.json": "sha256-06zC1Z3dYxavPfV5PekQRcNMs7shR/3FvrFb3wXgrBQ=", + "exports/components/filterable-table.brief.txt": "sha256-zPV+aXdZRf++ln0JIb0Mpi3WM4AMf0Z1ls4vr4ZLCOo=", + "exports/components/filterable-table.json": "sha256-FgoA7Z+aN1sKUvXhfYGTVlsu4U057oI83WYnPWiC1g4=", + "exports/components/form-builder.brief.txt": "sha256-Dxzaef9slW2LWv18qpOyhP6VTUzL7XY3vN9A8DZ1KVs=", + "exports/components/form-builder.json": "sha256-miN8svEIjf74EG/mgiKbeX1EIjVr23vQKcz4BPWAjPM=", + "exports/components/i3-window-frame.brief.txt": "sha256-2yMqSWcGUSF6bwN5CxfiXv2GW8w136a1/eZ6bKK8U7w=", + "exports/components/i3-window-frame.json": "sha256-6+Rlns+WQUtjHjy0fBktoTRt/N6Z09elMBFLJTmV7BY=", + "exports/components/icon-button.brief.txt": "sha256-HByocACPvED0UKRRSup/vcpmyxKQjOz1fjVakfjYg04=", + "exports/components/icon-button.json": "sha256-wsUy2FqkXOQgj8h0c5hM/iGC/9PPYT8ocL8VbGUddEY=", + "exports/components/kbd.brief.txt": "sha256-oqqXwF5kXhoEdMZ9MZE+p3icff3lUm2tXFOMdkEkhiM=", + "exports/components/kbd.json": "sha256-ELSLOzvvRYl1qurFJ9eVkLg1Qus9qzIs2GsYsm07m88=", + "exports/components/link.brief.txt": "sha256-0ov9NRQeCW9owz75eSecf/ib67pGoEO3fo/g2JXXKuU=", + "exports/components/link.json": "sha256-aa7yVhQfHQIDuaZ3Viq+YJdq1N3RuVlPWnvJvwIiOFg=", + "exports/components/list.brief.txt": "sha256-KiUX6LtnyZaXnKoACGuRJGmP3bwSbry9E6k+0YtvlCQ=", + "exports/components/list.json": "sha256-MgQOxe1uye8a88sZnrIRwiCJjCzKmx6twRG2VH8ABpw=", + "exports/components/loading-indicator.brief.txt": "sha256-h+AQ6BdjEjZuWlrMpqc4poVA30CNj44Gv1v7kA944F0=", + "exports/components/loading-indicator.json": "sha256-MoRle/0XGjgdNIEqvEd8Zb/9/2w/owjjxAPLM7c4f1E=", + "exports/components/menu.brief.txt": "sha256-us1M0dExqF55uZVFi/0ZXWFJdgejeQs+GVrX8FQDlT4=", + "exports/components/menu.json": "sha256-HKxbQP9UwfAcjuBIXBorwE1VQZpSEnO/Ua5uWbRUWDY=", + "exports/components/multiselect.brief.txt": "sha256-Oy9iTmSJB+YW6TIb4CApQSh+8UiJMS+fOYuo58Gpvbs=", + "exports/components/multiselect.json": "sha256-PuDkFvxHHih+G91pS5YvYXN3ngVeIRAMykjSESWlL7E=", + "exports/components/number-field.brief.txt": "sha256-/ou4j7UCKyMEscv2EgON1sOt4Onaf2YG4Yj8HPOnhKw=", + "exports/components/number-field.json": "sha256-+7nMgea0Ldg+XqSpHuMbtV8eJg+0ltg1Z1Ho0Ip7rZw=", + "exports/components/pagination.brief.txt": "sha256-2OYX06SSNwdRZCyOHtactflbMu3H8/GsEaz5suUidEU=", + "exports/components/pagination.json": "sha256-s3I6bPoje0Hc8u+0sHdHMDtRKutbWWLHDJtK7bhIe+g=", + "exports/components/popover.brief.txt": "sha256-kogcvWNtBF0aW2U+WKTbQWE3F1IrvneTa7aRK5cq1RE=", + "exports/components/popover.json": "sha256-8FivLslYwGkRoOiWEtyEZMd+Rxqgq8mq3Ru80cXUteE=", + "exports/components/progress.brief.txt": "sha256-4ldk+39TvIEktBAQa8LbxPiaRC5KWpemWxbltqY6UTk=", + "exports/components/progress.json": "sha256-atuObzVlilVSplI8GR8QFMxhauDgh1MOWX3v5Zo+sL4=", + "exports/components/radio-group.brief.txt": "sha256-29i4qoBpo+CQwlN45sEp0+yeVUoKUMRozSxnxdkWG+Q=", + "exports/components/radio-group.json": "sha256-qnmrt4TirV5YJu2ZZbqhQiUMTOwlzAXaFqW2esYW0yY=", + "exports/components/range.brief.txt": "sha256-KnZoxveuqDK1nlZYjwoQE5/x6VvVVP1AuxwgMHvyJoE=", + "exports/components/range.json": "sha256-8Rwcs6+GKludCNUPlE/4usBGVxBOcTKXUayPDr6jphU=", + "exports/components/repeater.brief.txt": "sha256-kzZjimvesA4tQpiZ6LzyZnu8RppqkJSNpSvbIBNbEKU=", + "exports/components/repeater.json": "sha256-uwjNW48C+4rgPWqwsvhRLAE5gI2k29fFaF0ZiBEtciw=", + "exports/components/search-field.brief.txt": "sha256-ruIB5K8o0yJH3gIhfteV0U1TicmOPUWv7IZm48azsFw=", + "exports/components/search-field.json": "sha256-647lqfbPOL20cOAzkXgzVhcOQhY0RDiYDhPI69TaHI0=", + "exports/components/segmented-control.brief.txt": "sha256-JW0viICMJJbxbvzRmyx7hFIQN7eRL7V5albZ5rjfOew=", + "exports/components/segmented-control.json": "sha256-liUtL1+NTGYiAeEKIitnjgH009FYFm3k10mmxudx4Sc=", + "exports/components/select.brief.txt": "sha256-rB9OAgwxUKoWoPVnAMfogz0EyMSEN/QjYuD6eF/ForQ=", + "exports/components/select.json": "sha256-ZrZC1FDM6rlw2SBVnELFq4lx/pPWoaSri/nc0tsDi6Y=", + "exports/components/settings-panel.brief.txt": "sha256-fBbIhUmroGdr6JrBrtz2OU96bSlEL0issqhpQ4c98D4=", + "exports/components/settings-panel.json": "sha256-RqTOGT6QV7EODuHat/8ofEaa3MIWEmuSRPx45HiyVxM=", + "exports/components/sidebar-nav.brief.txt": "sha256-FTsvTTZ8+Ra+jKMeAmEBFRCFEKc1+OVXLKuaIuv7v1c=", + "exports/components/sidebar-nav.json": "sha256-wv226o3f+EYpZcJZNJZAxApjN0W9yagwqiDOeohJ8WY=", + "exports/components/skeleton.brief.txt": "sha256-BvEm5II+LU4Ufc1Jj8Cili9Wv/Q1RJ1CE5A6j+a6tmY=", + "exports/components/skeleton.json": "sha256-OMrKD8/Kk9dULiW+REsrIE4owfDAT+eoF1Iy835kMH0=", + "exports/components/skip-link.brief.txt": "sha256-jSkJeM0YUHNcbjSpQ8i5mpmSBBhPAiMrnHcdPT/yX3Q=", + "exports/components/skip-link.json": "sha256-KrT7YKOOEhvsNGfWneRrSkYP8tnIpQvxYei+OtDLjGY=", + "exports/components/switch.brief.txt": "sha256-WL+oOpHM60I9zeLXkiq80sjpzXJSf1K6XdKri5feyBw=", + "exports/components/switch.json": "sha256-/0sqavIx2JZkf7Ci4bk531M7vHjMU4kUhihtyM/sJJo=", + "exports/components/table.brief.txt": "sha256-1jxxuhoQTG09D4fv7EP7q/p7hQN6Ne6aDVlZsXSFhoE=", + "exports/components/table.json": "sha256-7jbenzHcgsTwvxfnWiXqWby/EkDVdcqKbA35rUUZQXc=", + "exports/components/tabs.brief.txt": "sha256-xuLXPMgib4/p+zhbMFT2UkvJ9c6Q/DQ3IaUMsyhX6pE=", + "exports/components/tabs.json": "sha256-rhmTF+Hs1lqo38qrCW3XbEsfD0MyL5MBeNEVrMNSCb8=", + "exports/components/terminal.brief.txt": "sha256-v6eUIkoUVHZ9uuAwUtYU7+p0bnnwh2LuekRvhqjGvj8=", + "exports/components/terminal.json": "sha256-HeFB4mbUDKbQgnxbx0FhurGZoWlvg4oPweP8WZ2cxsw=", + "exports/components/text-field.brief.txt": "sha256-7aVs7Wv5lafBb5yGQCkSfUVxPMK/BOLVa9IYvMnR71s=", + "exports/components/text-field.json": "sha256-c652ooIq7UHR2+ZVpM/7h+GkpEcTQ4eIhOfu3mhoswM=", + "exports/components/textarea.brief.txt": "sha256-S1dUffsaunql6Ya4SgqAzGhkUWEtTLa/kblbIw1vH34=", + "exports/components/textarea.json": "sha256-jUO0fQDKg7bAhVlQBz3uY3PlOy0ESMONgIYo9VKoGrQ=", + "exports/components/time-picker.brief.txt": "sha256-0NSlhNQ1Ci+CyeqAc7+yS1aF/kMfJU0v8+qmqszWqog=", + "exports/components/time-picker.json": "sha256-tjXVz74N3HC4+w/SD/SOu1BuHASYAn7HYzy9WmFW/uk=", + "exports/components/timeline.brief.txt": "sha256-jfMu4l9YZLwGgYCVD1YM1J1P+ei/U9VUsuwZhVfR8aw=", + "exports/components/timeline.json": "sha256-OuFKZP3H8ql38neviRCAIPIlG4jsiesDQhUBmKQys3g=", + "exports/components/toast.brief.txt": "sha256-Hmd1kua9z4FNUaa6mfiBOCC7FlPs9qwUdugJIlSKer4=", + "exports/components/toast.json": "sha256-0FgbZg+1REfm4MYhvbXpZOXZT6RPxqkuVFlO6loVx+o=", + "exports/components/toolbar.brief.txt": "sha256-195aKaP4uV84DeV6yT+zmlhVcecxmJFQaHdA5W2fCWo=", + "exports/components/toolbar.json": "sha256-+HpDPj1BsDcO4uxCkgYJrvxFABMzVYSXGi8NC57ils0=", + "exports/components/tooltip.brief.txt": "sha256-H4DlLKUyTV7UJG+Fjg0SyGNtYvnqV8HYGhXMWn8wCF0=", + "exports/components/tooltip.json": "sha256-QYJtr4n+l37BD2GjopldLLrTuDDeHharcGANEStKiAA=", + "exports/components/tree.brief.txt": "sha256-AJtxA5nLBCqLnw0CSZUSvgfn0627JVYVXNWjteqXVQo=", + "exports/components/tree.json": "sha256-U3SAtvlBCYg9J3s8NoASoTAKhfPSqa7nkMVPLjy5lx0=", + "exports/components/wizard.brief.txt": "sha256-VRVHfuuVw3poTx3qaB3NFkUAZBIjWe3Mvjla8RB1HMA=", + "exports/components/wizard.json": "sha256-xdWhIw7OjMb6UXFITTbSXAdtOVY90Eebulex39zFZSw=", "exports/contrast.json": "sha256-gmovO9y68psNmmsDElXktOprdI/0LTT6JCo0/bLzCD4=", "exports/contrast.md": "sha256-vSmxTKGCZHxysVYKkQNwoGdqO2prLBJVZjHwnogcY+s=", "exports/coverage.json": "sha256-FeuiH5WV9i3ILuDqqcloRbL6pCMOoA3qZeoMEv1HdDU=", "exports/figma/importer.mjs": "sha256-VXfdSuZ1eYqKIIadm4JI73kT9Or0PTracOyncWAsbnI=", - "exports/forms/identity.json": "sha256-ReYrFo3DxY3o68oO6n9Hh7gqvZSNze0W7U1mZ7g43ZA=", + "exports/forms/identity.json": "sha256-t8Fh9iPiaO0TgiTVtSrACuLMa05G9mmsvofXrt+A+GA=", "exports/forms/templates.json": "sha256-k2e6tcvD0k6hUCU+l+1itDIeEGjAzxvq8bCmewl8XRg=", "exports/llms.txt": "sha256-Bzchjr9xc74FBFmz0hwbl9kjJBWCV/L8ZL/q+NvFOm8=", - "exports/patterns/validation-recovery.json": "sha256-hEfzGewdNViHMChlN5b8EXUCao68upU06VxJlR3Dp1w=", + "exports/patterns/validation-recovery.json": "sha256-Afu7exMAwPxab0LwYTYeXAjyY6SSGjxV3I9tMza2zlU=", "exports/port-capabilities.json": "sha256-6u3M0mXA+lN5FLjtOJvRkLpcFNePSv8ZUMpIiVohxVQ=", "exports/recipes/button/LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", "exports/recipes/button/README.md": "sha256-mS8bIWiTXGBfI7igIXsai6GF4p7KlPCfsQvAEFb9fls=", @@ -178,9 +178,9 @@ "exports/recipes/text-field/template.html": "sha256-IlSlLS7sPC3MLqIdxMRQUP4sFnn/58lwM3AFALtdY3c=", "exports/recipes/text-field/tokens.css": "sha256-EqSdsrQqs1NJVLFBDmxFtT0mbcjOiUeAx1G9cTcdpIY=", "exports/recipes/text-field/two-instances.html": "sha256-Abep8m5/si0kuUu3cVGEVzcHqMN1pHkPazmjloND8J0=", - "exports/task-inputs.json": "sha256-MBZr389Gyb8TZfN67iZgvZVQdPziFp2Y252NgbhaLoI=", - "exports/theme.compact.md": "sha256-jrEVDKhdwd24OJBek75+xuGzGoxkykr4U1pjkI5sadQ=", - "exports/theme.full.md": "sha256-vPkn4TtelDvQpwKcvJYx0ROwyHh2QwvuuFvL6Tn7+xI=", + "exports/task-inputs.json": "sha256-uIP7ehpHSIWAQ+yHO8Lnc8OQklzkz7KwWtvsQ0zTxSQ=", + "exports/theme.compact.md": "sha256-qg/mVVnPJiA74EfPSdXjeno7ZrMOlTM1uuuVWF2Pr5A=", + "exports/theme.full.md": "sha256-KET02c0tA+Bp2pYpoEodrr3gKugVB4Kx40Y5W48Nb3Q=", "exports/token-usage.json": "sha256-a1rYc+D6as/OKhMIp1zkGNWMvTXGSuwI6SbU1VNTcKA=", "exports/tokens.css": "sha256-ePraUzvnHrCsJIZ1frkOqaHPFHo7iT+aE6wrL4ian68=", "exports/tokens.resolved.json": "sha256-3KBrfmIiz4L6Qyqvi99TdTe4+5NeuA0ZWZe3Am4sRo4=" diff --git a/exports/forms/identity.json b/exports/forms/identity.json index 15a4b4214..1a1584d29 100644 --- a/exports/forms/identity.json +++ b/exports/forms/identity.json @@ -2,5 +2,5 @@ "name": "j3w1-theme", "version": "4.0.0", "profile": "default", - "sourceDigest": "sha256-KNf9QNXsLy6MzEixJdv+LTT8TglJJgE7H0JwMdzpjfA=" + "sourceDigest": "sha256-nnm9r459tJeHedlg/g0yPDBGXgbqNrXKLizmpFZhVHc=" } diff --git a/exports/patterns/validation-recovery.json b/exports/patterns/validation-recovery.json index 994ca572e..ddd7d926d 100644 --- a/exports/patterns/validation-recovery.json +++ b/exports/patterns/validation-recovery.json @@ -152,17 +152,17 @@ "name": "j3w1-theme", "version": "4.0.0", "profile": "default", - "sourceDigest": "sha256-KNf9QNXsLy6MzEixJdv+LTT8TglJJgE7H0JwMdzpjfA=" + "sourceDigest": "sha256-nnm9r459tJeHedlg/g0yPDBGXgbqNrXKLizmpFZhVHc=" }, "componentDigests": { - "admin-form": "sha256-cMCzZ7Y6R5vDQhUKroYjVSLFkJHU3Gli08YeWYYWjMc=", - "alert": "sha256-SDyyVlrQ4zCsh1k9d6euBFC5H1XTIXNlwApLZ28huDs=", - "button": "sha256-ZlEnd0u5yLcxzB1C8tOCxvA8w2H5K9kB6SkPgTufJuk=", - "checkbox": "sha256-lTwSQVmvHYgltg/LQk97oB/0JbAKuE3b4vjU8EE/mHk=", - "radio-group": "sha256-Ybo2AlA1UgFQjRgOGq07P5lxGTsO4dP+D8wFo3c3qOU=", - "select": "sha256-yL+LqAY+oEKvdS7BUSSuv0a/z1RpMCc9DH2QhdgJ2JA=", - "table": "sha256-Y/Q057zrmXpCMHe71Dk+XFeRwLNu0QkE+JJQMgvVwqs=", - "text-field": "sha256-VP6pzK4iEpJYP1z956Hy0l1cuQwtWdF13P3pTkc7hcA=", - "textarea": "sha256-soblNoXVqwwH4841ku6gvoWpKHO9aZpUgbKZEdG0UcQ=" + "admin-form": "sha256-mAFCR+xrmkneq362ZIjiIzqy3MEHbSq7K2pZCBc8M8Q=", + "alert": "sha256-V2pNLjS0HP52R1DcXAD+e7y5gtxN4yVAqtBTlQaSEE4=", + "button": "sha256-2i8SWTGy0yxV2DVp+BfPl74DDprhEO6TpTsKIOe5im8=", + "checkbox": "sha256-YAYWkcNs6/jIIgqy+jx6gmlDu/3U+4Gg47qHfYfCG18=", + "radio-group": "sha256-qnmrt4TirV5YJu2ZZbqhQiUMTOwlzAXaFqW2esYW0yY=", + "select": "sha256-ZrZC1FDM6rlw2SBVnELFq4lx/pPWoaSri/nc0tsDi6Y=", + "table": "sha256-7jbenzHcgsTwvxfnWiXqWby/EkDVdcqKbA35rUUZQXc=", + "text-field": "sha256-c652ooIq7UHR2+ZVpM/7h+GkpEcTQ4eIhOfu3mhoswM=", + "textarea": "sha256-jUO0fQDKg7bAhVlQBz3uY3PlOy0ESMONgIYo9VKoGrQ=" } } diff --git a/exports/task-inputs.json b/exports/task-inputs.json index f23f72100..17eb4e99e 100644 --- a/exports/task-inputs.json +++ b/exports/task-inputs.json @@ -1003,74 +1003,74 @@ "z.toast": [] }, "files": { - "agents/consume.md": "sha256-i6Yk0kTqauioqD23HdGiN3S1EkyVC1bn/m86OR99hqc=", - "exports/components/admin-form.json": "sha256-cMCzZ7Y6R5vDQhUKroYjVSLFkJHU3Gli08YeWYYWjMc=", - "exports/components/alert.json": "sha256-SDyyVlrQ4zCsh1k9d6euBFC5H1XTIXNlwApLZ28huDs=", - "exports/components/avatar.json": "sha256-hUNV+6XmlXrHWL6Tic/4F2BgAkQDiplqsBttX7wyBVo=", - "exports/components/badge.json": "sha256-J6LygawZXw+gAxgIfKKMtKinZWxdT4fQ7JbeHvOxI7Q=", - "exports/components/breadcrumbs.json": "sha256-ZEltkBqhykUx1c98sp1AnzBLBOL38xfDyJvOTwm4Sh4=", - "exports/components/button-group.json": "sha256-Sq8vsc8jJEpMDIaHTq3UMiJ7LDvSiv5vmDoAuxQX7Wk=", - "exports/components/button.json": "sha256-ZlEnd0u5yLcxzB1C8tOCxvA8w2H5K9kB6SkPgTufJuk=", - "exports/components/card.json": "sha256-sjtZLyhgdgrEFnSySdcpLFbLyZkWKnIa1jsxlIVK71o=", - "exports/components/chart.json": "sha256-BasdUdA3MzGo0Rmmrmj+E6bMOtudFa8Xxcdb51Nizp0=", - "exports/components/checkbox.json": "sha256-lTwSQVmvHYgltg/LQk97oB/0JbAKuE3b4vjU8EE/mHk=", - "exports/components/chip.json": "sha256-BfTPtwtzIh8BFij9jAuBYFOI1OOsIa/QqxGxoSvruBQ=", - "exports/components/code-editor.json": "sha256-9LKz74FqUL7zWtnvvJ/AAzTZkLqpiZk6fmDkxJGzlgg=", - "exports/components/combobox.json": "sha256-slabxERChhxzMG1On6USB3ilVP2/GZ86qPGxrKtyd/I=", - "exports/components/command-palette.json": "sha256-kjl20b57OaZaKaOyQYMLeCMiiJtqygpnPayE03RaF9E=", - "exports/components/compact-dashboard.json": "sha256-mdvkqeJBaUpbi1OZalkU9nibADqwIXoBlEn7k1c9QK4=", - "exports/components/data-table.json": "sha256-GtiL/MsfUQrKkEhOX2LBO39gDmHItEupAGUcxO9S7so=", - "exports/components/date-picker.json": "sha256-I7/+SFQ5Etf2XhC1KC2zKnJoBuuUfQ+XBwSvzIIM9G4=", - "exports/components/description-list.json": "sha256-TcAgWaXIqrh7GnyY4Fh1sxw18w3Z64obPXXecZjM9PA=", - "exports/components/diagnostics.json": "sha256-XEiEML9kKK1Sx0WE7ntiSRf1x/LsJV0WRD7Ld7KIRBI=", - "exports/components/dialog.json": "sha256-iW1JIM20K7jbEJPsZT44sXsMWUbFYnoH8MKe+xSwKno=", - "exports/components/diff-view.json": "sha256-UV7sIl990iqjdYQ+70hGI5AnnZVgdnk2glZ2TGeMBh0=", - "exports/components/disclosure.json": "sha256-9XecJvyNgfoZEOW2s0oYxV0wASigN5AcdFQ5jSvLFl8=", - "exports/components/drawer.json": "sha256-UWZZjgftkOkdmmGie3aC6ygvdyubUx31slprKBMVXco=", - "exports/components/editor-search.json": "sha256-9OA9zuYcg6E9odzsrjVymAg0bXpA/YrgHDPTF+ZX3fc=", - "exports/components/empty-state.json": "sha256-9jQ+/tMzpDMWDn1FdHFsY5MvGelrQ7ChHrdJgDpPO2Y=", - "exports/components/error-state.json": "sha256-vgS8frriX3mDe18TFJsu8qMJ5vGa8pSmryajo5TX8Z0=", - "exports/components/field.json": "sha256-/mkJI+8jB6gTFIo3KiYT8xkFsr/YATG/S6dC68UXBL8=", - "exports/components/fieldset.json": "sha256-UwVGiS3NbUzuJsIir7uaYz0WnWsR6xBT7/qEBYIX8RI=", - "exports/components/file-browser.json": "sha256-5Zla/4ImfqmxvuIKDJDxEQodvH9GaqSc25g7SMLGyMs=", - "exports/components/file-input.json": "sha256-2BPV00mPYWRZwpGSypAWLwmyzqBlF5/h2S4H5pq/2Qc=", - "exports/components/filterable-table.json": "sha256-t59LtzesMFhdRKldod6ybMMKusCmRLNz4lbCOopPYrg=", - "exports/components/form-builder.json": "sha256-4mIniVSwqBN9xrQw+5U3yNtrlk/aRH8jZPKuY0aIcFo=", - "exports/components/i3-window-frame.json": "sha256-HE2yLQP/EeCfukaO9TmrjuntEfxBg45zTLfMTv8dV+w=", - "exports/components/icon-button.json": "sha256-sNwIKljbVPU+JhJSwXGW7HAJqD+603MQomnt9DXiGfg=", - "exports/components/kbd.json": "sha256-qtJdAYhDBzZPtmFspChfruWyiMDL9twSz9dLREQCMQw=", - "exports/components/link.json": "sha256-Ve/sgeCPW8kcWLJQRARNL0CZ6+8QnNZ3pfX5Yy2tjSA=", - "exports/components/list.json": "sha256-ayifS2PLlnD94AVUVt5LUutQj2M8RmG/kLVPtqTuAkY=", - "exports/components/loading-indicator.json": "sha256-shFLUs9MXfCP4POg3WBzqxyPjk47+79iE82UK5M1V6M=", - "exports/components/menu.json": "sha256-vxb+FTeoH6TkYXfE0DDg7xcAntQBy94waPLnLqUiB4Y=", - "exports/components/multiselect.json": "sha256-UiDVzUHMqLI+ruP4XdGhBuhdbP+5baB4PPlvNWBrlw4=", - "exports/components/number-field.json": "sha256-CYDT5nidQgoqOlXEDX8P4MMWaVY5gtgr0XoeBFYIFLY=", - "exports/components/pagination.json": "sha256-vFyBtSE4gjXCH2sQZbtvZNAlK2UZRRoX7ogz76srgG4=", - "exports/components/popover.json": "sha256-mTckWzUiz2rRahydiFa/ONiXepSRsdEbdYRvaJ92k54=", - "exports/components/progress.json": "sha256-DQMvp+PkVdptaRd9LjZ19GAiQVgMa0awWfpqeGfMV0o=", - "exports/components/radio-group.json": "sha256-Ybo2AlA1UgFQjRgOGq07P5lxGTsO4dP+D8wFo3c3qOU=", - "exports/components/range.json": "sha256-WIF2ZWvwloqTUB+95IHl9aTeKIuaSxFCo/GK3oKxqPo=", - "exports/components/repeater.json": "sha256-YW1BZL3NCKzxpyHd/oX4fmkbNzwZIeDh5ImXEZuTlo4=", - "exports/components/search-field.json": "sha256-gOrIeIfgFkPVcFjUBIrmT69tTA0ucPhyFpv9/9NLFNY=", - "exports/components/segmented-control.json": "sha256-L4OU1sHlD4fDrmyShueCt1NH9/xM2b71QmPjDetz7Ys=", - "exports/components/select.json": "sha256-yL+LqAY+oEKvdS7BUSSuv0a/z1RpMCc9DH2QhdgJ2JA=", - "exports/components/settings-panel.json": "sha256-tZqQ8ue4o/6aX+gIHuAw7U7+KfnO1KR+5b/KbqzidzQ=", - "exports/components/sidebar-nav.json": "sha256-9M/9axST95VbeHYLN2FsITzn819QUURTBFzeFZ7w3eU=", - "exports/components/skeleton.json": "sha256-nM5bEtPXQluMleeSjUbHKRiLicp4xKgCshJTmeAE2TQ=", - "exports/components/skip-link.json": "sha256-wfbZNR4N5PUEmEQQ7ustM2ZZkw4F4OOgo2uylcTpQA0=", - "exports/components/switch.json": "sha256-+qLnIwiesw3n677GRmUYDQnLQyF7caiVcrQ43qWDqco=", - "exports/components/table.json": "sha256-Y/Q057zrmXpCMHe71Dk+XFeRwLNu0QkE+JJQMgvVwqs=", - "exports/components/tabs.json": "sha256-4uEKjf6Pcl6epXayzGG7Rb6szfuzs1JaRdBHjSWx28U=", - "exports/components/terminal.json": "sha256-tmO1tF2j9qKaUBaCWKbLDbwc6RvjOeH/0QsD0HBHuyg=", - "exports/components/text-field.json": "sha256-VP6pzK4iEpJYP1z956Hy0l1cuQwtWdF13P3pTkc7hcA=", - "exports/components/textarea.json": "sha256-soblNoXVqwwH4841ku6gvoWpKHO9aZpUgbKZEdG0UcQ=", - "exports/components/time-picker.json": "sha256-aN3mUcCZMpc0H3B6cGSep2AEEUblbSurbtYZ+4c3voQ=", - "exports/components/timeline.json": "sha256-Lrmu0cnFU8OjQU20yskQ+wUPDZIeKHNyt1QL57Hpq8o=", - "exports/components/toast.json": "sha256-kEViFGDQbl6zuTVQWQAkR9uhmJChDetGK+VHu7R7/R4=", - "exports/components/toolbar.json": "sha256-HR1PNVg/kEeT2sPQLICqlHh2Jpwgmjz2ISDyKNbOnfA=", - "exports/components/tooltip.json": "sha256-W6/wWbuwFVhv7bacwRrT7HpcYnZIO0lq7M4l6wET6/4=", - "exports/components/tree.json": "sha256-oUHCGdl1TrWMb2+5kqpcUru1cUe4isv3d+K5i8m9GBo=", - "exports/components/wizard.json": "sha256-gm/Ax9KeTuUiV1krYNzcz6m57jB7lC4lRu3+W+QuZrA=", + "agents/consume.md": "sha256-I7gvGchrdAXnxI1VpW1sIodxyPy9hNvveANaO2p7h8w=", + "exports/components/admin-form.json": "sha256-mAFCR+xrmkneq362ZIjiIzqy3MEHbSq7K2pZCBc8M8Q=", + "exports/components/alert.json": "sha256-V2pNLjS0HP52R1DcXAD+e7y5gtxN4yVAqtBTlQaSEE4=", + "exports/components/avatar.json": "sha256-RA3Pu+xDIHyOk6G8T+hi2EegLb60YZ6zcRzzj9pB9sg=", + "exports/components/badge.json": "sha256-fNCf1ucOy924OTdhh8VzzOdeOhAJZDPXbVoWH49ozXk=", + "exports/components/breadcrumbs.json": "sha256-HKZovzFwthHtZitxchseA9wsKYZrCroZ6k/K7hH1Pek=", + "exports/components/button-group.json": "sha256-3k2A1T3AgcMWuPu/Mj9WOhaoyGyEOOgzptf4DdE1eBo=", + "exports/components/button.json": "sha256-2i8SWTGy0yxV2DVp+BfPl74DDprhEO6TpTsKIOe5im8=", + "exports/components/card.json": "sha256-JMAwjwR46Ljwut8wyVtBU9aTCR+Atca8nigCFF4owGo=", + "exports/components/chart.json": "sha256-FYEeXPsVgFCDGrk6zBGMbHfkDAVxKMQ3UaD1fzHaJ5k=", + "exports/components/checkbox.json": "sha256-YAYWkcNs6/jIIgqy+jx6gmlDu/3U+4Gg47qHfYfCG18=", + "exports/components/chip.json": "sha256-I7KD3NTRR0IqBS2QOEzZBrtwN01HPGPZhVu6c/oVEZ0=", + "exports/components/code-editor.json": "sha256-fmKxx1DFhnRPkNRh1CrE7G54fFOfQWK1fK8yGaySxK8=", + "exports/components/combobox.json": "sha256-TSWQmiy38f9R1L1J3m402BJYYVcTEVT2Ul8+D8WFgHc=", + "exports/components/command-palette.json": "sha256-viPl0XmZASYliCak18F27AYYi3eekx/AXkV4SUwJ//I=", + "exports/components/compact-dashboard.json": "sha256-PepxTe+vIvd4SadpjZtQleHEhx8k4cthnqk1RWxc2uQ=", + "exports/components/data-table.json": "sha256-hpajRXSSKbUabQx7SpjnL3X9WGEHlkfwjbVTETGl+2A=", + "exports/components/date-picker.json": "sha256-Ai1Jw+SBBKqdlUT09SW83IwF0sG1Hk3KNqL+RGHCxB0=", + "exports/components/description-list.json": "sha256-BN9M9J+MvHvhsjJY6T2Fnh+O+bHOTZkTiy4Lvzq2ERc=", + "exports/components/diagnostics.json": "sha256-Zw27ng7HW3gu3viOs+CthP8U3/dHfjQKkH9ayymrArE=", + "exports/components/dialog.json": "sha256-d8aIBftfoG5OqpCEMjwnn66SGTniK6lDKeMpepUMa1c=", + "exports/components/diff-view.json": "sha256-aM/LNu2jcBVzsy39dMihY60GzhMvRb9HC/ecLiP8PSg=", + "exports/components/disclosure.json": "sha256-CfLtg1//IHO75gTLFrDUxaXnENRkCdbgGMbCk5SNdSU=", + "exports/components/drawer.json": "sha256-E2kcY0OlSe2UjMG2E0HSuUR2OTAk/jkTm5zBbO+RWg4=", + "exports/components/editor-search.json": "sha256-Mag45ddEDZEV+Y+jURUlPoQeTzv0JvCEHVsaPABj+vc=", + "exports/components/empty-state.json": "sha256-FWlvstG5NMgv9Q735VMhGNyPqacPWB/+pyCTpYWfrAQ=", + "exports/components/error-state.json": "sha256-NtAU+K+pqZDwmAwGCSSCkEhjSsRJIHJwM0caNw05jXs=", + "exports/components/field.json": "sha256-Rx5W9AoFNYMMW8A9ho1o4hRuE/ENB/gpnNOTRQRhNRI=", + "exports/components/fieldset.json": "sha256-V66tdC0Z7htW1lGkI6RhpGcCKpEm7uNQsAaqQ0A4dUs=", + "exports/components/file-browser.json": "sha256-HSGTIbtR79vmgI7tYLzZHijwqpGtKskWySNoF9/w/zE=", + "exports/components/file-input.json": "sha256-06zC1Z3dYxavPfV5PekQRcNMs7shR/3FvrFb3wXgrBQ=", + "exports/components/filterable-table.json": "sha256-FgoA7Z+aN1sKUvXhfYGTVlsu4U057oI83WYnPWiC1g4=", + "exports/components/form-builder.json": "sha256-miN8svEIjf74EG/mgiKbeX1EIjVr23vQKcz4BPWAjPM=", + "exports/components/i3-window-frame.json": "sha256-6+Rlns+WQUtjHjy0fBktoTRt/N6Z09elMBFLJTmV7BY=", + "exports/components/icon-button.json": "sha256-wsUy2FqkXOQgj8h0c5hM/iGC/9PPYT8ocL8VbGUddEY=", + "exports/components/kbd.json": "sha256-ELSLOzvvRYl1qurFJ9eVkLg1Qus9qzIs2GsYsm07m88=", + "exports/components/link.json": "sha256-aa7yVhQfHQIDuaZ3Viq+YJdq1N3RuVlPWnvJvwIiOFg=", + "exports/components/list.json": "sha256-MgQOxe1uye8a88sZnrIRwiCJjCzKmx6twRG2VH8ABpw=", + "exports/components/loading-indicator.json": "sha256-MoRle/0XGjgdNIEqvEd8Zb/9/2w/owjjxAPLM7c4f1E=", + "exports/components/menu.json": "sha256-HKxbQP9UwfAcjuBIXBorwE1VQZpSEnO/Ua5uWbRUWDY=", + "exports/components/multiselect.json": "sha256-PuDkFvxHHih+G91pS5YvYXN3ngVeIRAMykjSESWlL7E=", + "exports/components/number-field.json": "sha256-+7nMgea0Ldg+XqSpHuMbtV8eJg+0ltg1Z1Ho0Ip7rZw=", + "exports/components/pagination.json": "sha256-s3I6bPoje0Hc8u+0sHdHMDtRKutbWWLHDJtK7bhIe+g=", + "exports/components/popover.json": "sha256-8FivLslYwGkRoOiWEtyEZMd+Rxqgq8mq3Ru80cXUteE=", + "exports/components/progress.json": "sha256-atuObzVlilVSplI8GR8QFMxhauDgh1MOWX3v5Zo+sL4=", + "exports/components/radio-group.json": "sha256-qnmrt4TirV5YJu2ZZbqhQiUMTOwlzAXaFqW2esYW0yY=", + "exports/components/range.json": "sha256-8Rwcs6+GKludCNUPlE/4usBGVxBOcTKXUayPDr6jphU=", + "exports/components/repeater.json": "sha256-uwjNW48C+4rgPWqwsvhRLAE5gI2k29fFaF0ZiBEtciw=", + "exports/components/search-field.json": "sha256-647lqfbPOL20cOAzkXgzVhcOQhY0RDiYDhPI69TaHI0=", + "exports/components/segmented-control.json": "sha256-liUtL1+NTGYiAeEKIitnjgH009FYFm3k10mmxudx4Sc=", + "exports/components/select.json": "sha256-ZrZC1FDM6rlw2SBVnELFq4lx/pPWoaSri/nc0tsDi6Y=", + "exports/components/settings-panel.json": "sha256-RqTOGT6QV7EODuHat/8ofEaa3MIWEmuSRPx45HiyVxM=", + "exports/components/sidebar-nav.json": "sha256-wv226o3f+EYpZcJZNJZAxApjN0W9yagwqiDOeohJ8WY=", + "exports/components/skeleton.json": "sha256-OMrKD8/Kk9dULiW+REsrIE4owfDAT+eoF1Iy835kMH0=", + "exports/components/skip-link.json": "sha256-KrT7YKOOEhvsNGfWneRrSkYP8tnIpQvxYei+OtDLjGY=", + "exports/components/switch.json": "sha256-/0sqavIx2JZkf7Ci4bk531M7vHjMU4kUhihtyM/sJJo=", + "exports/components/table.json": "sha256-7jbenzHcgsTwvxfnWiXqWby/EkDVdcqKbA35rUUZQXc=", + "exports/components/tabs.json": "sha256-rhmTF+Hs1lqo38qrCW3XbEsfD0MyL5MBeNEVrMNSCb8=", + "exports/components/terminal.json": "sha256-HeFB4mbUDKbQgnxbx0FhurGZoWlvg4oPweP8WZ2cxsw=", + "exports/components/text-field.json": "sha256-c652ooIq7UHR2+ZVpM/7h+GkpEcTQ4eIhOfu3mhoswM=", + "exports/components/textarea.json": "sha256-jUO0fQDKg7bAhVlQBz3uY3PlOy0ESMONgIYo9VKoGrQ=", + "exports/components/time-picker.json": "sha256-tjXVz74N3HC4+w/SD/SOu1BuHASYAn7HYzy9WmFW/uk=", + "exports/components/timeline.json": "sha256-OuFKZP3H8ql38neviRCAIPIlG4jsiesDQhUBmKQys3g=", + "exports/components/toast.json": "sha256-0FgbZg+1REfm4MYhvbXpZOXZT6RPxqkuVFlO6loVx+o=", + "exports/components/toolbar.json": "sha256-+HpDPj1BsDcO4uxCkgYJrvxFABMzVYSXGi8NC57ils0=", + "exports/components/tooltip.json": "sha256-QYJtr4n+l37BD2GjopldLLrTuDDeHharcGANEStKiAA=", + "exports/components/tree.json": "sha256-U3SAtvlBCYg9J3s8NoASoTAKhfPSqa7nkMVPLjy5lx0=", + "exports/components/wizard.json": "sha256-xdWhIw7OjMb6UXFITTbSXAdtOVY90Eebulex39zFZSw=", "exports/port-capabilities.json": "sha256-6u3M0mXA+lN5FLjtOJvRkLpcFNePSv8ZUMpIiVohxVQ=", "exports/recipes/button/component.css": "sha256-+Fn90PbGbnW0JxDH1RAdiYrVQ4FrstMA+Rq7HlAQTdU=", "exports/recipes/button/example.html": "sha256-HRSLwap8t93ggusQ8BYoEAE0wPCsBWTKSY+4JGzRNa4=", @@ -1102,7 +1102,7 @@ "exports/recipes/text-field/template.html": "sha256-IlSlLS7sPC3MLqIdxMRQUP4sFnn/58lwM3AFALtdY3c=", "exports/recipes/text-field/tokens.css": "sha256-EqSdsrQqs1NJVLFBDmxFtT0mbcjOiUeAx1G9cTcdpIY=", "exports/recipes/text-field/two-instances.html": "sha256-Abep8m5/si0kuUu3cVGEVzcHqMN1pHkPazmjloND8J0=", - "exports/theme.compact.md": "sha256-jrEVDKhdwd24OJBek75+xuGzGoxkykr4U1pjkI5sadQ=", + "exports/theme.compact.md": "sha256-qg/mVVnPJiA74EfPSdXjeno7ZrMOlTM1uuuVWF2Pr5A=", "exports/tokens.resolved.json": "sha256-3KBrfmIiz4L6Qyqvi99TdTe4+5NeuA0ZWZe3Am4sRo4=", "LICENSE.md": "sha256-Ih5+DpqcNXGWJX6BbYgpt6psmJi9lGcXGJzuiU7elE0=", "schemas/json/theme.lock.schema.json": "sha256-y6m+IekX0jzgI6Rhel1Vx33fgz8RIT5A2OPyBL0qlXw=", diff --git a/exports/theme.compact.md b/exports/theme.compact.md index e183cab59..6813b5295 100644 --- a/exports/theme.compact.md +++ b/exports/theme.compact.md @@ -1,5 +1,5 @@ # j3w1 UI Theme Spec — compact (4.0.0, profile: default) - + Read this first; it is the smallest complete statement of the approved contract. Pin a tag or commit and fetch every file at that revision (see `agents/consume.md`). Values marked PROPOSED are not approved. diff --git a/exports/theme.full.md b/exports/theme.full.md index 8deb5f799..d0d065f4c 100644 --- a/exports/theme.full.md +++ b/exports/theme.full.md @@ -1,5 +1,5 @@ # j3w1 UI Theme Spec — full (4.0.0) - + Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens. Everything in one document: identity, foundations, every profile's resolved tokens, accessibility with the contrast report, portability, every component specification, the coverage ledger, the support table, the decision log and the references catalogue. @@ -8045,51 +8045,80 @@ A token moves from `proposed` to `approved` only by an `accepted` decision refer in its `$extensions["io.github.j3w1.theme"].approval.decision`. Agents may open `proposed` entries; only the owner changes a status. -Each entry has a Decision and a Status line (status, date, who decided, and -what later entries changed), plus Why, Consequences and Alternatives where they -apply. +Each entry has a Decision, a Why and a Status line (status, date, who decided, +and what later entries changed). Alternatives and Consequences appear only where +they add something stated nowhere else. Entries are ordered by topic. + +### Decisions by topic + +#### Governance and process | # | Title | Status | Date | Decided by | | --- | --- | --- | --- | --- | | D-000 | Responsibility split: tokens, spec, ports, evidence | accepted | 2026-09-05 | owner (design package) | -| D-001 | Controlled three-hue extension for status, diagnostics and diffs | accepted | 2026-09-06 | owner | | D-002 | v0.1.0 ships the full R1 component inventory | accepted | 2026-09-06 | owner | -| D-003 | Text-role corrections with new in-hue values | accepted | 2026-09-06 | owner | | D-004 | Public repository; MIT code, CC BY 4.0 prose | accepted | 2026-09-06 | owner | | D-005 | Default profile id is `default` | proposed | 2026-09-06 | — | -| D-006 | Focus-ring rule, including invalid + focus | proposed | 2026-09-06 | — | -| D-007 | `border.control` uses `#A3676B` | proposed | 2026-09-06 | — | -| D-008 | Fold site hairlines into `border.divider`; `surface.sunken`; unified overlay border | proposed | 2026-09-06 | — | -| D-009 | Density modes `compact` and `comfortable` as tokens | proposed | 2026-09-06 | — | | D-010 | The site deploys from `main` | proposed | 2026-09-06 | — | | D-011 | Reference screenshots are cropped before publication | proposed | 2026-09-06 | — | | D-012 | Exports are committed and drift-checked | proposed | 2026-09-06 | — | | D-013 | Consumption eligibility is separate from approval | proposed | 2026-09-07 | — | -| D-014 | Automatic inline literal color previews | proposed | 2026-09-07 | — | -| D-015 | Clarify component mappings exposed by consumption acceptance | proposed | 2026-09-07 | — | -| D-016 | Pinned release comparison report and historical rendering | proposed | 2026-09-08 | — | -| D-017 | Private framework parity evidence | proposed | 2026-09-08 | — | -| D-018 | Declared port capabilities and fresh import evidence | proposed | 2026-09-08 | — | -| D-019 | One-way namespaced Figma Variables bridge | proposed | 2026-09-08 | — | -| D-020 | Bounded local validation and recovery workflow | proposed | 2026-09-08 | — | -| D-021 | Local form composition with versioned data | proposed | 2026-09-08 | — | -| D-022 | Local visual selection before agent implementation distribution | proposed | 2026-09-08 | — | +| D-028 | Merge gates and the deployment gate are different suites | accepted | 2026-09-11 | owner (explicit verification-split instruction) | +| D-031 | Select the checks a change needs; shard the deployment matrix | accepted | 2026-09-26 | owner (explicit CI renovation request, plan approval) | + +#### Colour foundation + +| # | Title | Status | Date | Decided by | +| --- | --- | --- | --- | --- | +| D-001 | Controlled three-hue extension for status, diagnostics and diffs | accepted | 2026-09-06 | owner | +| D-003 | Text-role corrections with new in-hue values | accepted | 2026-09-06 | owner | +| D-007 | `border.control` uses `#A3676B` | proposed | 2026-09-06 | — | +| D-008 | Fold site hairlines into `border.divider`; `surface.sunken`; unified overlay border | proposed | 2026-09-06 | — | | D-023 | True Black / Rose canonical foundation | accepted | 2026-09-08 | owner (explicit selection of candidate I) | -| D-024 | Distinguish links from body text and headings | accepted | 2026-09-08 | owner (explicit preview correction) | -| D-025 | Theme interactive controls throughout the portal and demo | accepted | 2026-09-09 | owner (explicit native-control replacement request) | | D-026 | Primary action fill darkens off heritage ANSI 12 | accepted | 2026-09-11 | owner (explicit acceptance after visual review) | | D-027 | Recede the interactive chrome | accepted | 2026-09-11 | owner (explicit acceptance after visual review) | -| D-028 | Merge gates and the deployment gate are different suites | accepted | 2026-09-11 | owner (explicit verification-split instruction) | | D-029 | Readable terminal and code reds | accepted | 2026-09-26 | owner (explicit selection of values and release in planning) | | D-030 | Hued syntax roles for opt-in code highlighting | accepted | 2026-09-26 | owner (explicit request for a more colourful Codex, selection of the extended hues) | -| D-031 | Select the checks a change needs; shard the deployment matrix | accepted | 2026-09-26 | owner (explicit CI renovation request, plan approval) | | D-032 | Coral slot 6 and a fixed prompt background | accepted | 2026-09-26 | owner (explicit selection of coral and the PowerShell prompt look) | -| D-033 | Rose prose, semantic content headings and inherited bold | accepted | 2026-09-28 | owner (explicit implementation plan) | -| D-034 | Versioned Windows native and Windhawk adapters | accepted | 2026-09-28 | owner (explicit implementation plan) | | D-035 | An accent surface for the user's own content | accepted | 2026-10-06 | owner (Telegram acceptance: own and other people's messages too similar; chose #3d0c0a from a side-by-side comparison) | | D-036 | A translucent text-selection tint | accepted | 2026-10-06 | owner (Telegram acceptance: Android text selection barely visible; chose 50% from a side-by-side comparison) | + +#### Typography and density + +| # | Title | Status | Date | Decided by | +| --- | --- | --- | --- | --- | +| D-009 | Density modes `compact` and `comfortable` as tokens | proposed | 2026-09-06 | — | +| D-033 | Rose prose, semantic content headings and inherited bold | accepted | 2026-09-28 | owner (explicit implementation plan) | | D-037 | Display and title type sizes | proposed | 2026-10-14 | — | +#### Interaction and components + +| # | Title | Status | Date | Decided by | +| --- | --- | --- | --- | --- | +| D-006 | Focus-ring rule, including invalid + focus | proposed | 2026-09-06 | — | +| D-014 | Automatic inline literal color previews | proposed | 2026-09-07 | — | +| D-015 | Clarify component mappings exposed by consumption acceptance | proposed | 2026-09-07 | — | +| D-024 | Distinguish links from body text and headings | accepted | 2026-09-08 | owner (explicit preview correction) | +| D-025 | Theme interactive controls throughout the portal and demo | accepted | 2026-09-09 | owner (explicit native-control replacement request) | + +#### Site, tools and distribution + +| # | Title | Status | Date | Decided by | +| --- | --- | --- | --- | --- | +| D-016 | Pinned release comparison report and historical rendering | proposed | 2026-09-08 | — | +| D-017 | Private framework parity evidence | proposed | 2026-09-08 | — | +| D-019 | One-way namespaced Figma Variables bridge | proposed | 2026-09-08 | — | +| D-020 | Bounded local validation and recovery workflow | proposed | 2026-09-08 | — | +| D-021 | Local form composition with versioned data | proposed | 2026-09-08 | — | +| D-022 | Local visual selection before agent implementation distribution | proposed | 2026-09-08 | — | + +#### Ports + +| # | Title | Status | Date | Decided by | +| --- | --- | --- | --- | --- | +| D-018 | Declared port capabilities and fresh import evidence | proposed | 2026-09-08 | — | +| D-034 | Versioned Windows native and Windhawk adapters | accepted | 2026-09-28 | owner (explicit implementation plan) | + ### D-000 Responsibility split **Decision.** Token files own literal values and aliases; the specification owns @@ -8103,53 +8132,14 @@ origin, not an override of the adopted accessible design. **Status.** accepted · 2026-09-05 · owner (design package `ARCHITECTURE.md`). -### D-001 Controlled three-hue extension - -**Decision.** `default` adds three desaturated, warm-shifted hues: amber -`#C9973F` (warning, modified), green `#86A46F` (success, added), blue `#7E9EBB` -(info); dark tints `#1F1A0C`, `#0F1A0E`, `#0F141C`. They appear only in -`status`, `diagnostic` and `diff` (plus `code`, `terminal` and `chart` in -`extended`), never in `surface`, `text`, `border`, `interaction` or `action`. No -purple, cyan or magenta. Every status role also has a glyph, underline pattern -or border style. `default` syntax stays monochrome; `extended` stays `proposed`. - -**Why.** Lightness alone cannot separate diagnostics, diffs and status (a -200-line diff cannot be scanned by glyph); the owner's PhpStorm scheme already -uses such hues. - -**Consequences.** Contrast on canvas / surface / raised: amber 7.54 / 7.34 / -6.90, green 7.13 / 6.95 / 6.53, blue 7.08 / 6.90 / 6.48. - -**Status.** accepted · 2026-09-06 · owner. Superseded in part by D-030 (opt-in -`code.hued.*`; `code.syntax.*` stays monochrome). - ### D-002 v0.1.0 inventory **Decision.** The first public release holds every `R1` inventory component (about 47 across all nine families) plus four composed specimens (settings panel, administrative form, filterable table, i3 window frame), each *specified* and *demonstrated*. Ten core components are also *tested*: button, link, -text-field, select, checkbox, radio-group, tabs, dialog, menu, table. - -**Consequences.** `R2` items and the form-builder specimen wait for v0.2. - -**Status.** accepted · 2026-09-06 · owner. - -### D-003 Text-role corrections - -**Decision.** `text.subtle` = `#AD7175` (5.10 / 4.96 / 4.67) for metadata, -comments and line numbers. `text.disabled` = `#8A5559` (3.33 / 3.24 / 3.05; -exempt under WCAG 1.4.3, at least 3:1 by house policy). `#A3676B` stays as -`border.control`, `icon.decorative`, `status.neutral.fill` and `chart.series.4` -(non-text, at least 3:1); `#7D1310` only as `border.disabled`, `code.whitespace` -and minor grid lines, never text. - -**Why.** `#A3676B` (the site's `--quiet`) measures 4.45:1 on `#0C0909` and -`#7D1310` (`--inactive`) 1.86:1, yet the site used `#7D1310` for line numbers; -its suggested `#A8403A` measures only 3.27:1. - -**Consequences.** `heritage-ansi` keeps the original assignments, flagged -`$deprecated`. +text-field, select, checkbox, radio-group, tabs, dialog, menu, table. `R2` items +and the form-builder specimen wait for v0.2. **Status.** accepted · 2026-09-06 · owner. @@ -8158,10 +8148,8 @@ its suggested `#A8403A` measures only 3.27:1. **Decision.** The repository is public. MIT: code, tokens, schemas, scripts, tests, site source, generated JSON/CSS exports. CC BY 4.0: specification prose, specimens, generated Markdown exports. Screenshots under `references/`: all -rights reserved, reference only. - -**Consequences.** Fonts, vendor template material and private business data are -never committed; CI scans for them. See `LICENSE.md`. +rights reserved, reference only. Fonts, vendor template material and private +business data are never committed; CI scans for them. See `LICENSE.md`. **Status.** accepted · 2026-09-06 · owner. @@ -8172,57 +8160,6 @@ renaming it later is a MAJOR version change. **Status.** proposed · 2026-09-06. -### D-006 Focus-ring rule - -**Decision.** Controls and rows: `outline: 1px dashed -{color.interaction.focus.ring}` (`#E53935`), `outline-offset: -2px`. Focusable -containers (panes, windows, dialogs, cards): `outline: 2px solid -{color.interaction.focus.ring-container}` (`#FFA2A7`), `outline-offset: -3px`. -On any fill (selection, action, status) the ring takes the on-fill text colour; -on invalid + focus, where the 2px danger border is already red, it takes -`#FFA2A7` at `outline-offset: -4px`. `:focus:not(:focus-visible)` draws nothing; -forced-colors mode uses `Highlight`. Selection is a fill, focus a ring. - -**Why.** `#E53935` on `#911410` measures 2.15:1. - -**Status.** proposed · 2026-09-06. Clarified by D-015 (declared component ring -mappings on fills). Since D-027 a selected row (`#531310`, 3.38:1) takes the -ordinary ring. - -### D-007 Control boundary colour - -**Decision.** `border.control` = `#A3676B` (4.45 / 4.33 / 4.07). - -**Why.** Control boundaries need 3:1 against their surface (WCAG 1.4.11); -`#531310` (1.39) and `#9E231F` (2.56) fail. - -**Alternatives.** `#C81A1A` (3.42): too loud for every input at rest. - -**Status.** proposed · 2026-09-06. - -### D-008 Hairlines, sunken surface, overlay border - -**Decision.** The site's six near-identical hairlines (`#290D0C`, `#24100F`, -`#321110`, `#38100F`, `#190B0B`, `#2B0E0D`) fold into `border.divider` = -`#2B0E0D`. `#0A0707` becomes `surface.sunken`. Every floating layer (dialog, -drawer, menu, popover, toast) takes a 1px `border.overlay` = `#E53935`. - -**Consequences.** The dunst frame `#AE1914` survives only in `heritage-ansi`. - -**Status.** proposed · 2026-09-06. - -### D-009 Density modes - -**Decision.** Density modes are tokens, set with `data-density` on any subtree. -`compact` matches the site: control 24px, row 28px, UI type 12/16, icon 16, list -gap 2. `comfortable`: control 32px, row 36px, UI type 13/18, icon 16, list gap -4. - -**Consequences.** Both meet the 24×24 CSS-pixel target minimum; `compact` needs -4px between adjacent targets. - -**Status.** proposed · 2026-09-06. - ### D-010 Deployment source **Decision.** The site deploys from `main` through GitHub Actions after the full @@ -8261,223 +8198,138 @@ profiles are historical-only; deprecated or heritage roles cannot be newly mapped in an approved profile, and no substitute is implied. Observed/approved roles are usable within their documented scope; primitives are inspection-only. Release version, profile status, role status, deprecation and eligibility are -separate facts; the generator emits the policy and eligibility metadata. +separate facts; the generator emits the policy and eligibility metadata. This +governs consumption only: no pending value is approved, and D-005 through D-012 +are unchanged. **Why.** Issue #4 found conflicting instructions to use and to prohibit pending -roles in the approved default profile. - -**Consequences.** Governs consumption only: no pending value is approved, and -D-005 through D-012 are unchanged. - -**Alternatives.** Block pending roles until individually approved. +roles in the approved default profile; blocking them until each is approved was +the alternative. **Status.** proposed · 2026-09-07 (formal log status remains owner-controlled). Owner direction, 2026-09-07, in Phase 1 planning: "Use and report", and "Block new use" for deprecated roles; implementation authorized. -### D-014 Automatic inline literal color previews +### D-028 Merge gates and the deployment gate are different suites -**Decision.** Every visible CSS hex literal on the spec page gets one generated -preview; the literal stays exact and is data, never inferred from a token or -screenshot. The preview is 16px with its theme-derived 1px boundary, circular at -rest; on CSS `:hover` it scales to 17.4px with radius zero (fast duration token -and ease-out on transform and border-radius; none under reduced motion). Alpha -shows over a checkerboard of theme tokens. Only this preview may use rounded -geometry, patterned gradient backgrounds and border-radius animation. Text, -copying, keyboard order and no-JS access stay intact. Syntax specimens `#f00`, -`#f008`, `#ff0000`, `#ff000080`, `#000000`, `#ffffff` (literal data, not roles) -also test copy fidelity and transparent, dark and light previews in the browser -suite. +**Decision.** The full browser and packed-consumer matrix gates deployment, not +merging; it runs on `main` before `deploy` and on demand through the workflow +dispatch. A subset never writes evidence: it uses the plain list reporter, +because the evidence reporter would mark unselected tests not run and publish a +matrix that only looked complete. Packed consumers move with the browser suite, +which republishes their evidence against the deployed package; +`scripts/ui-verification-report.mjs` requires the complete protocol on all three +engines. No mandatory local gate: `npm run test:all` is recommended, never +verified; the practice is recorded in `AGENTS.md`. As first recorded, pull +requests merged on `validate`, `build` and a `smoke` job (desktop project; page, +portal, button and text-field specs; plain list reporter), which is never a +coverage claim. -**Why.** Issue #1 asks for circular previews and a transparency checkerboard, -against the square and no-gradient rules. +**Why.** Accepting D-026 and D-027 cost 29.5 minutes of CI before merge, 84% of +it the browser matrix: pure latency on a public repository. A browser failure +stops publication, not a correct merge; a local receipt proves only that +something wrote it. Sharding before merge (about six minutes, partial evidence +files) and consumers on the merge path were rejected. -**Consequences.** Literal-data presentation only: no new palette, semantic role -or geometry rule. +**Status.** accepted · 2026-09-11 · owner: merges gate on a few minutes of +checks, the full matrix gates deployment, a local full run stays recommended. +Superseded in part by D-031 (path-selected pull-request checks, a sharded +deployment matrix with one evidence report, `release-gate` as the only required +check); the rules above still hold. -**Status.** proposed · 2026-09-07 (formal log status remains owner-controlled). -Owner direction, 2026-09-07: the narrow exception explicitly approved, -implementation authorized. +### D-031 Select the checks a change needs; shard the deployment matrix -#### Follow the pointer hovering effect +**Decision.** CI is `select` → checks → `release-gate`. -Part of this exception only; the tooltip and focus contracts are unchanged. -Mouse and pen pointers open a non-interactive popup with the exact value; touch -and unknown pointers do not. CSS `:hover` alone drives the morph; neither uses -the `hover` or `any-hover` media features, which can report no hover despite -mouse input. The popup follows the pointer inside the circle at an 8px gap, -flips when necessary and stays within an 8px viewport gutter, bounded by the -viewport. It closes at once when the pointer leaves the circle, on an outside -press, Escape or loss of window focus, and after page or nested-container -scrolling unless the same circle is still under the last pointer position. It -cannot capture input or hold itself open and adds no keyboard stop; token tables -and the keyboard-accessible token inspector keep the persistent information and -links. Tracking has no animation or easing, even under reduced motion. Circles -and literal text stay visible without JavaScript. +- `select` reads the changed paths and `scripts/ci/proofs.json`; a path gets + cheaper only when a rule claims it. Unclaimed paths and control files + (workflows, the selector and registry, `package.json`, the lockfile, the + Playwright configs) run every check: a broad rule is a floor, never a verdict. + On a pull request the base commit's control list also applies, so a change + cannot make itself cheaper; review protects the selector. A file a browser + spec imports runs that spec and counts as a site change. +- Unit tests and the build run in parallel. A pull request runs only the + selected checks; browser subsets write no evidence (D-028). +- A push to `main` that changes the site runs the whole matrix: browser projects + split into jobs (desktop in four parts; projects read from the Playwright + config) whose blob reports merge once into the evidence reporter, with packed + consumers in parallel. The merge needs every shard passed and reported; a + check refuses evidence missing any configured test in any project. Then the + verification report and deployment; no site change, no deployment. Changed + paths count from the last commit that reached Pages, so a failed deploy is + counted again. +- `release-gate`, the only required check, recomputes the plan from Git with the + same code, refuses a mismatch, and checks each job ran exactly as planned and + passed. +- `fullyParallel`, two workers per CI job, zero retries. The page axe scan is + two tests (colour contrast; every other rule) from a tag-based run, together + exactly the tagged rules. Only `playwright test` with nothing narrowing or + listing it, or the merge of every shard, writes evidence; the counting check + runs no reporter and proves the evidence file unchanged. -### D-015 Clarify component mappings exposed by consumption acceptance +**Why.** `main` ran every check whatever changed: a terminal-kit-only change, +which the site never reads, took 63 minutes to deploy, and the browser suite ran +on one worker for 24.7 minutes. Shards now write blob reports merged into one +report, so D-028's objection to sharding no longer applies. Rejected: a +self-hosted runner (fork pull requests could run code on it), reusing +pull-request evidence on `main` (the build stamps the commit), Playwright's +internal shard weights (not public). -**Decision.** Keep current component appearance and all token values. Ordinary -confirmation uses the primary tone; destructive tone is for destructive actions, -whatever the confirmation's semantic role. A pressed primary button keeps -`color.action.primary.border`, secondary and tertiary use `color.border.active`, -destructive keeps its declared border; the generic metadata is corrected to -match. Controls keep their documented ring mappings (primary and -checked/selected fills: `color.interaction.focus.ring-container` where declared; -destructive fills: their on-fill text role). The global wording points to them, -keeping ring geometry, forced-colors behavior and every contrast floor. +**Status.** accepted · 2026-09-26 · owner, who found thirty-minute runs on +`main` unacceptable and asked for classified checks modelled on theselfish.one. +Supersedes D-028 in part. -**Why.** Phase 2's independently reviewed composed acceptance preserved these -three contradictions; Phase 3 controls must not present an arbitrary -interpretation as canonical. +### D-001 Controlled three-hue extension -**Consequences.** No profile or pending-token approval; historical acceptance -reports stay historical evidence. +**Decision.** `default` adds three desaturated, warm-shifted hues: amber +`#C9973F` (warning, modified), green `#86A46F` (success, added), blue `#7E9EBB` +(info); dark tints `#1F1A0C`, `#0F1A0E`, `#0F141C`. They appear only in +`status`, `diagnostic` and `diff` (plus `code`, `terminal` and `chart` in +`extended`), never in `surface`, `text`, `border`, `interaction` or `action`. No +purple, cyan or magenta. Every status role also has a glyph, underline pattern +or border style. `default` syntax stays monochrome; `extended` stays `proposed`. -**Alternatives.** Enforce the generic prose everywhere, or mark affected -workbench configurations unresolved. +**Why.** Lightness alone cannot separate diagnostics, diffs and status (a +200-line diff cannot be scanned by glyph); the owner's PhpStorm scheme already +uses such hues. Measured contrast is in `exports/contrast.md`. -**Status.** proposed · 2026-09-07. The owner directed application on 2026-09-07; -formal status remains owner-managed. +**Status.** accepted · 2026-09-06 · owner. Superseded in part by D-030 (opt-in +`code.hued.*`; `code.syntax.*` stays monochrome). -### D-016 Pinned release comparison report and historical rendering +### D-003 Text-role corrections -**Decision.** A report (schema version 1) records both immutable revisions, -profile and input digests, separate semantic change categories, explicit -dependency evidence and unsupported historical inputs. Reports and historical -specimen renderings are build artifacts in `dist/releases/`; canonical exports -keep their contract. History is read from Git, never executed as a build or -imported as a module. The shared specimen renderer draws each side's maintained -markup and styles (documented renderer version, matched conditions): a -reconstructed reference, not evidence that an old site's JavaScript or an -external port ran. Browser captures are run evidence with environment and -artifact hashes; missing evidence stays not run. A rename needs an explicit -mapping naming both revisions; equal values do not establish one. +**Decision.** `text.subtle` = `#AD7175` for metadata, comments and line numbers. +`text.disabled` = `#8A5559` (exempt under WCAG 1.4.3, at least 3:1 by house +policy). `#A3676B` stays as `border.control`, `icon.decorative`, +`status.neutral.fill` and `chart.series.4` (non-text, at least 3:1); `#7D1310` +only as `border.disabled`, `code.whitespace` and minor grid lines, never text. +`heritage-ansi` keeps the original assignments, flagged `$deprecated`. -**Why.** Run metadata must stay out of deterministic exports, and missing -historical fields must not be read by today's rules. +**Why.** `#A3676B` (the site's `--quiet`) measures 4.45:1 on `#0C0909` and +`#7D1310` (`--inactive`) 1.86:1, yet the site used `#7D1310` for line numbers; +its suggested `#A8403A` measures only 3.27:1. -**Consequences.** No design values, eligibility rules or verification statuses -change. +**Status.** accepted · 2026-09-06 · owner. -**Alternatives.** A raw file diff (no semantic categories) or running historical -applications (a wider trust boundary). +### D-007 Control boundary colour -**Status.** proposed · 2026-09-08. Issue #2 authorizes derived release -diagnostics; formal status and all theme approvals remain owner-managed. +**Decision.** `border.control` = `#A3676B`. -### D-017 Private framework parity evidence +**Why.** Control boundaries need 3:1 against their surface (WCAG 1.4.11); +`#531310` (1.39) and `#9E231F` (2.56) fail, and `#C81A1A` (3.42) is too loud for +every input at rest. -**Decision.** An independently authored private harness takes an -operator-supplied licensed target and an explicit license review, copies only -declared template inputs into a new private fixture directory, uses synthetic -examples and records exact theme, template, framework, dependency and fixture -identities. The target and its application behavior stay outside its write scope; browser captures, copied -vendor inputs and detailed results stay private; missing prerequisites give -not-run output. +**Status.** proposed · 2026-09-06. -**Consequences.** A successful diagnostic run is not a verified port or a claim -of complete visual parity. +### D-008 Hairlines, sunken surface, overlay border -**Alternatives.** A public vendor copy (breaks the license boundary) or a -generic mock presented as template evidence. +**Decision.** The site's six near-identical hairlines (`#290D0C`, `#24100F`, +`#321110`, `#38100F`, `#190B0B`, `#2B0E0D`) fold into `border.divider` = +`#2B0E0D`. `#0A0707` becomes `surface.sunken`. Every floating layer (dialog, +drawer, menu, popover, toast) takes a 1px `border.overlay` = `#E53935`. The +dunst frame `#AE1914` survives only in `heritage-ansi`. -**Status.** proposed · 2026-09-08. Issue #3 authorizes the harness; approval -statuses and license boundaries are unchanged. - -### D-018 Declared port capabilities and fresh import evidence - -**Decision.** Optional `capabilities.json` refines each mapped/unmapped role -into mapped, inherited, unsupported, out-of-scope or not-implemented, with a -surface and reason; legacy unmapped reasons stay unclassified, never guessed. -Import verification is separate from mapping state and declared status: verified -output needs a recorded real-import protocol bound to current target metadata, -canonical tokens, mappings, capabilities and artifact bytes. Relevant changes -make evidence stale; failed or missing checks cannot pass. One generated -catalogue feeds summaries, drill-downs and task kits; private parity records -never enter it automatically. - -**Alternatives.** A hand-maintained support matrix, or a parse treated as an -import. - -**Status.** proposed · 2026-09-08. Issue #14 authorizes a derived mapping -explorer; it creates no port, changes no host capability and approves no -profile. - -### D-019 One-way namespaced Figma Variables bridge - -**Decision.** An explicit pinned revision supplies colors and scalar -spacing/radius values, one way. Aliases keep their dependency structure; -dependency-only primitives are hidden from property pickers; unsupported types -and non-approved profiles are reported. One collection and one mode avoid -assuming paid mode capabilities. Dry-run is read-only, apply explicit; import -receipts identify owned IDs and their last observed values; conflicts and manual -edits stop an update or rollback. The bridge never stores ownership in -unsupported plugin data, overwrites unrelated variables or writes back to the -repository. - -**Alternatives.** Manual duplicate maintenance, a paid-only REST workflow, or -flattening aliases/composites. - -**Status.** proposed · 2026-09-08. Issue #15 authorizes this bounded adapter; -approval and eligibility follow the canonical source. - -### D-020 Bounded local validation and recovery workflow - -**Decision.** One executable pattern: editing, invalid, review, busy, success. -Validation runs on explicit submission, keeps values and shows linked errors; -typing does not rewrite live announcements. Review can return to a field; -confirm enters busy, a separate local simulation-completion event enters -success, and no request is made. The workstation example's reserved name and -hostname are local fixture conflicts, not business policy. The contract pins -constituent component content digests and reports automated evidence apart from -manual screen-reader acceptance. - -**Alternatives.** A color-only invalid snapshot, validation on every keystroke, -or a submit click treated as a successful save. - -**Status.** proposed · 2026-09-08. Issue #16 authorizes one pattern from -existing admin-form, field, alert and button rules, without new palette roles. - -### D-021 Local form composition with versioned data - -**Decision.** Five canonical field kinds can be added, edited, removed and -reordered with buttons. Definitions, preview values and validation state are -separate. JSON imports have closed fields, bounded size/counts and unique stable -IDs; a failed import changes nothing. Content identity pins the supplying theme -and component contracts; downloads hold definitions, never entered values. -Rendering and validation reuse D-020. - -**Consequences.** A draft reference component, not a backend platform or native -port. - -**Alternatives.** Arbitrary HTML/schema execution, a conditional workflow -engine, or a second field implementation. - -**Status.** proposed · 2026-09-08. Issue #19 authorizes the deferred -form-builder demonstration. - -### D-022 Local visual selection before agent implementation distribution - -**Decision.** Before canonicalization a local harness compares exactly three -explicit token overlays with Current, using shared specimen rendering and an -original Vue composition. Overlays, reports and review builds stay ignored, -never public profiles or delivery artifacts. The existing alias resolver and -unrounded contrast engine judge candidates without changing canonical values, -historical ANSI slots or waivers. Numbers and browser evidence approve nothing: -the owner selects a concrete candidate before foundation freeze, mass -productization or deployment. See `docs/phase6-visual-review.md`. - -**Why.** Agents need installable or copyable components and compositions with -complete dependencies and pinned contracts, shared by the future package, -documentation portal and Vue application. - -**Alternatives.** Productizing the old palette first, unapproved preview -profiles, or appearance-only snippets. - -**Status.** proposed · 2026-09-08. Issue #37 and the owner's implementation -instruction authorize three local candidates; design approval remains -owner-managed. The selection is D-023. +**Status.** proposed · 2026-09-06. ### D-023 True Black / Rose canonical foundation @@ -8488,94 +8340,34 @@ panels use `#100c0c`. The two new values become `color.primitive.ink.14` and Everything else stays exactly as reviewed (rose/white foreground, red actions, focus, borders, selections, status and chart roles); raised/overlay stay `#241010`, alternate chrome `#1c0a09`. The historical profile keeps its previous -surfaces. +surfaces. This approves these surfaces only, not other pending decisions, new +colors or accessibility waivers; the A–I candidate reviews stay historical local +evidence, not public profiles. It ships in 1.0.0 under the major-version rule; +existing pins stay immutable. **Why.** The owner explicitly selected the reviewed candidate I: "use the True Black / Rose theme and make it permanent for j3w1/theme". -**Consequences.** Approves these surfaces only, not other pending decisions, new -colors or accessibility waivers. The rejected A/B/C, revised D/E/F and final -G/H/I reviews are historical local evidence, not public profiles. Foundation for -the Phase 6 package, copy distributions, static portal and Vue showcase; ships -in 1.0.0 under the major-version rule, existing pins immutable. - **Status.** accepted · 2026-09-08 · owner, who also authorized the remaining Phase 6 implementation. Superseded in part only: D-024 (`text.link`), D-026 (`action.primary.bg`), D-027 (`surface.raised`, `interaction.selection.bg`, `text.placeholder`). -### D-024 Distinguish links from body text and headings - -**Decision.** `color.text.link` maps to the existing strong red `#f73f35`, -keeping the persistent red underline and near-white hover text on the strong -dark-red hover fill. Visited links keep color and underline; current-page and -selected navigation keep their on-fill roles; body and heading colors are -unchanged. - -**Why.** In the implementation preview the owner asked for links more -distinguishable from normal text, using different colors. - -**Consequences.** No new primitive, status hue, contrast exception or focus -rule; the historical profile keeps the old link; ships in the same unreleased -1.0.0. - -**Alternatives.** Bright rose (the heading color) or blue/purple (an unrelated -hue). - -**Status.** accepted · 2026-09-08 · owner, correcting D-023 for links only. -D-027 later moves link hover to `interaction.hover.bg`. - -### D-025 Theme interactive controls throughout the portal and demo - -**Decision.** The maintained select renders its single-choice popup and -multiple-choice list in theme-owned DOM with the existing selection, surface, -text, border and focus roles; the native select remains the form-value and -constraint source and the no-JavaScript fallback. It follows the select-only -combobox and multiple listbox keyboard patterns, keeps labels, disabled -options/fieldsets, native input/change events, defaults and form reset, and -documents its tested scope. The same enhancement serves existing application -controls, the portal, the Vue demo, consumption docs and copy closures; input, -button, checkbox, radio, range and file chrome is themed too. Date inputs get a -theme-owned text editor and calendar, time inputs text entry and theme-owned -step buttons; native inputs keep constraints and values. Browser-owned system dialogs and -no-JavaScript fallbacks stay native, without platform hacks; native ports keep -their mappings. The command field fills its dialog width below its label. - -**Why.** Seeing native blue selections in the work board and agent-kit picker, -the owner explicitly instructed: "replace mostly all native components like -`` we must use all j3w1 themed", and asked for a properly proportioned +command-search field. Advisory option CSS keeps the blue selection; one-off +dropdowns duplicate behavior. + +**Status.** accepted · 2026-09-09 · owner. + +### D-016 Pinned release comparison report and historical rendering + +**Decision.** A report (schema version 1) records both immutable revisions, +profile and input digests, separate semantic change categories, explicit +dependency evidence and unsupported historical inputs. Reports and historical +specimen renderings are build artifacts in `dist/releases/`; canonical exports +keep their contract. History is read from Git, never executed as a build or +imported as a module. The shared specimen renderer draws each side's maintained +markup and styles (documented renderer version, matched conditions): a +reconstructed reference, not evidence that an old site's JavaScript or an +external port ran. Browser captures are run evidence with environment and +artifact hashes; missing evidence stays not run. A rename needs an explicit +mapping naming both revisions; equal values do not establish one. No design +values, eligibility rules or verification statuses change. + +**Why.** Run metadata must stay out of deterministic exports, and missing +historical fields must not be read by today's rules. A raw file diff has no +semantic categories; running historical applications widens the trust boundary. + +**Status.** proposed · 2026-09-08. Issue #2 authorizes derived release +diagnostics; formal status and all theme approvals remain owner-managed. + +### D-017 Private framework parity evidence + +**Decision.** An independently authored private harness takes an +operator-supplied licensed target and an explicit license review, copies only +declared template inputs into a new private fixture directory, uses synthetic +examples and records exact theme, template, framework, dependency and fixture +identities. The target and its application behavior stay outside its write +scope; browser captures, copied vendor inputs and detailed results stay private; +missing prerequisites give not-run output. A successful diagnostic run is not a +verified port or a claim of complete visual parity. + +**Why.** A public vendor copy breaks the license boundary, and a generic mock +would be presented as template evidence. + +**Status.** proposed · 2026-09-08. Issue #3 authorizes the harness; approval +statuses and license boundaries are unchanged. + +### D-019 One-way namespaced Figma Variables bridge + +**Decision.** An explicit pinned revision supplies colors and scalar +spacing/radius values, one way. Aliases keep their dependency structure; +dependency-only primitives are hidden from property pickers; unsupported types +and non-approved profiles are reported. One collection and one mode avoid +assuming paid mode capabilities. Dry-run is read-only, apply explicit; import +receipts identify owned IDs and their last observed values; conflicts and manual +edits stop an update or rollback. The bridge never stores ownership in +unsupported plugin data, overwrites unrelated variables or writes back to the +repository. + +**Why.** Manual duplicate maintenance, a paid-only REST workflow, and flattening +aliases or composites were the alternatives. + +**Status.** proposed · 2026-09-08. Issue #15 authorizes this bounded adapter; +approval and eligibility follow the canonical source. + +### D-020 Bounded local validation and recovery workflow + +**Decision.** One executable pattern: editing, invalid, review, busy, success. +Validation runs on explicit submission, keeps values and shows linked errors; +typing does not rewrite live announcements. Review can return to a field; +confirm enters busy, a separate local simulation-completion event enters +success, and no request is made. The workstation example's reserved name and +hostname are local fixture conflicts, not business policy. The contract pins +constituent component content digests and reports automated evidence apart from +manual screen-reader acceptance. + +**Why.** A color-only invalid snapshot, validation on every keystroke, or a +submit click treated as a successful save were the alternatives. + +**Status.** proposed · 2026-09-08. Issue #16 authorizes one pattern from +existing admin-form, field, alert and button rules, without new palette roles. + +### D-021 Local form composition with versioned data + +**Decision.** Five canonical field kinds can be added, edited, removed and +reordered with buttons. Definitions, preview values and validation state are +separate. JSON imports have closed fields, bounded size/counts and unique stable +IDs; a failed import changes nothing. Content identity pins the supplying theme +and component contracts; downloads hold definitions, never entered values. +Rendering and validation reuse D-020. A draft reference component, not a backend +platform or native port. + +**Why.** Arbitrary HTML/schema execution, a conditional workflow engine, or a +second field implementation were the alternatives. + +**Status.** proposed · 2026-09-08. Issue #19 authorizes the deferred +form-builder demonstration. + +### D-022 Local visual selection before agent implementation distribution + +**Decision.** Before canonicalization a local harness compares exactly three +explicit token overlays with Current, using shared specimen rendering and an +original Vue composition. Overlays, reports and review builds stay ignored, +never public profiles or delivery artifacts. The existing alias resolver and +unrounded contrast engine judge candidates without changing canonical values, +historical ANSI slots or waivers. Numbers and browser evidence approve nothing: +the owner selects a concrete candidate before foundation freeze, mass +productization or deployment. See `docs/phase6-visual-review.md`. + +**Why.** Agents need installable or copyable components and compositions with +complete dependencies and pinned contracts, shared by the future package, +documentation portal and Vue application. Productizing the old palette first, +unapproved preview profiles, or appearance-only snippets were the alternatives. + +**Status.** proposed · 2026-09-08. Issue #37 and the owner's implementation +instruction authorize three local candidates; design approval remains +owner-managed. The selection is D-023. + +### D-018 Declared port capabilities and fresh import evidence + +**Decision.** Optional `capabilities.json` refines each mapped/unmapped role +into mapped, inherited, unsupported, out-of-scope or not-implemented, with a +surface and reason; legacy unmapped reasons stay unclassified, never guessed. +Import verification is separate from mapping state and declared status: verified +output needs a recorded real-import protocol bound to current target metadata, +canonical tokens, mappings, capabilities and artifact bytes. Relevant changes +make evidence stale; failed or missing checks cannot pass. One generated +catalogue feeds summaries, drill-downs and task kits; private parity records +never enter it automatically. + +**Why.** A hand-maintained support matrix, or a parse treated as an import, were +the alternatives. + +**Status.** proposed · 2026-09-08. Issue #14 authorizes a derived mapping +explorer; it creates no port, changes no host capability and approves no +profile. + +### D-034 Versioned Windows native and Windhawk adapters + +**Decision.** A Windows port uses native settings where sufficient and pinned +Windhawk 2.0 alpha 6 stylers solely as rendering adapters for canonical semantic +tokens: a bounded exception to the unsupported-injection prohibition in +portability. No binary patching, shell replacement, paid tool or third-party +theme is permitted. Unknown shell versions/structures fail closed. Full lifecycle +support includes pinned install/update, verification, original-state restore, +transaction rollback and removal of owned theme assets. User shortcuts, window +management, existing layouts and desktop icons are preserved; cursors and black +wallpaper are included. Native limitations are disclosed, not silently patched. + +**Why.** Native settings cannot represent the full black/rose shell identity, +and the owner explicitly accepted the pinned prerelease to use its upstream CLI. +Private storage edits and UI automation are less reproducible; binary theme +patching was rejected. + +**Status.** accepted · 2026-09-28 · owner, explicit implementation plan approval. + ## References | Reference | Kind | Where | What it does not prove | diff --git a/packages/ui/dist/canonical/admin-form.json b/packages/ui/dist/canonical/admin-form.json index d9c2f0098..b99624816 100644 --- a/packages/ui/dist/canonical/admin-form.json +++ b/packages/ui/dist/canonical/admin-form.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "admin-form", "family": "composed", "maturity": "stable", diff --git a/packages/ui/dist/canonical/alert.json b/packages/ui/dist/canonical/alert.json index b89f74eb8..613807cda 100644 --- a/packages/ui/dist/canonical/alert.json +++ b/packages/ui/dist/canonical/alert.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "alert", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/avatar.json b/packages/ui/dist/canonical/avatar.json index b87bc4ba6..8fb177dac 100644 --- a/packages/ui/dist/canonical/avatar.json +++ b/packages/ui/dist/canonical/avatar.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "avatar", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/badge.json b/packages/ui/dist/canonical/badge.json index e8fb3f1d9..c660e8edf 100644 --- a/packages/ui/dist/canonical/badge.json +++ b/packages/ui/dist/canonical/badge.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "badge", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/breadcrumbs.json b/packages/ui/dist/canonical/breadcrumbs.json index 4ad9f0157..8f76b51f2 100644 --- a/packages/ui/dist/canonical/breadcrumbs.json +++ b/packages/ui/dist/canonical/breadcrumbs.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "breadcrumbs", "family": "navigation", "maturity": "stable", diff --git a/packages/ui/dist/canonical/button-group.json b/packages/ui/dist/canonical/button-group.json index c9ff24fe3..ac743e2f9 100644 --- a/packages/ui/dist/canonical/button-group.json +++ b/packages/ui/dist/canonical/button-group.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "button-group", "family": "actions", "maturity": "stable", diff --git a/packages/ui/dist/canonical/button.json b/packages/ui/dist/canonical/button.json index 09365a973..5caf187ae 100644 --- a/packages/ui/dist/canonical/button.json +++ b/packages/ui/dist/canonical/button.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "button", "family": "actions", "maturity": "stable", diff --git a/packages/ui/dist/canonical/card.json b/packages/ui/dist/canonical/card.json index 32e6c7b3b..ecf5d77ba 100644 --- a/packages/ui/dist/canonical/card.json +++ b/packages/ui/dist/canonical/card.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "card", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/chart.json b/packages/ui/dist/canonical/chart.json index c9589d641..91e5be004 100644 --- a/packages/ui/dist/canonical/chart.json +++ b/packages/ui/dist/canonical/chart.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "chart", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/checkbox.json b/packages/ui/dist/canonical/checkbox.json index 062776314..0b1ec0370 100644 --- a/packages/ui/dist/canonical/checkbox.json +++ b/packages/ui/dist/canonical/checkbox.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "checkbox", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/chip.json b/packages/ui/dist/canonical/chip.json index e3455073c..cc9ef264e 100644 --- a/packages/ui/dist/canonical/chip.json +++ b/packages/ui/dist/canonical/chip.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "chip", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/code-editor.json b/packages/ui/dist/canonical/code-editor.json index e9dfeed82..8f62c5855 100644 --- a/packages/ui/dist/canonical/code-editor.json +++ b/packages/ui/dist/canonical/code-editor.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "code-editor", "family": "developer", "maturity": "stable", diff --git a/packages/ui/dist/canonical/combobox.json b/packages/ui/dist/canonical/combobox.json index 853b48f08..75398e378 100644 --- a/packages/ui/dist/canonical/combobox.json +++ b/packages/ui/dist/canonical/combobox.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "combobox", "family": "forms-advanced", "maturity": "stable", diff --git a/packages/ui/dist/canonical/command-palette.json b/packages/ui/dist/canonical/command-palette.json index 43037bcb9..9296007b6 100644 --- a/packages/ui/dist/canonical/command-palette.json +++ b/packages/ui/dist/canonical/command-palette.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "command-palette", "family": "navigation", "maturity": "stable", diff --git a/packages/ui/dist/canonical/compact-dashboard.json b/packages/ui/dist/canonical/compact-dashboard.json index a4a93d2d4..1f4d14721 100644 --- a/packages/ui/dist/canonical/compact-dashboard.json +++ b/packages/ui/dist/canonical/compact-dashboard.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "compact-dashboard", "family": "composed", "maturity": "stable", diff --git a/packages/ui/dist/canonical/data-table.json b/packages/ui/dist/canonical/data-table.json index cfb7375ef..f84349c46 100644 --- a/packages/ui/dist/canonical/data-table.json +++ b/packages/ui/dist/canonical/data-table.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "data-table", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/date-picker.json b/packages/ui/dist/canonical/date-picker.json index 66f885ab6..435aea5c7 100644 --- a/packages/ui/dist/canonical/date-picker.json +++ b/packages/ui/dist/canonical/date-picker.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "date-picker", "family": "forms-advanced", "maturity": "stable", diff --git a/packages/ui/dist/canonical/description-list.json b/packages/ui/dist/canonical/description-list.json index 3cfa86b3f..41625feaa 100644 --- a/packages/ui/dist/canonical/description-list.json +++ b/packages/ui/dist/canonical/description-list.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "description-list", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/diagnostics.json b/packages/ui/dist/canonical/diagnostics.json index ad8d2b2a6..6ba9e0fe1 100644 --- a/packages/ui/dist/canonical/diagnostics.json +++ b/packages/ui/dist/canonical/diagnostics.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "diagnostics", "family": "developer", "maturity": "stable", diff --git a/packages/ui/dist/canonical/dialog.json b/packages/ui/dist/canonical/dialog.json index e08cffa9e..59af8ad13 100644 --- a/packages/ui/dist/canonical/dialog.json +++ b/packages/ui/dist/canonical/dialog.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "dialog", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/diff-view.json b/packages/ui/dist/canonical/diff-view.json index b6b685ce3..d7a2f1b34 100644 --- a/packages/ui/dist/canonical/diff-view.json +++ b/packages/ui/dist/canonical/diff-view.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "diff-view", "family": "developer", "maturity": "stable", diff --git a/packages/ui/dist/canonical/disclosure.json b/packages/ui/dist/canonical/disclosure.json index b283693d6..b98d6d441 100644 --- a/packages/ui/dist/canonical/disclosure.json +++ b/packages/ui/dist/canonical/disclosure.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "disclosure", "family": "navigation", "maturity": "stable", diff --git a/packages/ui/dist/canonical/drawer.json b/packages/ui/dist/canonical/drawer.json index 2da96c96d..2f845a850 100644 --- a/packages/ui/dist/canonical/drawer.json +++ b/packages/ui/dist/canonical/drawer.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "drawer", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/editor-search.json b/packages/ui/dist/canonical/editor-search.json index c20a77318..70d6c2d47 100644 --- a/packages/ui/dist/canonical/editor-search.json +++ b/packages/ui/dist/canonical/editor-search.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "editor-search", "family": "developer", "maturity": "stable", diff --git a/packages/ui/dist/canonical/empty-state.json b/packages/ui/dist/canonical/empty-state.json index 73066fccb..06075bb9e 100644 --- a/packages/ui/dist/canonical/empty-state.json +++ b/packages/ui/dist/canonical/empty-state.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "empty-state", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/error-state.json b/packages/ui/dist/canonical/error-state.json index d3e8aa202..de1e89b10 100644 --- a/packages/ui/dist/canonical/error-state.json +++ b/packages/ui/dist/canonical/error-state.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "error-state", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/field.json b/packages/ui/dist/canonical/field.json index 422db0182..d1a572914 100644 --- a/packages/ui/dist/canonical/field.json +++ b/packages/ui/dist/canonical/field.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "field", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/fieldset.json b/packages/ui/dist/canonical/fieldset.json index e4207c56e..0a37d71ed 100644 --- a/packages/ui/dist/canonical/fieldset.json +++ b/packages/ui/dist/canonical/fieldset.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "fieldset", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/file-browser.json b/packages/ui/dist/canonical/file-browser.json index 3a2728dc5..d3a073ae9 100644 --- a/packages/ui/dist/canonical/file-browser.json +++ b/packages/ui/dist/canonical/file-browser.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "file-browser", "family": "composed", "maturity": "stable", diff --git a/packages/ui/dist/canonical/file-input.json b/packages/ui/dist/canonical/file-input.json index ef0ebdf9d..7c61f2ecb 100644 --- a/packages/ui/dist/canonical/file-input.json +++ b/packages/ui/dist/canonical/file-input.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "file-input", "family": "forms-advanced", "maturity": "stable", diff --git a/packages/ui/dist/canonical/filterable-table.json b/packages/ui/dist/canonical/filterable-table.json index 4f4972eb9..addce53fb 100644 --- a/packages/ui/dist/canonical/filterable-table.json +++ b/packages/ui/dist/canonical/filterable-table.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "filterable-table", "family": "composed", "maturity": "stable", diff --git a/packages/ui/dist/canonical/form-builder.json b/packages/ui/dist/canonical/form-builder.json index 05f599f70..0875f0a4f 100644 --- a/packages/ui/dist/canonical/form-builder.json +++ b/packages/ui/dist/canonical/form-builder.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "form-builder", "family": "forms-advanced", "maturity": "draft", diff --git a/packages/ui/dist/canonical/i3-window-frame.json b/packages/ui/dist/canonical/i3-window-frame.json index 5f97c9ab6..c030660c9 100644 --- a/packages/ui/dist/canonical/i3-window-frame.json +++ b/packages/ui/dist/canonical/i3-window-frame.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "i3-window-frame", "family": "composed", "maturity": "stable", diff --git a/packages/ui/dist/canonical/icon-button.json b/packages/ui/dist/canonical/icon-button.json index a531d358a..840c93885 100644 --- a/packages/ui/dist/canonical/icon-button.json +++ b/packages/ui/dist/canonical/icon-button.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "icon-button", "family": "actions", "maturity": "stable", diff --git a/packages/ui/dist/canonical/kbd.json b/packages/ui/dist/canonical/kbd.json index f95f82cec..d56b6d41a 100644 --- a/packages/ui/dist/canonical/kbd.json +++ b/packages/ui/dist/canonical/kbd.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "kbd", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/link.json b/packages/ui/dist/canonical/link.json index 4432d9d60..b3afc794d 100644 --- a/packages/ui/dist/canonical/link.json +++ b/packages/ui/dist/canonical/link.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "link", "family": "actions", "maturity": "stable", diff --git a/packages/ui/dist/canonical/list.json b/packages/ui/dist/canonical/list.json index ee36d4e78..fbb3e14cd 100644 --- a/packages/ui/dist/canonical/list.json +++ b/packages/ui/dist/canonical/list.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "list", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/loading-indicator.json b/packages/ui/dist/canonical/loading-indicator.json index 4fd9e2a5c..c17ccd4e4 100644 --- a/packages/ui/dist/canonical/loading-indicator.json +++ b/packages/ui/dist/canonical/loading-indicator.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "loading-indicator", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/menu.json b/packages/ui/dist/canonical/menu.json index 01aa7ef1d..442a4968c 100644 --- a/packages/ui/dist/canonical/menu.json +++ b/packages/ui/dist/canonical/menu.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "menu", "family": "navigation", "maturity": "stable", diff --git a/packages/ui/dist/canonical/multiselect.json b/packages/ui/dist/canonical/multiselect.json index 978d31ad5..c19f765f4 100644 --- a/packages/ui/dist/canonical/multiselect.json +++ b/packages/ui/dist/canonical/multiselect.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "multiselect", "family": "forms-advanced", "maturity": "stable", diff --git a/packages/ui/dist/canonical/number-field.json b/packages/ui/dist/canonical/number-field.json index bfe51d25a..fe690652d 100644 --- a/packages/ui/dist/canonical/number-field.json +++ b/packages/ui/dist/canonical/number-field.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "number-field", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/pagination.json b/packages/ui/dist/canonical/pagination.json index 597aae01a..b9f8696fb 100644 --- a/packages/ui/dist/canonical/pagination.json +++ b/packages/ui/dist/canonical/pagination.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "pagination", "family": "navigation", "maturity": "stable", diff --git a/packages/ui/dist/canonical/popover.json b/packages/ui/dist/canonical/popover.json index f675faca6..9009dc0c8 100644 --- a/packages/ui/dist/canonical/popover.json +++ b/packages/ui/dist/canonical/popover.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "popover", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/progress.json b/packages/ui/dist/canonical/progress.json index 590a3996a..3451e3b67 100644 --- a/packages/ui/dist/canonical/progress.json +++ b/packages/ui/dist/canonical/progress.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "progress", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/radio-group.json b/packages/ui/dist/canonical/radio-group.json index af3e3f65d..dfb208091 100644 --- a/packages/ui/dist/canonical/radio-group.json +++ b/packages/ui/dist/canonical/radio-group.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "radio-group", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/range.json b/packages/ui/dist/canonical/range.json index b29548f1a..7c395d9c6 100644 --- a/packages/ui/dist/canonical/range.json +++ b/packages/ui/dist/canonical/range.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "range", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/repeater.json b/packages/ui/dist/canonical/repeater.json index 92632a4bb..c6225ff54 100644 --- a/packages/ui/dist/canonical/repeater.json +++ b/packages/ui/dist/canonical/repeater.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "repeater", "family": "forms-advanced", "maturity": "stable", diff --git a/packages/ui/dist/canonical/search-field.json b/packages/ui/dist/canonical/search-field.json index 4ce060cc1..604ee375a 100644 --- a/packages/ui/dist/canonical/search-field.json +++ b/packages/ui/dist/canonical/search-field.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "search-field", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/segmented-control.json b/packages/ui/dist/canonical/segmented-control.json index e08fc9601..ab01ed966 100644 --- a/packages/ui/dist/canonical/segmented-control.json +++ b/packages/ui/dist/canonical/segmented-control.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "segmented-control", "family": "actions", "maturity": "stable", diff --git a/packages/ui/dist/canonical/select.json b/packages/ui/dist/canonical/select.json index 715260847..18463c9ec 100644 --- a/packages/ui/dist/canonical/select.json +++ b/packages/ui/dist/canonical/select.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "select", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/settings-panel.json b/packages/ui/dist/canonical/settings-panel.json index 0d365f760..296529fb9 100644 --- a/packages/ui/dist/canonical/settings-panel.json +++ b/packages/ui/dist/canonical/settings-panel.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "settings-panel", "family": "composed", "maturity": "stable", diff --git a/packages/ui/dist/canonical/sidebar-nav.json b/packages/ui/dist/canonical/sidebar-nav.json index fb4dad9bf..b3e994688 100644 --- a/packages/ui/dist/canonical/sidebar-nav.json +++ b/packages/ui/dist/canonical/sidebar-nav.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "sidebar-nav", "family": "navigation", "maturity": "stable", diff --git a/packages/ui/dist/canonical/skeleton.json b/packages/ui/dist/canonical/skeleton.json index e9101ab3e..ee4ef28c9 100644 --- a/packages/ui/dist/canonical/skeleton.json +++ b/packages/ui/dist/canonical/skeleton.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "skeleton", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/skip-link.json b/packages/ui/dist/canonical/skip-link.json index eb5f58930..081d99298 100644 --- a/packages/ui/dist/canonical/skip-link.json +++ b/packages/ui/dist/canonical/skip-link.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "skip-link", "family": "navigation", "maturity": "stable", diff --git a/packages/ui/dist/canonical/switch.json b/packages/ui/dist/canonical/switch.json index 3e5bb8974..256e5fd9c 100644 --- a/packages/ui/dist/canonical/switch.json +++ b/packages/ui/dist/canonical/switch.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "switch", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/table.json b/packages/ui/dist/canonical/table.json index a4ff2f9d6..2d7c4baaf 100644 --- a/packages/ui/dist/canonical/table.json +++ b/packages/ui/dist/canonical/table.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "table", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/tabs.json b/packages/ui/dist/canonical/tabs.json index 865b1b258..aba1c33e2 100644 --- a/packages/ui/dist/canonical/tabs.json +++ b/packages/ui/dist/canonical/tabs.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "tabs", "family": "navigation", "maturity": "stable", diff --git a/packages/ui/dist/canonical/terminal.json b/packages/ui/dist/canonical/terminal.json index f7e9bba1a..960592e7e 100644 --- a/packages/ui/dist/canonical/terminal.json +++ b/packages/ui/dist/canonical/terminal.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "terminal", "family": "developer", "maturity": "stable", diff --git a/packages/ui/dist/canonical/text-field.json b/packages/ui/dist/canonical/text-field.json index 719e1ea0c..9760fb66c 100644 --- a/packages/ui/dist/canonical/text-field.json +++ b/packages/ui/dist/canonical/text-field.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "text-field", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/textarea.json b/packages/ui/dist/canonical/textarea.json index e28cba603..63d57598a 100644 --- a/packages/ui/dist/canonical/textarea.json +++ b/packages/ui/dist/canonical/textarea.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "textarea", "family": "forms-basic", "maturity": "stable", diff --git a/packages/ui/dist/canonical/time-picker.json b/packages/ui/dist/canonical/time-picker.json index 9621c6b91..c4f67245a 100644 --- a/packages/ui/dist/canonical/time-picker.json +++ b/packages/ui/dist/canonical/time-picker.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "time-picker", "family": "forms-advanced", "maturity": "stable", diff --git a/packages/ui/dist/canonical/timeline.json b/packages/ui/dist/canonical/timeline.json index 65d07dcf2..62bb66ba8 100644 --- a/packages/ui/dist/canonical/timeline.json +++ b/packages/ui/dist/canonical/timeline.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "timeline", "family": "display", "maturity": "stable", diff --git a/packages/ui/dist/canonical/toast.json b/packages/ui/dist/canonical/toast.json index e628b3eb1..6c6af299a 100644 --- a/packages/ui/dist/canonical/toast.json +++ b/packages/ui/dist/canonical/toast.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "toast", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/toolbar.json b/packages/ui/dist/canonical/toolbar.json index 4ce267549..0bc86e21d 100644 --- a/packages/ui/dist/canonical/toolbar.json +++ b/packages/ui/dist/canonical/toolbar.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "toolbar", "family": "navigation", "maturity": "stable", diff --git a/packages/ui/dist/canonical/tooltip.json b/packages/ui/dist/canonical/tooltip.json index 0037674f6..d8b337596 100644 --- a/packages/ui/dist/canonical/tooltip.json +++ b/packages/ui/dist/canonical/tooltip.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "tooltip", "family": "feedback", "maturity": "stable", diff --git a/packages/ui/dist/canonical/tree.json b/packages/ui/dist/canonical/tree.json index f84767084..1bcfdec76 100644 --- a/packages/ui/dist/canonical/tree.json +++ b/packages/ui/dist/canonical/tree.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "tree", "family": "navigation", "maturity": "stable", diff --git a/packages/ui/dist/canonical/wizard.json b/packages/ui/dist/canonical/wizard.json index 54bce18a8..7e13b51e0 100644 --- a/packages/ui/dist/canonical/wizard.json +++ b/packages/ui/dist/canonical/wizard.json @@ -9,7 +9,7 @@ "stability": "release", "policy": "Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens." }, - "sourceDigest": "sha256-A8qTv0rg9VovOZiB0cmF8A7kuS2/y4E3gJfch4++GQc=", + "sourceDigest": "sha256-zzZItSumsAAETA+ATMP7+E7s8lzcnvGPpaU3VwNZByg=", "id": "wizard", "family": "forms-advanced", "maturity": "stable", diff --git a/packages/ui/dist/chunks/form-builder-C5Kx5G9b.js b/packages/ui/dist/chunks/form-builder-BXNafoR0.js similarity index 99% rename from packages/ui/dist/chunks/form-builder-C5Kx5G9b.js rename to packages/ui/dist/chunks/form-builder-BXNafoR0.js index 28f2bf5b9..fdc087250 100644 --- a/packages/ui/dist/chunks/form-builder-C5Kx5G9b.js +++ b/packages/ui/dist/chunks/form-builder-BXNafoR0.js @@ -69,7 +69,7 @@ var identity_default = { name: "j3w1-theme", version: "4.0.0", profile: "default", - sourceDigest: "sha256-KNf9QNXsLy6MzEixJdv+LTT8TglJJgE7H0JwMdzpjfA=" + sourceDigest: "sha256-nnm9r459tJeHedlg/g0yPDBGXgbqNrXKLizmpFZhVHc=" }; //#endregion //#region packages/ui/src/internal/form-builder.js diff --git a/packages/ui/dist/chunks/form-builder-C6Rhfsz6.js b/packages/ui/dist/chunks/form-builder-CFAdHM30.js similarity index 92% rename from packages/ui/dist/chunks/form-builder-C6Rhfsz6.js rename to packages/ui/dist/chunks/form-builder-CFAdHM30.js index 2daa2e07f..8cd7653ca 100644 --- a/packages/ui/dist/chunks/form-builder-C6Rhfsz6.js +++ b/packages/ui/dist/chunks/form-builder-CFAdHM30.js @@ -1,5 +1,5 @@ import { t as J3w1Element } from "./element-C1XeXVYC.js"; -import { t as mountBuilder } from "./form-builder-C5Kx5G9b.js"; +import { t as mountBuilder } from "./form-builder-BXNafoR0.js"; //#region packages/ui/src/behaviors/form-builder.js function formBuilder(root, { signal }) { const editor = root.querySelector("[data-builder]"); @@ -22,7 +22,7 @@ function formBuilder(root, { signal }) { var J3w1FormBuilder = class extends J3w1Element { static componentId = "form-builder"; static version = "4.0.0"; - static implementationId = "sha256-uXS+kL7KbvfhlApDhEsvMY+pFsX9bHFlaTF/qUH94mE="; + static implementationId = "sha256-vKyI+0g8XcrrlnXb8VDRupYyXO+a97JyfcRi2HdehXU="; static connect = formBuilder; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/form-builder.js b/packages/ui/dist/components/form-builder.js index a3969b6cb..dcf7d7c5e 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-C6Rhfsz6.js"; +export { t as J3w1FormBuilder } from "../chunks/form-builder-CFAdHM30.js"; diff --git a/packages/ui/dist/contracts/form-builder.json b/packages/ui/dist/contracts/form-builder.json index 2215d7496..12b1adbed 100644 --- a/packages/ui/dist/contracts/form-builder.json +++ b/packages/ui/dist/contracts/form-builder.json @@ -878,6 +878,6 @@ "copy": { "directory": "copy/form-builder/", "manifest": "copy/form-builder/manifest.json", - "digest": "sha256-/AJpK7InIcUrx5C6r4HWc3McmNfuSvcN0bFFLRwFx7s=" + "digest": "sha256-9aRIMGPvfRblC+UVdvgeFSHxQT8ygF8qBODdlM14PgY=" } } diff --git a/packages/ui/dist/copy/form-builder/manifest.json b/packages/ui/dist/copy/form-builder/manifest.json index 76ce18794..7ad9af41e 100644 --- a/packages/ui/dist/copy/form-builder/manifest.json +++ b/packages/ui/dist/copy/form-builder/manifest.json @@ -7,17 +7,17 @@ "register/form-builder.js", "chunks/element-C1XeXVYC.js", "chunks/choice-Db_w_BOQ.js", - "chunks/form-builder-C6Rhfsz6.js", - "chunks/form-builder-C5Kx5G9b.js", + "chunks/form-builder-CFAdHM30.js", + "chunks/form-builder-BXNafoR0.js", "chunks/form-workflow-DMGni-Gs.js", "chunks/markup-DeQ4bEMR.js" ], "files": { - "runtime/register/form-builder.js": "sha256-eM9TDYrxREfT+vaywPQ8TCrx3X7gAB/fXuj8viaqKzM=", + "runtime/register/form-builder.js": "sha256-ta0PUDz9X2i0VKy4mwKJqBn3NfRFb9jNbF78CN+VcYo=", "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/chunks/form-builder-C6Rhfsz6.js": "sha256-CnwUvLr0BCPWw5F9dlDy1D8Y73slv5huNge/LK40+x8=", - "runtime/chunks/form-builder-C5Kx5G9b.js": "sha256-H2Zi4dAojDJ5ZF7OQWEPsPaCg3kMBiAVVG1k948Yiuw=", + "runtime/chunks/form-builder-CFAdHM30.js": "sha256-stH+t/FIyVK7blEckA4XVttW9mAr1vzzlGWcMd9NNLA=", + "runtime/chunks/form-builder-BXNafoR0.js": "sha256-JPPVR551hu9AB60j2KwrBP3ghYI/TNxgkLZcR09PddA=", "runtime/chunks/form-workflow-DMGni-Gs.js": "sha256-g3g/Afxx3XsClDK4ZfvWQjZKprT6z7Qp1lULS48F0rY=", "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", diff --git a/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-C5Kx5G9b.js b/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-BXNafoR0.js similarity index 99% rename from packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-C5Kx5G9b.js rename to packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-BXNafoR0.js index 28f2bf5b9..fdc087250 100644 --- a/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-C5Kx5G9b.js +++ b/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-BXNafoR0.js @@ -69,7 +69,7 @@ var identity_default = { name: "j3w1-theme", version: "4.0.0", profile: "default", - sourceDigest: "sha256-KNf9QNXsLy6MzEixJdv+LTT8TglJJgE7H0JwMdzpjfA=" + sourceDigest: "sha256-nnm9r459tJeHedlg/g0yPDBGXgbqNrXKLizmpFZhVHc=" }; //#endregion //#region packages/ui/src/internal/form-builder.js diff --git a/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-C6Rhfsz6.js b/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-CFAdHM30.js similarity index 92% rename from packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-C6Rhfsz6.js rename to packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-CFAdHM30.js index 2daa2e07f..8cd7653ca 100644 --- a/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-C6Rhfsz6.js +++ b/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-CFAdHM30.js @@ -1,5 +1,5 @@ import { t as J3w1Element } from "./element-C1XeXVYC.js"; -import { t as mountBuilder } from "./form-builder-C5Kx5G9b.js"; +import { t as mountBuilder } from "./form-builder-BXNafoR0.js"; //#region packages/ui/src/behaviors/form-builder.js function formBuilder(root, { signal }) { const editor = root.querySelector("[data-builder]"); @@ -22,7 +22,7 @@ function formBuilder(root, { signal }) { var J3w1FormBuilder = class extends J3w1Element { static componentId = "form-builder"; static version = "4.0.0"; - static implementationId = "sha256-uXS+kL7KbvfhlApDhEsvMY+pFsX9bHFlaTF/qUH94mE="; + static implementationId = "sha256-vKyI+0g8XcrrlnXb8VDRupYyXO+a97JyfcRi2HdehXU="; static connect = formBuilder; static upgradeProperties = [ "disabled", 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 320e671f8..ed03e2df0 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,5 +1,5 @@ import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; -import { t as J3w1FormBuilder } from "../chunks/form-builder-C6Rhfsz6.js"; +import { t as J3w1FormBuilder } from "../chunks/form-builder-CFAdHM30.js"; //#region .cache/ui-build/entries/register/form-builder.js var element = registerElement("j3w1-form-builder", J3w1FormBuilder); //#endregion diff --git a/packages/ui/dist/enhance/form-builder.js b/packages/ui/dist/enhance/form-builder.js index b83cdfef9..73a2b832d 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-C5Kx5G9b.js"; +export { t as mountBuilder } from "../chunks/form-builder-BXNafoR0.js"; diff --git a/packages/ui/dist/index.js b/packages/ui/dist/index.js index e2a7d53b9..e1dcf0979 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-C6Rhfsz6.js"; +import { t as J3w1FormBuilder } from "./chunks/form-builder-CFAdHM30.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 ac123b6ea..e9c2f0853 100644 --- a/packages/ui/dist/manifest.json +++ b/packages/ui/dist/manifest.json @@ -12256,11 +12256,11 @@ "copy": { "directory": "copy/form-builder/", "files": { - "runtime/register/form-builder.js": "sha256-eM9TDYrxREfT+vaywPQ8TCrx3X7gAB/fXuj8viaqKzM=", + "runtime/register/form-builder.js": "sha256-ta0PUDz9X2i0VKy4mwKJqBn3NfRFb9jNbF78CN+VcYo=", "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/chunks/form-builder-C6Rhfsz6.js": "sha256-CnwUvLr0BCPWw5F9dlDy1D8Y73slv5huNge/LK40+x8=", - "runtime/chunks/form-builder-C5Kx5G9b.js": "sha256-H2Zi4dAojDJ5ZF7OQWEPsPaCg3kMBiAVVG1k948Yiuw=", + "runtime/chunks/form-builder-CFAdHM30.js": "sha256-stH+t/FIyVK7blEckA4XVttW9mAr1vzzlGWcMd9NNLA=", + "runtime/chunks/form-builder-BXNafoR0.js": "sha256-JPPVR551hu9AB60j2KwrBP3ghYI/TNxgkLZcR09PddA=", "runtime/chunks/form-workflow-DMGni-Gs.js": "sha256-g3g/Afxx3XsClDK4ZfvWQjZKprT6z7Qp1lULS48F0rY=", "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", @@ -12269,7 +12269,7 @@ "element.html": "sha256-vq61pWv0xeMFu0tTsDtRWWpAr16AFefjpz5JTSyF440=", "index.html": "sha256-v74xLbiCzhGoMsKDM8vIO3nwDmWQJymihSOqXqvPlkk=", "README.md": "sha256-MGlPh4CEW6DLecBSj7Ym9ww3NAGe8r5V9uANRpZLY48=", - "manifest.json": "sha256-/AJpK7InIcUrx5C6r4HWc3McmNfuSvcN0bFFLRwFx7s=" + "manifest.json": "sha256-9aRIMGPvfRblC+UVdvgeFSHxQT8ygF8qBODdlM14PgY=" } } }, diff --git a/packages/ui/dist/register/form-builder.js b/packages/ui/dist/register/form-builder.js index 320e671f8..ed03e2df0 100644 --- a/packages/ui/dist/register/form-builder.js +++ b/packages/ui/dist/register/form-builder.js @@ -1,5 +1,5 @@ import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; -import { t as J3w1FormBuilder } from "../chunks/form-builder-C6Rhfsz6.js"; +import { t as J3w1FormBuilder } from "../chunks/form-builder-CFAdHM30.js"; //#region .cache/ui-build/entries/register/form-builder.js var element = registerElement("j3w1-form-builder", J3w1FormBuilder); //#endregion diff --git a/packages/ui/dist/rules/consume.md b/packages/ui/dist/rules/consume.md index 8126df171..2d317fdf9 100644 --- a/packages/ui/dist/rules/consume.md +++ b/packages/ui/dist/rules/consume.md @@ -1,12 +1,10 @@ # Consuming j3w1/theme (for agents and integrators) -This document is for people and agents who apply the theme to another project. -The contributor workflow for this repository is in `AGENTS.md`. - -You are consuming **design data and optional official implementations**. The -consumer project's own instructions (its `AGENTS.md`, `CLAUDE.md`, security, -architecture and operational rules) always win over anything in this -repository. +For people and agents who apply the theme to another project; contributors +to this repository read `AGENTS.md`. You are consuming **design data and +optional official implementations**. The consumer project's own instructions +(its `AGENTS.md`, `CLAUDE.md`, security, architecture and operational rules) +always win over anything in this repository. ## Official web implementations @@ -22,20 +20,19 @@ bundles are also supported. ``` Choose `copy` to own the full source, or `mapping` for a host the package does -not fit. Native hosts need mapping mode. Kits include the canonical contracts, -their dependency closure and the shared accessibility/identity rules. They do +not fit; native hosts need mapping mode. Kits include the canonical contracts, +their dependency closure and the shared accessibility/identity rules; they do not declare your app verified. `docs/ui-consumption.md` has the exact -installation, framework binding and runtime checks. npm publication is an -owner release action; until then, use the release tarball and its published -integrity metadata. For canonical mappings, keep the lock and deviation -workflow below. +installation, framework binding and runtime checks. Until npm publication (an +owner release action), use the release tarball and its published integrity +metadata. Canonical mappings keep the lock and deviation workflow below. ## 0. Pin a revision first -`` is a release tag (`v0.1.0`) or a full 40-character commit SHA. Never -`main`, never a branch name, never "latest". Resolve a tag to its commit before -you read anything, and use the same `` in every URL below. Mixing -revisions breaks the contract. +`` is a release tag (`v0.1.0`) or a full 40-character commit SHA, never +`main`, a branch name or "latest". Resolve a tag to its commit before you read +anything, and use the same `` in every URL below; mixing revisions breaks +the contract. ``` GET https://api.github.com/repos/j3w1/theme/git/ref/tags/ → object.sha @@ -65,10 +62,10 @@ Use the pinned approved default profile. Pending roles in that profile use-and-r The policy block above is generated. Each resolved token lists its pending -decision IDs in `eligibility.decisionIds`, including alias dependencies. -Report those IDs together with any real deviations. Using an authorized -pending value is a disclosure, not an invented substitution. A blocked action -implies no replacement. A profile preview does not authorize delivered work. +decision IDs, alias dependencies included, in `eligibility.decisionIds`; report +them with any real deviations. Using an authorized pending value is a +disclosure, not an invented substitution. A blocked action implies no +replacement, and a profile preview does not authorize delivered work. ## 4. Read only what you need, in this order @@ -81,18 +78,17 @@ https://raw.githubusercontent.com/j3w1/theme//exports/digests.json Optional: `exports/theme.full.md` for the whole specification; `exports/tokens.css` for a ready-made custom-property sheet. The website -`https://j3w1.github.io/theme/` is for visual confirmation only. It is not a -source of values, and screenshots never override tokens. +`https://j3w1.github.io/theme/` is for visual confirmation only, never a source +of values; screenshots never override tokens. ## 5. Inspect the target before changing anything 1. Name the integration kind: `css-vars`, `vuetify`, `tailwind`, `jetbrains-icls`, `gtk-css`, `terminal-16` or `other`. -2. List which specified surfaces the target can express natively, and which - it cannot (for example, a framework with no read-only field style, or a - sixteen-colour terminal that cannot show hover). -3. Anything the target cannot express becomes a documented deviation in step - 7, never an invented approximation. +2. List which specified surfaces the target can and cannot express natively + (for example, no read-only field style, or a sixteen-colour terminal that + cannot show hover). Each one it cannot express becomes a documented + deviation in step 7, never an invented approximation. ## 6. Implement the mapping @@ -104,8 +100,8 @@ source of values, and screenshots never override tokens. - Keep host accessibility at least as strong as before: never remove a focus indicator, never lower a contrast ratio the host already met, never set `outline: none` without drawing the specified ring. -- Radii are 0, borders 1px, the family is monospace. A host that forbids one - of these gets a deviation, not a redesign. +- Radii are 0, borders 1px, the family is monospace; a host that forbids one + gets a deviation, not a redesign. - Selection is a fill; focus is a ring. On fills, the ring takes the colour the component JSON declares for that state (D-015). Status roles keep their glyphs. @@ -118,10 +114,10 @@ source of values, and screenshots never override tokens. ## What you may not do -- Invent, blend, lighten, darken or "harmonise" colours. Use resolved values +- Invent, blend, lighten, darken or "harmonise" colours; use resolved values only. - Use a blocked value, deliver a proposed profile, or leave out the required - pending-decision disclosures. Historical-only values are not approved UI + pending-decision disclosures; historical-only values are not approved UI roles. - Take values from the site's HTML, from screenshots or from memory. - Touch unrelated components, layouts, copy, dependencies or build @@ -158,7 +154,7 @@ lock: ## theme.lock.json -A small file, committed next to the integration code and validated by +Committed next to the integration code and validated by `schemas/json/theme.lock.schema.json`. It is not a package manager: no graph, no install, no auto-update. To update the theme, change `ref`, `revision`, `version` and `exports`, rerun the consumer's own checks, and write the From 492b6c58629d8e748977ee0de5d0aafa1397116d Mon Sep 17 00:00:00 2001 From: j3w1 Date: Wed, 14 Oct 2026 15:37:36 -0500 Subject: [PATCH 05/65] refactor: centralize Node helpers and fix generated consumption guidance Keep color precision and keyboard wrapping semantics while sharing their implementations, clean scratch fixtures, and reserve one primary form action. Co-Authored-By: Claude Opus 5.5 --- apps/demo/vite.config.js | 3 +- docs/ui-consumption.md | 14 +- packages/ui/src/behaviors/advanced.js | 4 +- packages/ui/src/behaviors/navigation.js | 6 +- packages/ui/src/behaviors/tables.js | 4 +- packages/ui/src/catalogue.mjs | 473 +++++++++++++++++++++-- packages/ui/src/examples.mjs | 67 +++- packages/ui/src/examples/form-markup.mjs | 8 +- packages/ui/src/internal/dom.js | 7 + scripts/ci/dependabot-refresh.mjs | 3 +- scripts/ci/select.mjs | 7 +- scripts/consumption-judge.mjs | 12 +- scripts/lib/color.mjs | 28 ++ scripts/lib/contrast.mjs | 10 +- scripts/lib/exports.mjs | 8 +- scripts/lib/generators.mjs | 22 +- scripts/lib/hex-literals.mjs | 3 +- scripts/lib/host-install/generators.mjs | 3 +- scripts/lib/host-install/specimen.mjs | 21 +- scripts/lib/markup.mjs | 3 + scripts/lib/port-artifacts.mjs | 13 +- scripts/lib/port-presentation.mjs | 4 +- scripts/lib/release-comparison.mjs | 40 +- scripts/lib/source-locations.mjs | 5 +- scripts/lib/spec.mjs | 8 +- scripts/lib/task-kit.mjs | 22 +- scripts/lib/telegram-port.mjs | 11 +- scripts/lib/tokens.mjs | 8 +- scripts/lib/ui-consumer-examples.mjs | 61 ++- scripts/lib/verification-report.mjs | 15 +- scripts/lib/visual-review.mjs | 10 +- scripts/lib/windows-folder-icon.mjs | 3 +- scripts/lib/windows-markdown.mjs | 3 +- scripts/lib/windows-port.mjs | 25 +- scripts/phase6-visual-review.mjs | 5 +- scripts/tooling/git.mjs | 4 +- site/integrations/rehype-spec.mjs | 3 +- site/src/lib/base.ts | 2 - site/src/lib/theme.ts | 11 +- tests/chatgpt-port.test.js | 49 +-- tests/dependabot-refresh.test.js | 3 +- tests/helpers/json.mjs | 3 + tests/helpers/powershell.mjs | 14 + tests/helpers/scratch.mjs | 15 +- tests/helpers/tokens.mjs | 7 + tests/node-helpers.test.js | 47 +++ tests/node-regressions.test.js | 53 +++ tests/obsidian-android-install.test.js | 16 +- tests/obsidian-cascade.test.js | 3 +- tests/port-artifacts.test.js | 4 +- tests/port-preservation.test.js | 4 +- tests/readable-heritage.test.js | 17 +- tests/task-consumption.test.js | 4 +- tests/telegram-port.test.js | 3 +- tests/telegram-publish.test.js | 5 +- tests/windows-atomic.test.js | 6 +- tests/windows-font.test.js | 9 +- tests/windows-install.test.js | 17 +- tests/windows-markdown.test.js | 7 +- tests/windows-menu.test.js | 3 +- tests/windows-native.test.js | 29 +- tests/windows-port.test.js | 30 +- tests/windows-settings-startup.test.js | 9 +- tests/windows-setup.test.js | 13 +- tests/windows-text-popup.test.js | 5 +- 65 files changed, 1030 insertions(+), 304 deletions(-) create mode 100644 scripts/lib/color.mjs create mode 100644 tests/helpers/json.mjs create mode 100644 tests/helpers/powershell.mjs create mode 100644 tests/helpers/tokens.mjs create mode 100644 tests/node-helpers.test.js create mode 100644 tests/node-regressions.test.js diff --git a/apps/demo/vite.config.js b/apps/demo/vite.config.js index 1aa76b7c6..fcfd0505c 100644 --- a/apps/demo/vite.config.js +++ b/apps/demo/vite.config.js @@ -1,3 +1,4 @@ import { defineConfig } from "vite"; import vue from "@vitejs/plugin-vue"; -export default defineConfig({ base: "/theme/demo/", plugins: [vue({ template: { compilerOptions: { isCustomElement: tag => tag.startsWith("j3w1-") } } })], build: { target: "es2022", sourcemap: false } }); +import manifest from "../../theme.json" with { type: "json" }; +export default defineConfig({ base: `${manifest.site.base.replace(/\/$/, "")}/demo/`, plugins: [vue({ template: { compilerOptions: { isCustomElement: tag => tag.startsWith("j3w1-") } } })], build: { target: "es2022", sourcemap: false } }); diff --git a/docs/ui-consumption.md b/docs/ui-consumption.md index fb7d37943..22370406e 100644 --- a/docs/ui-consumption.md +++ b/docs/ui-consumption.md @@ -23,9 +23,11 @@ complete maintained markup on the component's page. Keep the exact package version and your package-manager lockfile in source control. + ```sh -npm install --save-exact @j3w1/ui@3.1.0 +npm install --save-exact @j3w1/ui@4.0.0 ``` + That command needs npm publication, which is an owner release action. Before publication: @@ -34,9 +36,11 @@ publication: 2. Check it against its published digest. 3. Install the local file: + ```sh -npm install --save-exact ./j3w1-ui-3.1.0.tgz +npm install --save-exact ./j3w1-ui-4.0.0.tgz ``` + The repository builds this same artifact with `npm run ui:build` and `npm run ui:pack`. Never use a branch URL in place of a release pin. Do not @@ -250,10 +254,12 @@ Styling: ## Copy a complete bundle + ```sh -npx --package=@j3w1/ui@3.1.0 j3w1-ui copy dialog --out ./vendor/j3w1/dialog -npx --package=@j3w1/ui@3.1.0 j3w1-ui kit --components text-field,button,dialog --out ./vendor/j3w1/task +npx --package=@j3w1/ui@4.0.0 j3w1-ui copy dialog --out ./vendor/j3w1/dialog +npx --package=@j3w1/ui@4.0.0 j3w1-ui kit --components text-field,button,dialog --out ./vendor/j3w1/task ``` + - Installed from a tarball: run the installed `j3w1-ui` binary instead of npx. - The CLI checks all source bytes before it writes. It rejects unknown components diff --git a/packages/ui/src/behaviors/advanced.js b/packages/ui/src/behaviors/advanced.js index 792e35cfa..b06b9dd67 100644 --- a/packages/ui/src/behaviors/advanced.js +++ b/packages/ui/src/behaviors/advanced.js @@ -1,4 +1,4 @@ -import { all, enabled, visible, rove, identify, nativeInput, make } from "../internal/dom.js"; +import { keyIndex, all, enabled, visible, rove, identify, nativeInput, make } from "../internal/dom.js"; import { IDREFS } from "../../../../scripts/lib/markup.mjs"; export function tree(root, { on }) { @@ -35,7 +35,7 @@ export function tree(root, { on }) { 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 = event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : Math.max(0, Math.min(options.length - 1, index + (event.key === "ArrowDown" ? 1 : -1))); rove(options, next); } + 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); } diff --git a/packages/ui/src/behaviors/navigation.js b/packages/ui/src/behaviors/navigation.js index fecb87f45..2d90bd28d 100644 --- a/packages/ui/src/behaviors/navigation.js +++ b/packages/ui/src/behaviors/navigation.js @@ -1,4 +1,4 @@ -import { all, enabled, visible, rove, identify, nativeInput, announce, place } from "../internal/dom.js"; +import { keyIndex, all, enabled, visible, rove, identify, nativeInput, announce, place } from "../internal/dom.js"; export function tabs(root, { on }, listOverride) { const list = listOverride ?? root.querySelector('[role="tablist"]'); @@ -46,7 +46,7 @@ export function toolbar(root, { on }) { 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, event.key === next ? index + 1 : event.key === prev ? index - 1 : event.key === "Home" ? 0 : items.length - 1); + 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]"); @@ -142,7 +142,7 @@ export function menu(root, { on }) { 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, event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : index + (event.key === "ArrowDown" ? 1 : -1)); } + 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(); diff --git a/packages/ui/src/behaviors/tables.js b/packages/ui/src/behaviors/tables.js index fd914df3d..ada3f2df2 100644 --- a/packages/ui/src/behaviors/tables.js +++ b/packages/ui/src/behaviors/tables.js @@ -1,4 +1,4 @@ -import { all, enabled, rove, identify } from "../internal/dom.js"; +import { keyIndex, all, enabled, rove, identify } from "../internal/dom.js"; export function table(root, { on }) { const element = root.querySelector("table"), body = element?.tBodies[0]; @@ -48,7 +48,7 @@ export function table(root, { on }) { 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 = event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : Math.max(0, Math.min(options.length - 1, index + (event.key === "ArrowDown" ? 1 : -1))); + 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; } diff --git a/packages/ui/src/catalogue.mjs b/packages/ui/src/catalogue.mjs index 37b0126b6..6d74515a9 100644 --- a/packages/ui/src/catalogue.mjs +++ b/packages/ui/src/catalogue.mjs @@ -4,58 +4,455 @@ const property = (name, type, description, controller = false, readonly = false) const method = (name, signature, description) => ({ name, signature, description }); const event = (name, detail, description) => ({ name: `j3w1-${name}`, detail, description }); const common = { - attributes: [{ name: "disabled", description: "Disable the native controls owned by this instance." }, { name: "loading", description: "Mark the primary control busy and prevent duplicate activation." }], - properties: [property("disabled", "boolean", "Delegates disabled state to native children."), property("name", "string", "Native control name; application form keys remain explicit.")], - methods: [method("refresh", "(): void", "Reconnect behavior after replacing native child structure."), method("focus", "(options?: FocusOptions): void", "Focus the first usable native control.")], - events: [], + attributes: [ + { name: "disabled", description: "Disable the native controls owned by this instance." }, + { name: "loading", description: "Mark the primary control busy and prevent duplicate activation." } + ], + properties: [ + property("disabled", "boolean", "Delegates disabled state to native children."), + property("name", "string", "Native control name; application form keys remain explicit.") + ], + methods: [ + method("refresh", "(): void", "Reconnect behavior after replacing native child structure."), + method("focus", "(options?: FocusOptions): void", "Focus the first usable native control.") + ], + events: [] }; const define = (ids, module, behavior, extra = {}) => { for (const id of ids.split(" ")) { const api = extra.api ?? {}; - definitions[id] = { module, behavior, domReason: "Light DOM retains static content, native semantics, label relationships and host composition without duplicating controls.", ...extra, api: { attributes: [...common.attributes, ...(api.attributes ?? [])], properties: [...common.properties.filter(p => !(api.properties ?? []).some(own => own.name === p.name)), ...(api.properties ?? [])], methods: [...common.methods.filter(m => !(api.methods ?? []).some(own => own.name === m.name)), ...(api.methods ?? [])], events: api.events ?? [] } }; + definitions[id] = { + module, + behavior, + domReason: "Light DOM retains static content, native semantics, label relationships and host composition without duplicating controls.", + ...extra, + api: { + attributes: [...common.attributes, ...(api.attributes ?? [])], + properties: [ + ...common.properties.filter(p => !(api.properties ?? []).some(own => own.name === p.name)), + ...(api.properties ?? []) + ], + methods: [...common.methods.filter(m => !(api.methods ?? []).some(own => own.name === m.name)), ...(api.methods ?? [])], + events: api.events ?? [] + } + }; } }; -define("button icon-button button-group", "native", "actions", { display: "inline-block", api: { attributes: [{ name: "tone", description: "Button tone: primary, secondary, tertiary or destructive." }], events: [event("action", "{ action: string; pressed: boolean }", "A native button activated. Prevent default on this event to cancel the associated native default action.")] } }); +define( + "button icon-button button-group", + "native", + "actions", + { + display: "inline-block", + api: { + attributes: [{ name: "tone", description: "Button tone: primary, secondary, tertiary or destructive." }], + events: [ + event("action", "{ action: string; pressed: boolean }", "A native button activated. Prevent default on this event to cancel the associated native default action.") + ] + } + } +); define("link field fieldset radio-group segmented-control breadcrumbs skip-link card list description-list badge kbd timeline skeleton loading-indicator progress", "native", "content"); -define("text-field textarea select checkbox range number-field search-field date-picker time-picker", "native", "fields", { domReason: "Visible native controls retain FormData, labels, constraints, disabled fieldsets and reset. No duplicate form-value mechanism is installed.", api: { - attributes: ["value", "required", "readonly", "checked"].map(name => ({ name, description: `Forwards ${name} to the primary native control.` })), - properties: [property("value", "string", "Primary native value; assignment does not fabricate user events."), property("checked", "boolean", "Native checkbox state."), property("required", "boolean", "Native required constraint."), property("readOnly", "boolean", "Native readonly property."), property("form", "HTMLFormElement | null", "Owning native form.", false, true)], - methods: [method("checkValidity", "(): boolean", "Check owned native constraints."), method("reportValidity", "(): boolean", "Report the first invalid owned control."), method("clear", "(): void", "Clear an editable primary input and emit native input/change.")], - events: [event("change", "{ value: string; checked?: boolean; name: string }", "Native change from an owned control, alongside the original native event.")], -} }); +define( + "text-field textarea select checkbox range number-field search-field date-picker time-picker", + "native", + "fields", + { + domReason: "Visible native controls retain FormData, labels, constraints, disabled fieldsets and reset. No duplicate form-value mechanism is installed.", + api: { + attributes: ["value", "required", "readonly", "checked"].map(name => ({ name, description: `Forwards ${name} to the primary native control.` })), + properties: [ + property("value", "string", "Primary native value; assignment does not fabricate user events."), + property("checked", "boolean", "Native checkbox state."), + property("required", "boolean", "Native required constraint."), + property("readOnly", "boolean", "Native readonly property."), + property("form", "HTMLFormElement | null", "Owning native form.", false, true) + ], + methods: [ + method("checkValidity", "(): boolean", "Check owned native constraints."), + method("reportValidity", "(): boolean", "Report the first invalid owned control."), + method("clear", "(): void", "Clear an editable primary input and emit native input/change.") + ], + events: [ + event("change", "{ value: string; checked?: boolean; name: string }", "Native change from an owned control, alongside the original native event.") + ] + } + } +); definitions.checkbox.api.properties.push(property("indeterminate", "boolean", "Native mixed state; Space changes a mixed checkbox to checked.", true)); definitions.checkbox.api.properties.push(property("values", "string[]", "Values of checked native options in this instance.", true)); definitions.select.api.properties.push(property("values", "string[]", "Selected values of a multiple native select.", true)); definitions.select.domReason = "Theme-owned combobox/listbox presentation backed by the original native select for FormData, constraints, defaults and reset. The native control is visible only before enhancement or without JavaScript."; for (const id of ['date-picker','time-picker']) definitions[id].domReason = "Theme-owned date/time editor and controls backed by the original native input for form values and constraints. Native input is the no-JavaScript fallback."; for (const id of ["number-field", "text-field"]) definitions[id].api.methods.push(method("stepBy", "(amount: number): void", "Step a number input by the supplied number of native steps.")); -define("switch", "native", "switchControl", { display: "inline-block", api: { attributes: ["checked", "value"].map(name => ({ name, description: `Default switch ${name}.` })), properties: [property("checked", "boolean", "Immediate switch state; a named switch exposes a matching native hidden form value.", true)], events: [event("change", "{ checked: boolean; value: string; name: string }", "The user toggled the switch.")] } }); -define("file-input", "native", "fileInput", { api: { properties: [property("files", "File[]", "Current native files; files are never uploaded by the component.", true, true)], methods: [method("clear", "(): void", "Clear the current native file selection.")], events: [event("change", "{ value: string; name: string }", "Native file selection changed; read files from the component.")] } }); -define("tabs", "navigation", "tabs", { api: { attributes: [{ name: "activation", description: "automatic (default) or manual activation when arrowing among tabs." }], properties: [property("selectedId", "string", "ID of the selected enabled tab.", true)], methods: [method("select", "(id: string, focus?: boolean): HTMLElement", "Select an enabled tab by its exact ID.")], events: [event("select", "{ id: string; panelId: string }", "The user selected a tab.")] } }); +define( + "switch", + "native", + "switchControl", + { + display: "inline-block", + api: { + attributes: ["checked", "value"].map(name => ({ name, description: `Default switch ${name}.` })), + properties: [ + property("checked", "boolean", "Immediate switch state; a named switch exposes a matching native hidden form value.", true) + ], + events: [event("change", "{ checked: boolean; value: string; name: string }", "The user toggled the switch.")] + } + } +); +define( + "file-input", + "native", + "fileInput", + { + api: { + properties: [property("files", "File[]", "Current native files; files are never uploaded by the component.", true, true)], + methods: [method("clear", "(): void", "Clear the current native file selection.")], + events: [ + event("change", "{ value: string; name: string }", "Native file selection changed; read files from the component.") + ] + } + } +); +define( + "tabs", + "navigation", + "tabs", + { + api: { + attributes: [{ name: "activation", description: "automatic (default) or manual activation when arrowing among tabs." }], + properties: [property("selectedId", "string", "ID of the selected enabled tab.", true)], + methods: [method("select", "(id: string, focus?: boolean): HTMLElement", "Select an enabled tab by its exact ID.")], + events: [event("select", "{ id: string; panelId: string }", "The user selected a tab.")] + } + } +); define("toolbar", "navigation", "toolbar", { api: { events: [event("action", "{ action: string; pressed: boolean }", "A toggle action changed.")] } }); -define("sidebar-nav disclosure", "navigation", "disclosure", { api: { properties: [property("open", "boolean", "Native details expansion when this component contains details.", true)], events: [event("toggle", "{ id: string; expanded: boolean }", "A native disclosure or navigation group changed.")] } }); -define("combobox", "navigation", "combobox", { api: { properties: [property("value", "string", "Typed or accepted input value.", true), property("open", "boolean", "List visibility.", true)], methods: [method("show", "(allOptions?: boolean): void", "Open the list, optionally showing every option."), method("hide", "(): void", "Close without discarding typed text.")], events: [event("change", "{ value: string; name: string }", "An option was accepted or the value cleared.")] } }); -define("menu", "navigation", "menu", { api: { properties: [property("open", "boolean", "Menu visibility.", true)], methods: [method("show", "(): void", "Open and focus the first menu item."), method("hide", "(focus?: boolean): void", "Close all menus, optionally restoring the trigger.")], events: [event("action", "{ action: string; checked: boolean }", "An enabled action or check item was invoked.")] } }); -define("dialog drawer", "overlays", "modal", { api: { properties: [property("open", "boolean", "Native modal state.", true), property("returnValue", "string", "Native dialog result.", true, true)], methods: [method("show", "(): void", "Open using native showModal and remember the opener."), method("close", "(value?: string): void", "Close with a result value.")], events: [event("open", "Record", "The modal opened."), event("close", "{ returnValue: string }", "The modal closed and restored available opener focus."), event("cancel", "Record", "Native cancel request; prevent default to keep the modal open."), event("action", "{ action: string }", "An explicit dialog action; prevent default to keep it open.")] } }); -define("tooltip", "overlays", "tooltip", { display: "inline-block", api: { properties: [property("open", "boolean", "Current tooltip visibility.", true, true)], methods: [method("show", "(): void", "Show the description unless dismissed in this hover/focus session."), method("hide", "(): void", "Hide and cancel pending timers.")] } }); -define("popover", "overlays", "popover", { api: { properties: [property("open", "boolean", "Non-modal panel visibility.", true)], methods: [method("show", "(): void", "Show next to the trigger."), method("hide", "(focus?: boolean): void", "Hide, optionally restoring trigger focus.")], events: [event("toggle", "{ expanded: boolean }", "The panel changed visibility.")] } }); -define("alert toast empty-state error-state chip", "overlays", "feedback", { api: { methods: [method("dismiss", "(id?: string): void", "Dismiss a message; focused actions move to the next available control.")], events: [event("dismiss", "{ id: string }", "Cancelable message dismissal."), event("retry", "Record", "Request recovery; the host owns the result."), event("action", "{ action: string }", "An explicit message action.")] } }); -define("tree", "advanced", "tree", { api: { properties: [property("selectedId", "string", "Selected treeitem ID.", true)], methods: [method("expand", "(id: string, expanded?: boolean): void", "Expand or collapse a parent by ID.")], events: [event("select", "{ id: string }", "The user selected a visible enabled item."), event("toggle", "{ id: string; expanded: boolean }", "A parent expanded or collapsed.")] } }); -define("multiselect", "advanced", "multiselect", { api: { properties: [property("values", "string[]", "Selected native checkbox values, including hidden matches.", true)], methods: [method("clear", "(): void", "Clear every selected value and report the explicit change.")], events: [event("selection", "{ values: string[] }", "The selected values changed through interaction.")] } }); -define("repeater", "advanced", "repeater", { api: { attributes: [{ name: "max", description: "Maximum rows, default 10; positive integer up to 100." }], properties: [property("rowIds", "string[]", "Stable IDs in current source order.", true, true)], methods: [method("add", "(): string | null", "Append a row when below the configured limit."), method("remove", "(id: string): void", "Remove a known row and recover focus."), method("move", "(id: string, direction: number): void", "Move a row one position up or down.")], events: [event("rows", "{ ids: string[] }", "Row order or membership changed.")] } }); -define("command-palette", "advanced", "commandPalette", { api: { attributes: [{ name: "shortcut", description: "Opt in to Ctrl+K / Cmd+K; absence leaves global shortcuts to the host." }], properties: [property("open", "boolean", "Native modal state.", true)], methods: [method("show", "(): void", "Open and focus the command prompt."), method("close", "(): void", "Close and restore the opener.")], events: [event("command", "{ action: string; href: string | null }", "Invoke the chosen command; prevent default to handle a result link yourself.")] } }); -define("avatar", "display", "avatar", { display: "inline-block", api: { attributes: [{ name: "src", description: "Optional caller-owned image URL." }], properties: [property("src", "string", "Image URL; empty restores initials.", true)] } }); -define("chart", "display", "chart", { api: { properties: [property("data", "Array<{ label: string; value: number }>", "Finite non-negative one-series data; at most 200 rows.", true)] } }); -define("editor-search", "display", "editorSearch", { api: { properties: [property("source", "string", "Read-only literal source text.", true), property("query", "string", "Literal case-insensitive query.", true), property("matchCount", "number", "Current number of matches.", true, true)], methods: [method("next", "(direction?: number): void", "Move among existing matches without moving input focus.")] } }); -define("code-editor terminal diff-view diagnostics", "display", "developerView", { api: { methods: [method("setText", "(text: string): void", "Replace the bounded read-only text view; no code or shell execution occurs.")], events: [event("action", "{ action: string }", "Request a developer-view action; editing and execution belong to the host.")] } }); -define("table data-table filterable-table", "tables", "table", { api: { methods: [method("sort", "(column: number, direction?: 'ascending' | 'descending'): void", "Sort existing native rows by a column."), method("filter", "(query: string): void", "Filter existing rows by literal text.")], events: [event("sort", "{ column: number; direction: string }", "The user requested sorting."), event("selection", "{ ids: string[] }", "Selected row identities changed.")] } }); -define("pagination", "tables", "pagination", { api: { properties: [property("page", "number", "Current page when using local button-mode pagination.", true)], events: [event("page", "{ page: number }", "Local page choice changed; native href links continue to navigate.")] } }); -define("wizard", "forms", "wizard", { api: { properties: [property("step", "number", "Current zero-based step.", true)], methods: [method("next", "(): boolean", "Validate current native controls before advancing."), method("back", "(): void", "Return without validation.")], events: [event("step", "{ step: number }", "The active step changed."), event("complete", "Record", "Final local validation succeeded; the host owns persistence.")] } }); -define("form-builder", "form-builder", "formBuilder", { styles: ["button", "text-field", "textarea", "select", "checkbox", "radio-group", "alert", "table"], api: { methods: [method("exportDefinition", "(): string", "Export the canonical bounded definition without entered preview values."), method("importDefinition", "(json: string): boolean", "Validate and import a complete definition without partial mutation.")] } }); -define("settings-panel admin-form", "forms", "formComposition", { styles: ["button", "field", "text-field", "checkbox", "radio-group", "select", "switch"], api: { events: [event("submit", "{ values: Array<[string, FormDataEntryValue]> }", "Validated local native form values; the host owns saving.")] } }); -define("file-browser", "compositions", "fileBrowser", { dependencies: ["tree"], styles: ["table"], api: { events: [event("open-file", "{ id: string }", "Request opening an existing file identity.")] } }); -define("compact-dashboard", "compositions", "dashboard", { dependencies: ["chart"], styles: ["table"], api: { events: [event("open-record", "{ id: string }", "Request an existing record.")] } }); -define("i3-window-frame", "compositions", "windowFrame", { api: { events: [event("window-action", "{ action: string }", "Request a host window action; the browser component does not control OS windows.")] } }); +define( + "sidebar-nav disclosure", + "navigation", + "disclosure", + { + api: { + properties: [property("open", "boolean", "Native details expansion when this component contains details.", true)], + events: [event("toggle", "{ id: string; expanded: boolean }", "A native disclosure or navigation group changed.")] + } + } +); +define( + "combobox", + "navigation", + "combobox", + { + api: { + properties: [ + property("value", "string", "Typed or accepted input value.", true), + property("open", "boolean", "List visibility.", true) + ], + methods: [ + method("show", "(allOptions?: boolean): void", "Open the list, optionally showing every option."), + method("hide", "(): void", "Close without discarding typed text.") + ], + events: [event("change", "{ value: string; name: string }", "An option was accepted or the value cleared.")] + } + } +); +define( + "menu", + "navigation", + "menu", + { + api: { + properties: [property("open", "boolean", "Menu visibility.", true)], + methods: [ + method("show", "(): void", "Open and focus the first menu item."), + method("hide", "(focus?: boolean): void", "Close all menus, optionally restoring the trigger.") + ], + events: [event("action", "{ action: string; checked: boolean }", "An enabled action or check item was invoked.")] + } + } +); +define( + "dialog drawer", + "overlays", + "modal", + { + api: { + properties: [ + property("open", "boolean", "Native modal state.", true), + property("returnValue", "string", "Native dialog result.", true, true) + ], + methods: [ + method("show", "(): void", "Open using native showModal and remember the opener."), + method("close", "(value?: string): void", "Close with a result value.") + ], + events: [ + event("open", "Record", "The modal opened."), + event("close", "{ returnValue: string }", "The modal closed and restored available opener focus."), + event("cancel", "Record", "Native cancel request; prevent default to keep the modal open."), + event("action", "{ action: string }", "An explicit dialog action; prevent default to keep it open.") + ] + } + } +); +define( + "tooltip", + "overlays", + "tooltip", + { + display: "inline-block", + api: { + properties: [property("open", "boolean", "Current tooltip visibility.", true, true)], + methods: [ + method("show", "(): void", "Show the description unless dismissed in this hover/focus session."), + method("hide", "(): void", "Hide and cancel pending timers.") + ] + } + } +); +define( + "popover", + "overlays", + "popover", + { + api: { + properties: [property("open", "boolean", "Non-modal panel visibility.", true)], + methods: [ + method("show", "(): void", "Show next to the trigger."), + method("hide", "(focus?: boolean): void", "Hide, optionally restoring trigger focus.") + ], + events: [event("toggle", "{ expanded: boolean }", "The panel changed visibility.")] + } + } +); +define( + "alert toast empty-state error-state chip", + "overlays", + "feedback", + { + api: { + methods: [ + method("dismiss", "(id?: string): void", "Dismiss a message; focused actions move to the next available control.") + ], + events: [ + event("dismiss", "{ id: string }", "Cancelable message dismissal."), + event("retry", "Record", "Request recovery; the host owns the result."), + event("action", "{ action: string }", "An explicit message action.") + ] + } + } +); +define( + "tree", + "advanced", + "tree", + { + api: { + properties: [property("selectedId", "string", "Selected treeitem ID.", true)], + methods: [method("expand", "(id: string, expanded?: boolean): void", "Expand or collapse a parent by ID.")], + events: [ + event("select", "{ id: string }", "The user selected a visible enabled item."), + event("toggle", "{ id: string; expanded: boolean }", "A parent expanded or collapsed.") + ] + } + } +); +define( + "multiselect", + "advanced", + "multiselect", + { + api: { + properties: [property("values", "string[]", "Selected native checkbox values, including hidden matches.", true)], + methods: [method("clear", "(): void", "Clear every selected value and report the explicit change.")], + events: [event("selection", "{ values: string[] }", "The selected values changed through interaction.")] + } + } +); +define( + "repeater", + "advanced", + "repeater", + { + api: { + attributes: [{ name: "max", description: "Maximum rows, default 10; positive integer up to 100." }], + properties: [property("rowIds", "string[]", "Stable IDs in current source order.", true, true)], + methods: [ + method("add", "(): string | null", "Append a row when below the configured limit."), + method("remove", "(id: string): void", "Remove a known row and recover focus."), + method("move", "(id: string, direction: number): void", "Move a row one position up or down.") + ], + events: [event("rows", "{ ids: string[] }", "Row order or membership changed.")] + } + } +); +define( + "command-palette", + "advanced", + "commandPalette", + { + api: { + attributes: [{ name: "shortcut", description: "Opt in to Ctrl+K / Cmd+K; absence leaves global shortcuts to the host." }], + properties: [property("open", "boolean", "Native modal state.", true)], + methods: [ + method("show", "(): void", "Open and focus the command prompt."), + method("close", "(): void", "Close and restore the opener.") + ], + events: [ + event("command", "{ action: string; href: string | null }", "Invoke the chosen command; prevent default to handle a result link yourself.") + ] + } + } +); +define( + "avatar", + "display", + "avatar", + { + display: "inline-block", + api: { + attributes: [{ name: "src", description: "Optional caller-owned image URL." }], + properties: [property("src", "string", "Image URL; empty restores initials.", true)] + } + } +); +define("chart", "display", "chart", { + api: { + properties: [ + property("data", "Array<{ label: string; value: number }>", "Finite non-negative one-series data; at most 200 rows.", true) + ] + } +}); +define( + "editor-search", + "display", + "editorSearch", + { + api: { + properties: [ + property("source", "string", "Read-only literal source text.", true), + property("query", "string", "Literal case-insensitive query.", true), + property("matchCount", "number", "Current number of matches.", true, true) + ], + methods: [method("next", "(direction?: number): void", "Move among existing matches without moving input focus.")] + } + } +); +define( + "code-editor terminal diff-view diagnostics", + "display", + "developerView", + { + api: { + methods: [ + method("setText", "(text: string): void", "Replace the bounded read-only text view; no code or shell execution occurs.") + ], + events: [ + event("action", "{ action: string }", "Request a developer-view action; editing and execution belong to the host.") + ] + } + } +); +define( + "table data-table filterable-table", + "tables", + "table", + { + api: { + methods: [ + method("sort", "(column: number, direction?: 'ascending' | 'descending'): void", "Sort existing native rows by a column."), + method("filter", "(query: string): void", "Filter existing rows by literal text.") + ], + events: [ + event("sort", "{ column: number; direction: string }", "The user requested sorting."), + event("selection", "{ ids: string[] }", "Selected row identities changed.") + ] + } + } +); +define( + "pagination", + "tables", + "pagination", + { + api: { + properties: [property("page", "number", "Current page when using local button-mode pagination.", true)], + events: [event("page", "{ page: number }", "Local page choice changed; native href links continue to navigate.")] + } + } +); +define( + "wizard", + "forms", + "wizard", + { + api: { + properties: [property("step", "number", "Current zero-based step.", true)], + methods: [ + method("next", "(): boolean", "Validate current native controls before advancing."), + method("back", "(): void", "Return without validation.") + ], + events: [ + event("step", "{ step: number }", "The active step changed."), + event("complete", "Record", "Final local validation succeeded; the host owns persistence.") + ] + } + } +); +define( + "form-builder", + "form-builder", + "formBuilder", + { + styles: ["button", "text-field", "textarea", "select", "checkbox", "radio-group", "alert", "table"], + api: { + methods: [ + method("exportDefinition", "(): string", "Export the canonical bounded definition without entered preview values."), + method("importDefinition", "(json: string): boolean", "Validate and import a complete definition without partial mutation.") + ] + } + } +); +define( + "settings-panel admin-form", + "forms", + "formComposition", + { + styles: ["button", "field", "text-field", "checkbox", "radio-group", "select", "switch"], + api: { + events: [ + event("submit", "{ values: Array<[string, FormDataEntryValue]> }", "Validated local native form values; the host owns saving.") + ] + } + } +); +define( + "file-browser", + "compositions", + "fileBrowser", + { + dependencies: ["tree"], + styles: ["table"], + api: { events: [event("open-file", "{ id: string }", "Request opening an existing file identity.")] } + } +); +define("compact-dashboard", "compositions", "dashboard", { + dependencies: ["chart"], + styles: ["table"], + api: { events: [event("open-record", "{ id: string }", "Request an existing record.")] } +}); +define( + "i3-window-frame", + "compositions", + "windowFrame", + { + api: { + events: [ + event("window-action", "{ action: string }", "Request a host window action; the browser component does not control OS windows.") + ] + } + } +); // Composition dependencies are registered and copied with their parent. definitions.breadcrumbs.module = "navigation"; definitions.breadcrumbs.behavior = "disclosure"; diff --git a/packages/ui/src/examples.mjs b/packages/ui/src/examples.mjs index 700557b12..0761b1bf4 100644 --- a/packages/ui/src/examples.mjs +++ b/packages/ui/src/examples.mjs @@ -12,7 +12,10 @@ const wrap = (node, tag) => { const parent = node.parentNode, index = parent.chi function wizardMarkup(variant) { const labels = variant === "icons" ? ["Source", "Workspaces", "Bindings", "Review"] : ["Project", "Preferences", "Review"]; - return `
    ${labels.map((label, i) => `
  1. `).join("")}
${labels.map((label, i) => `

Step ${i + 1} of ${labels.length}: ${label}

${i < labels.length - 1 ? `` : `

All previous values remain available. Complete requests host handling; it does not send a network request.

`}
`).join("")}
`; + return [ + `
    ${labels.map((label, i) => `
  1. `).join("")}
${labels.map((label, i) => `

Step ${i + 1} of ${labels.length}: ${label}

${i < labels.length - 1 ? `` : `

All previous values remain available. Complete requests host handling; it does not send a network request.

`}
`).join("")}
`, + `
` + ].join(""); } function widthMenu(index, label) { @@ -23,15 +26,63 @@ function tableMarkup(id, variant) { const data = id !== "table", cls = data ? "data-table" : "table", selectable = data && variant !== "default", resizable = variant === "resizable"; const columns = ["Project", "Owner", "Status", "Scope"]; const records = variant === "empty" ? [] : [["Atlas library", "Avery Kim", "Ready", "24"], ["Orion workspace", "Jordan Lee", "In progress", "12"], ["Field notes", "Morgan Noor", "Ready", "38"], ["Signal monitor", "Riley Stone", "Review", "6"]]; - return `
${selectable ? '' : ""}${columns.map((label, i) => ``).join("")}${records.map((record, index) => `${selectable ? `` : ""}${record.map((value, i) => ``).join("")}`).join("")}
Project records · synthetic fixture
${resizable ? `${widthMenu(i + Number(selectable), label)}` : ""}
${value}
No rows match.
⋯ Loading rows
`; + const selectionHeader = selectable + ? '' + : ""; + const headers = columns.map((label, i) => [ + ``, + resizable ? `${widthMenu(i + Number(selectable), label)}` : "", + ``, + ].join("")).join(""); + const rows = records.map((record, index) => { + const selectionCell = selectable + ? `` + : ""; + const cells = record.map((value, i) => + `${value}` + ).join(""); + return [ + ``, + selectionCell, cells, ``, + ].join(""); + }).join(""); + return [ + `
`, + ``, + selectionHeader, headers, ``, rows, + ``, + `
Project records · synthetic fixture
No rows match.
⋯ Loading rows
`, + ].join(""); } function filterableMarkup(variant) { - return `
${tableMarkup("data-table", variant === "default" ? "selectable" : variant)}

`; + return [ + `
`, + `
`, + ``, + `
${tableMarkup("data-table", variant === "default" ? "selectable" : variant)}

` + ].join(""); } function adminMarkup(variant) { - return `

Project details

Review the local values before passing them to your app.

Project information

`; + return [ + `

Project details

Review the local values before passing them to your app.

`, + `
Project information
`, + `
`, + `
`, + ``, + `
`, + `
`, + ``, + `

` + ].join(""); } export function renderUsage(component, variant, prefix) { @@ -69,7 +120,13 @@ export function renderUsage(component, variant, prefix) { } if (component.id === "toolbar" && variant === "overflow") { const more = nodes(tree).find(node => hasClass(node, "toolbar-more")); - if (more) replace(more, ``); + if (more) replace(more, [ + `` + ].join("")); } if (component.id === "i3-window-frame") { const list = nodes(tree).find(node => hasClass(node, "i3-window-frame-workspaces")); diff --git a/packages/ui/src/examples/form-markup.mjs b/packages/ui/src/examples/form-markup.mjs index b60d5a74d..22b2fc16d 100644 --- a/packages/ui/src/examples/form-markup.mjs +++ b/packages/ui/src/examples/form-markup.mjs @@ -2,15 +2,15 @@ import { anchorFor } from "../../../../scripts/lib/anchors.mjs"; import { escapeHtml as esc } from "../../../../scripts/lib/hex-literals.mjs"; export function workflowMarkup(prefix) { - return ``; + return ``; } export function builderMarkup(prefix) { const id = name => anchorFor.uiExample(prefix, name); return `

The bounded form editor requires JavaScript. Its definition is plain JSON with stable field IDs, labels, help, required flags and explicit option IDs.

`; +

Transfer definition

Schema version 1 accepts at most 64 KiB and 20 fields. Invalid imports leave the current definition unchanged. Export excludes entered preview values.

The bounded form editor requires JavaScript. Its definition is plain JSON with stable field IDs, labels, help, required flags and explicit option IDs.

`; } diff --git a/packages/ui/src/internal/dom.js b/packages/ui/src/internal/dom.js index fc4b10fab..bbf3d03b3 100644 --- a/packages/ui/src/internal/dom.js +++ b/packages/ui/src/internal/dom.js @@ -19,6 +19,13 @@ export function announce(root, message) { } export function identify(root, node, suffix) { if (node && !node.id) node.id = `${root.id}-${suffix}`; return node?.id; } export function nativeInput(input, type = "input") { input.dispatchEvent(new Event(type, { bubbles: true })); } +export 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)); +} + export function rove(items, index, focus = true) { if (!items.length) return null; const next = items[(index + items.length) % items.length]; diff --git a/scripts/ci/dependabot-refresh.mjs b/scripts/ci/dependabot-refresh.mjs index fb7883b43..ebabfabdd 100644 --- a/scripts/ci/dependabot-refresh.mjs +++ b/scripts/ci/dependabot-refresh.mjs @@ -2,6 +2,7 @@ // Proposes generated changes for an npm Dependabot PR. Never stages in the // checkout's index or changes the PR; the patch is not a compatibility check. +import { gitBytes } from "../tooling/git.mjs"; import { execFileSync } from "node:child_process"; import { appendFileSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import path from "node:path"; @@ -24,7 +25,7 @@ export const isGenerated = (file) => generatedFiles.has(file) || export const isNpmBump = (paths, workspaces) => paths.some((file) => file === "package.json" || file === "package-lock.json" || workspaces.some((workspace) => file === `${workspace}/package.json`)); -const git = (dir, args, options = {}) => execFileSync("git", args, { cwd: dir, maxBuffer: 64 * 1024 * 1024, ...options }); +const git = (dir, args, options = {}) => gitBytes(args, { cwd: dir, maxBuffer: 64 * 1024 * 1024, ...options }); const lines = (bytes) => bytes.toString("utf8").split("\0").filter(Boolean); const sha = (dir, ref) => git(dir, ["rev-parse", "--verify", `${ref}^{commit}`]).toString("utf8").trim(); diff --git a/scripts/ci/select.mjs b/scripts/ci/select.mjs index 224adb867..71205fd77 100644 --- a/scripts/ci/select.mjs +++ b/scripts/ci/select.mjs @@ -10,7 +10,8 @@ // Writes the plan as JSON to stdout, and to $GITHUB_OUTPUT when set. import { execFileSync } from "node:child_process"; -import { createHash } from "node:crypto"; +import { sha256Hex } from "../lib/host-install/files.mjs"; +import { git as queryGit } from "../tooling/git.mjs"; import { existsSync, readFileSync, appendFileSync, readdirSync, statSync } from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; @@ -172,10 +173,10 @@ export function plan({ registry, event, paths, full = false, reason = null, spec paths: paths === null ? null : paths.length, reasons: [...new Set(reasons)].sort().slice(0, 40), }; - return { ...body, planHash: createHash("sha256").update(JSON.stringify(body)).digest("hex") }; + return { ...body, planHash: sha256Hex(JSON.stringify(body)) }; } -const git = (...args) => execFileSync("git", args, { cwd: root, encoding: "utf8" }).trim(); +const git = (...args) => queryGit(args, { cwd: root }); export function changedPaths(base, head) { if (!SHA.test(base ?? "") || !SHA.test(head ?? "")) return null; diff --git a/scripts/consumption-judge.mjs b/scripts/consumption-judge.mjs index e39a9cb0b..4821e98ee 100644 --- a/scripts/consumption-judge.mjs +++ b/scripts/consumption-judge.mjs @@ -9,6 +9,7 @@ with the component's stateRules. Exit code 1 on any failure; the judge is never loosened to make a run pass (tests/consumption/PROTOCOL.md). */ +import { rgbToHex, rgbCssToHex } from "./lib/color.mjs"; import { promises as fs } from "node:fs"; import path from "node:path"; import { readJson, repoRoot } from "./lib/fs.mjs"; @@ -56,7 +57,7 @@ const normalise = (value) => { const v = value.trim().toLowerCase(); const rgb = v.match(/^rgba?\(\s*(\d+)[\s,]+(\d+)[\s,]+(\d+)(?:[\s,/]+([\d.]+%?))?\s*\)$/); if (rgb) { - const hex = `#${[rgb[1], rgb[2], rgb[3]].map((n) => Number(n).toString(16).padStart(2, "0")).join("")}`; + const hex = rgbToHex(rgb.slice(1, 4)); if (rgb[4] === undefined) return hex; const alpha = rgb[4].endsWith("%") ? Number(rgb[4].slice(0, -1)) / 100 : Number(rgb[4]); return alpha >= 1 ? hex : `rgb(${rgb[1]} ${rgb[2]} ${rgb[3]} / ${Math.round(alpha * 100)}%)`; @@ -115,10 +116,6 @@ if (browser && findings.length === 0) { await page.goto(`file://${path.resolve(resultPath)}`); const rules = Object.fromEntries(component.stateRules.map((r) => [r.state, r.tokens])); computed = await page.evaluate((states) => { - const toHex = (rgb) => { - const m = rgb.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/); - return m ? `#${[m[1], m[2], m[3]].map((n) => Number(n).toString(16).padStart(2, "0")).join("")}` : rgb; - }; const out = {}; for (const state of states) { const wrapper = document.querySelector(`[data-state="${state.replace(/"/g, '\\"')}"]`); @@ -137,11 +134,14 @@ if (browser && findings.length === 0) { const outlineStyle = pick((s) => s.outlineStyle !== "none" && parseFloat(s.outlineWidth) > 0, cs); const bgStyle = pick((s) => s.backgroundColor !== "rgba(0, 0, 0, 0)", cs); const placeholder = state.includes("placeholder-shown") && "value" in control && control.value === "" ? getComputedStyle(control, "::placeholder").color : null; - out[state] = { color: toHex(placeholder ?? cs.color), background: toHex(bgStyle.backgroundColor), border: toHex(borderStyle.borderTopColor), outline: toHex(outlineStyle.outlineColor), outlineStyle: outlineStyle.outlineStyle, radius: borderStyle.borderRadius }; + out[state] = { color: placeholder ?? cs.color, background: bgStyle.backgroundColor, border: borderStyle.borderTopColor, outline: outlineStyle.outlineColor, outlineStyle: outlineStyle.outlineStyle, radius: borderStyle.borderRadius }; } return out; }, component.states); await b.close(); + for (const entry of Object.values(computed)) { + for (const key of ["color", "background", "border", "outline"]) entry[key] = rgbCssToHex(entry[key]); + } for (const [state, expected] of Object.entries(rules)) { const actual = computed[state]; if (!actual || !expected) continue; diff --git a/scripts/lib/color.mjs b/scripts/lib/color.mjs new file mode 100644 index 000000000..f32262759 --- /dev/null +++ b/scripts/lib/color.mjs @@ -0,0 +1,28 @@ +/* Colour representation helpers. Byte RGB and float sRGB conversions stay + explicit so analytical callers never inherit token-authoring rounding. */ +export const rgb = hex => [1, 3, 5].map(i => Number.parseInt(hex.slice(i, i + 2), 16)); + +export const rgbToHex = channels => `#${channels.map(n => Number(n).toString(16).padStart(2, "0")).join("")}`; + +export const colorValue = (hex, alpha = 1) => ({ + colorSpace: "srgb", + components: rgb(hex).map(c => c / 255), + alpha, + hex, +}); + +/* Authoring keeps the established four-decimal token precision. */ +export const hexToColor = (hex, alpha = 1) => { + const value = colorValue(hex.toLowerCase(), alpha); + return { ...value, components: value.components.map(c => Number(c.toFixed(4))) }; +}; + +/* Both source tokens and resolved exports have the same colour meaning. */ +export const hexOf = token => token?.type === "color" ? (token.resolved ?? token.value).hex : null; + +export const rgbCssToHex = css => { + const match = css.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/); + return match ? rgbToHex(match.slice(1, 4)) : css; +}; + +export const componentsToHex = components => rgbToHex(components.map(c => Math.round(c * 255))); diff --git a/scripts/lib/contrast.mjs b/scripts/lib/contrast.mjs index a43ca2a75..855302b00 100644 --- a/scripts/lib/contrast.mjs +++ b/scripts/lib/contrast.mjs @@ -6,10 +6,16 @@ displayed ratio is rounded to two decimals (so 4.4996 reads 4.50 and still fails). */ -const linear = (c) => (c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4); +import { colorValue, componentsToHex as toHex } from "./color.mjs"; + +export const linear = (c) => (c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4); export const luminance = ({ components: [r, g, b] }) => 0.2126 * linear(r) + 0.7152 * linear(g) + 0.0722 * linear(b); +export const luminanceRgb = channels => luminance({ components: channels.map(c => c / 255) }); +export const luminanceHex = hex => luminance(colorValue(hex)); +export const contrastHex = (a, b) => ratio(colorValue(a), colorValue(b)); + /* Composites `top` (with alpha) over `under` (assumed opaque). */ export const composite = (top, under) => { const a = top.alpha ?? 1; @@ -18,8 +24,6 @@ export const composite = (top, under) => { return { colorSpace: "srgb", components, alpha: 1, hex: toHex(components) }; }; -export const toHex = (components) => `#${components.map((c) => Math.round(c * 255).toString(16).padStart(2, "0")).join("")}`; - export const ratio = (fg, bg) => { const l1 = luminance(fg); const l2 = luminance(bg); diff --git a/scripts/lib/exports.mjs b/scripts/lib/exports.mjs index 4ba0cdb4e..120a7a268 100644 --- a/scripts/lib/exports.mjs +++ b/scripts/lib/exports.mjs @@ -11,10 +11,10 @@ import { portDownloadPath } from "./port-presentation.mjs"; const RAW = (manifest, rev) => manifest.sourceRevision.rawBase.replace("{rev}", rev); -export const tagFor = (manifest) => `v${manifest.version}`; +const tagFor = (manifest) => `v${manifest.version}`; /* The region between and , or the whole body. */ -export const compactRegion = (body) => { +const compactRegion = (body) => { const m = body.match(/([\s\S]*?)/); return (m ? m[1] : body).trim(); }; @@ -54,7 +54,7 @@ const foundationRows = (resolved, { filter = null } = {}) => { return rows; }; -export const shiftHeadings = (markdown, by = 1) => markdown.replace(/^(#{1,5}) /gm, (m, hashes) => `${"#".repeat(Math.min(6, hashes.length + by))} `); +const shiftHeadings = (markdown, by = 1) => markdown.replace(/^(#{1,5}) /gm, (m, hashes) => `${"#".repeat(Math.min(6, hashes.length + by))} `); const stateRulesOf = (component) => { const table = component.sections.get("States") ?? ""; @@ -315,7 +315,7 @@ export const downloadsTable = (manifest, ports) => ] : ["No application theme files are published yet."]; -export const catalogueTable = (catalogue) => [ +const catalogueTable = (catalogue) => [ "| Reference | Kind | Where | What it does not prove |", "| --- | --- | --- | --- |", ...catalogue.entries.map((e) => `| ${e.title} | ${e.kind} | ${e.source ? `\`${e.source.repository}\` \`${e.source.path}\`` : `\`${e.path}\``} | ${e.notes} |`), diff --git a/scripts/lib/generators.mjs b/scripts/lib/generators.mjs index 7e7d691f2..df35003cf 100644 --- a/scripts/lib/generators.mjs +++ b/scripts/lib/generators.mjs @@ -18,7 +18,7 @@ import { statusOf, toCss, toResolvedExport } from "./tokens.mjs"; import { buildCss, buildDensityCss } from "./css.mjs"; import { loadDeclaredPairs, validateDocs, validatePorts, validateReferences } from "./validators.mjs"; import { buildBrief, buildCompact, buildComponentJson, buildFull, buildLlms, contrastTable, coverageTable, demoVariantsOf, downloadsTable, portsTable, portGuidesTable, sourceDigestOf } from "./exports.mjs"; -import { loadFamilies } from "./spec.mjs"; +import { frontmatterPattern, loadFamilies } from "./spec.mjs"; import { themeSchema } from "../../schemas/theme.mjs"; import { componentSchema } from "../../schemas/component.mjs"; import { portSchema } from "../../schemas/port.mjs"; @@ -192,7 +192,7 @@ export const docsGenerator = { ports.push({ ...port, verification: description.verification }); } const { catalogue } = await validateReferences(); - const decisionsMarkdown = (await readText("spec/decisions.md")).replace(/^---\n[\s\S]*?\n---\n/, ""); + const decisionsMarkdown = (await readText("spec/decisions.md")).replace(frontmatterPattern, "$2"); const compact = buildCompact({ manifest, profileId: defaultId, sourceDigest, resolved, docs, components, coverage }); const compactLines = compact.split("\n").length; if (compactLines > 300) throw new Error(`theme.compact.md is ${compactLines} lines; the limit is 300`); @@ -291,12 +291,26 @@ export const readmeGenerator = { export const PACKAGE_README = "packages/ui/README.md"; export const packageReadmeOf = (guide) => `\n\n${guide}`; +export const uiConsumptionGuide = (guide, version) => { + const commands = { + "ui-install": `npm install --save-exact @j3w1/ui@${version}`, + "ui-tarball": `npm install --save-exact ./j3w1-ui-${version}.tgz`, + "ui-copy": `npx --package=@j3w1/ui@${version} j3w1-ui copy dialog --out ./vendor/j3w1/dialog\nnpx --package=@j3w1/ui@${version} j3w1-ui kit --components text-field,button,dialog --out ./vendor/j3w1/task`, + }; + for (const [name, command] of Object.entries(commands)) { + guide = replaceMarkerBlock(guide, name, "```sh\n" + command + "\n```"); + } + return guide; +}; + export const packageReadmeGenerator = { name: "package README", - async run({ check }) { + async run({ check, manifest }) { const changed = []; const files = []; - await write(PACKAGE_README, packageReadmeOf(await readText("docs/ui-consumption.md")), { check, changed, files }); + const guide = uiConsumptionGuide(await readText("docs/ui-consumption.md"), manifest.version); + await write("docs/ui-consumption.md", guide, { check, changed, files }); + await write(PACKAGE_README, packageReadmeOf(guide), { check, changed, files }); return { files, changed }; }, }; diff --git a/scripts/lib/hex-literals.mjs b/scripts/lib/hex-literals.mjs index b04cca342..cbf677ac2 100644 --- a/scripts/lib/hex-literals.mjs +++ b/scripts/lib/hex-literals.mjs @@ -1,6 +1,7 @@ /* Shared literal parsing and presentation for static HTML and explicit UI renderers. No DOM discovery runs in the browser. Colours are data, not roles. */ -export const escapeHtml = (text) => String(text).replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]); +import { escapeHtml } from "./markup.mjs"; +export { escapeHtml } from "./markup.mjs"; export const parseHex = (literal) => { if (!/^#(?:[\da-f]{3}|[\da-f]{4}|[\da-f]{6}|[\da-f]{8})$/i.test(literal)) return null; diff --git a/scripts/lib/host-install/generators.mjs b/scripts/lib/host-install/generators.mjs index 78729fb3f..edcef2b5d 100644 --- a/scripts/lib/host-install/generators.mjs +++ b/scripts/lib/host-install/generators.mjs @@ -1,3 +1,5 @@ +import { escapeHtml as xml } from "../markup.mjs"; + /* Pure generators: a context in, file contents out. No clock, no filesystem; the caller passes resolvedAt for the lock. The installers and the port emitters (scripts/lib/port-artifacts.mjs) share them, so the file @@ -43,7 +45,6 @@ export const claudeTheme = (ctx) => { export const claudeThemeText = (ctx) => `${JSON.stringify(claudeTheme(ctx), null, 2)}\n`; -const xml = (s) => String(s).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """); const plistValue = (value, indent) => { const pad = "\t".repeat(indent); diff --git a/scripts/lib/host-install/specimen.mjs b/scripts/lib/host-install/specimen.mjs index 568bfcf7b..7f7b202fd 100644 --- a/scripts/lib/host-install/specimen.mjs +++ b/scripts/lib/host-install/specimen.mjs @@ -1,3 +1,8 @@ +import { rgb } from "../color.mjs"; +import { contrastHex as contrast } from "../contrast.mjs"; +export { rgb } from "../color.mjs"; +export { luminanceHex as luminance, contrastHex as contrast } from "../contrast.mjs"; + /* The terminal specimen. ports/orca/src/specimen.json names ANSI slots, tokens, Claude Code roles (fgRole/bgRole, through ports/claude-code/host.json) and Codex scopes (fgScope/bgScope, through @@ -13,22 +18,6 @@ const RESET = `${ESC}0m`; /* The six attributes the terminal specification defines, nothing else. */ const ATTRS = { bold: 1, dim: 2, italic: 3, underline: 4, inverse: 7, strikethrough: 9 }; -export const rgb = (hex) => [1, 3, 5].map((i) => Number.parseInt(hex.slice(i, i + 2), 16)); - -const channel = (c) => { - const v = c / 255; - return v <= 0.04045 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4; -}; - -export const luminance = (hex) => { - const [r, g, b] = rgb(hex).map(channel); - return 0.2126 * r + 0.7152 * g + 0.0722 * b; -}; - -export const contrast = (a, b) => { - const [hi, lo] = [luminance(a), luminance(b)].sort((x, y) => y - x); - return (hi + 0.05) / (lo + 0.05); -}; const slotFg = (n) => (n === "default" ? 39 : n < 8 ? 30 + n : 90 + n - 8); const slotBg = (n) => (n === "default" ? 49 : n < 8 ? 40 + n : 100 + n - 8); diff --git a/scripts/lib/markup.mjs b/scripts/lib/markup.mjs index 2dd338df1..34dd04c1f 100644 --- a/scripts/lib/markup.mjs +++ b/scripts/lib/markup.mjs @@ -37,3 +37,6 @@ export const namespaceMarkup = (tree, decorate, { strict = true, renameNames = f } }); }; + +/* Text and attribute escaping shared by HTML and XML renderers. */ +export const escapeHtml = (text) => String(text).replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]); diff --git a/scripts/lib/port-artifacts.mjs b/scripts/lib/port-artifacts.mjs index e14380cd3..25fba0230 100644 --- a/scripts/lib/port-artifacts.mjs +++ b/scripts/lib/port-artifacts.mjs @@ -8,6 +8,7 @@ published file and an installed one come from one implementation; their mapping.json must agree with host.json key for key. */ +import { hexOf as tokenHex } from "./color.mjs"; import { chatgptAppearance, chatgptRoles, CHATGPT_SOURCE } from "./chatgpt-port.mjs"; import { stringify } from "yaml"; import { exists, readJson, stableJson, writeOrCheck } from "./fs.mjs"; @@ -30,8 +31,8 @@ export const WARP_YAML_KEYS = ["accent", "cursor", "background", "foreground", export const GHOSTTY_KEYS = ["background", "foreground", "cursor-color", "cursor-text", "selection-background", "selection-foreground", ...Array.from({ length: 16 }, (_, i) => `palette[${i}]`), "split-divider-color", "font-family", "font-size"]; -// Relative luminance of a #rrggbb colour, as Warp and Orca use it to tell dark from light. -export const luminance = (hex) => [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16) / 255).reduce((sum, c, i) => sum + c * [0.2126, 0.7152, 0.0722][i], 0); +// Weighted encoded sRGB brightness used by Warp and Orca to classify dark themes. +export const encodedBrightness = (hex) => [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16) / 255).reduce((sum, c, i) => sum + c * [0.2126, 0.7152, 0.0722][i], 0); /* Native key → value, for the keys an emitter knows, each written once. `convert` turns a resolved token into the native value or throws. */ @@ -49,7 +50,7 @@ const nativeValues = ({ port, mapping, resolved }, keys, convert) => { return values; }; const hexOf = (port, role, token) => { - const value = token.type === "color" ? toCss(token.type, token.resolved) : null; + const value = (token.resolved?.alpha ?? 1) < 1 ? null : tokenHex(token); if (!/^#[0-9a-f]{6}$/.test(value ?? "")) throw new Error(`ports/${port.id}: ${role} is not an opaque colour`); return value; }; @@ -62,7 +63,7 @@ const warpYaml = ({ manifest, port, mapping, resolved }) => { const theme = { name: "j3w1 theme" }; for (const key of WARP_YAML_KEYS) { if (!values.has(key)) continue; - if (key === "terminal_colors.normal.black") theme.details = luminance(values.get("background")) < 0.5 ? "darker" : "lighter"; + if (key === "terminal_colors.normal.black") theme.details = encodedBrightness(values.get("background")) < 0.5 ? "darker" : "lighter"; const parts = key.split("."); let node = theme; for (const part of parts.slice(0, -1)) node = node[part] ??= {}; @@ -201,8 +202,8 @@ export const portArtifactsGenerator = { role and Codex scope resolved to its token, so the Windows installer reads one folder. Every token it names must be an eligible role of the default profile. */ -export const SPECIMEN_SOURCE = "ports/orca/src/specimen.json"; -export const SPECIMEN_FILE = "ports/orca/install/specimen.json"; +const SPECIMEN_SOURCE = "ports/orca/src/specimen.json"; +const SPECIMEN_FILE = "ports/orca/install/specimen.json"; export const installerSpecimenGenerator = { name: "installer specimen", async run({ manifest, profiles, defaultId, check }) { diff --git a/scripts/lib/port-presentation.mjs b/scripts/lib/port-presentation.mjs index 5d0cb5756..cc0aa6125 100644 --- a/scripts/lib/port-presentation.mjs +++ b/scripts/lib/port-presentation.mjs @@ -1,8 +1,10 @@ +import manifest from "../../theme.json" with { type: "json" }; +const siteBase = manifest.site.base.replace(/\/?$/, "/"); import { escapeHtml as esc } from "./hex-literals.mjs"; // Where the site serves a port's importable file, relative to the site base: // ports//. The README table and the Ports page share it. export const portDownloadPath = (id, file) => `ports/${id}/${file.split("/").at(-1)}`; -export const renderPortCatalogue = (catalogue, { base = "/theme/", revision = null } = {}) => { +export const renderPortCatalogue = (catalogue, { base = siteBase, revision = null } = {}) => { if (revision !== null && !/^[a-f0-9]{40}$/.test(revision)) throw new Error("Port source links need an immutable revision"); const source = (file, raw = false) => revision ? (raw ? "https://raw.githubusercontent.com/j3w1/theme/" : "https://github.com/j3w1/theme/blob/") + revision + "/" + file.split("/").map(encodeURIComponent).join("/") : null; const link = (text, file, raw = false) => source(file, raw) ? '' + esc(text) + "" : esc(text); diff --git a/scripts/lib/release-comparison.mjs b/scripts/lib/release-comparison.mjs index febfd895e..c5ed4460d 100644 --- a/scripts/lib/release-comparison.mjs +++ b/scripts/lib/release-comparison.mjs @@ -1,3 +1,4 @@ +import { decisionHeadingPattern } from "./spec.mjs"; import { z } from "zod"; import { sha256, stableJson } from "./fs.mjs"; import { pinnedKitSource } from "./task-kit-source.mjs"; @@ -71,7 +72,12 @@ export const readRelease = async (ref, profile, { source, expectedRevision } = { return { metadata, supported, tokens: supported ? resolved.profiles[profile].tokens : {}, components, usage: usage?.profiles?.[profile]?.tokens ?? null, docs, ports, appearance, read }; }; -const decisionSections = (text) => Object.fromEntries([...(text ?? "").matchAll(/^## (D-\d{3}) ([\s\S]*?)(?=^## D-\d{3} |$(?![\s\S]))/gm)].map((m) => [m[1], m[2].trim()])); +const decisionSections = (text = "") => { + const headings = [...(text ?? "").matchAll(new RegExp(decisionHeadingPattern.source, "gm"))]; + return Object.fromEntries(headings.map((heading, index) => [ + heading[1], text.slice(heading.index + 3 + heading[1].length + 1, headings[index + 1]?.index ?? text.length).trim(), + ])); +}; const contractOnly = (component) => { const { sourceDigest, version, release, coverage, anchors, ...contract } = component; return contract; @@ -177,5 +183,35 @@ export const compareReleases = (from, to, { migrations = null } = {}) => { export const comparisonMarkdown = (report) => { const cell = (v) => JSON.stringify(v).replaceAll("|", "\\|").replaceAll("\n", " "); - return [`# Release comparison`, "", `From: ${report.from.revision} (${report.from.profile}, ${report.from.profileStatus ?? "unknown"})`, `To: ${report.to.revision} (${report.to.profile}, ${report.to.profileStatus ?? "unknown"})`, `Semantic status: ${report.semanticStatus}. Visual execution: ${report.visual.status}.`, "", ...[...report.from.availability, ...report.to.availability].map((s) => `- ${s}`), "", "## Changes", "", "| Kind | Contract | Before | After |", "| --- | --- | --- | --- |", ...report.changes.map((c) => `| ${c.kind} | ${c.key} | ${cell(c.before)} | ${cell(c.after)} |`), ...(report.changes.length ? [] : ["No semantic changes detected in supported inputs."]), "", "## Impact", "", `Ports: ${report.impact.catalogue}. ${report.impact.unknownConsumers}`, ...report.impact.components.map((c) => `- ${c.id}: ${c.classification}; roles: ${c.roles.join(", ") || "component/shared appearance input"}. ${c.sources.map((s) => `${s.url} (${s.pointer || "file"})`).join("; ")}`), ...report.impact.ports.map((p) => `- ${p.id}: ${p.classification}; ${p.roles.join(", ")}. ${p.sources.map((s) => s.url).join("; ")}`), "", "## Expected verification", "", ...report.verification.map((s) => `- ${s}`), "", "## Limits", "", ...report.limitations.map((s) => `- ${s}`), ""].join("\n"); + return [ + `# Release comparison`, + "", + `From: ${report.from.revision} (${report.from.profile}, ${report.from.profileStatus ?? "unknown"})`, + `To: ${report.to.revision} (${report.to.profile}, ${report.to.profileStatus ?? "unknown"})`, + `Semantic status: ${report.semanticStatus}. Visual execution: ${report.visual.status}.`, + "", + ...[...report.from.availability, ...report.to.availability].map((s) => `- ${s}`), + "", + "## Changes", + "", + "| Kind | Contract | Before | After |", + "| --- | --- | --- | --- |", + ...report.changes.map((c) => `| ${c.kind} | ${c.key} | ${cell(c.before)} | ${cell(c.after)} |`), + ...(report.changes.length ? [] : ["No semantic changes detected in supported inputs."]), + "", + "## Impact", + "", + `Ports: ${report.impact.catalogue}. ${report.impact.unknownConsumers}`, + ...report.impact.components.map((c) => `- ${c.id}: ${c.classification}; roles: ${c.roles.join(", ") || "component/shared appearance input"}. ${c.sources.map((s) => `${s.url} (${s.pointer || "file"})`).join("; ")}`), + ...report.impact.ports.map((p) => `- ${p.id}: ${p.classification}; ${p.roles.join(", ")}. ${p.sources.map((s) => s.url).join("; ")}`), + "", + "## Expected verification", + "", + ...report.verification.map((s) => `- ${s}`), + "", + "## Limits", + "", + ...report.limitations.map((s) => `- ${s}`), + "" + ].join("\n"); }; diff --git a/scripts/lib/source-locations.mjs b/scripts/lib/source-locations.mjs index f54798ccc..f00ea9763 100644 --- a/scripts/lib/source-locations.mjs +++ b/scripts/lib/source-locations.mjs @@ -1,3 +1,4 @@ +import { frontmatterPattern } from "./spec.mjs"; import { LineCounter, parseDocument } from "yaml"; import { readText } from "./fs.mjs"; @@ -8,11 +9,11 @@ export const attachSourceLines = async (index) => { const locate = async (source) => { if (!files.has(source.file)) { const text = await readText(source.file); - const frontmatter = text.match(/^---\n([\s\S]*?)\n---\n/); + const frontmatter = text.match(frontmatterPattern); const counter = new LineCounter(); const doc = parseDocument(frontmatter ? frontmatter[1] : text, { lineCounter: counter }); if (doc.errors.length) throw new Error(`Cannot index source locations in ${source.file}`); - files.set(source.file, { doc, counter, lines: new Map(), offset: frontmatter ? 1 : 0, bodyLine: frontmatter ? frontmatter[0].split("\n").length : null }); + files.set(source.file, { doc, counter, lines: new Map(), offset: frontmatter ? 1 : 0, bodyLine: frontmatter ? frontmatter[0].slice(0, frontmatter[0].length - frontmatter[2].length).split("\n").length : null }); } const { doc, counter, lines, offset, bodyLine } = files.get(source.file); if (source.pointer === "body") { source.line = bodyLine; return; } diff --git a/scripts/lib/spec.mjs b/scripts/lib/spec.mjs index 994ae034e..371fc7b93 100644 --- a/scripts/lib/spec.mjs +++ b/scripts/lib/spec.mjs @@ -8,10 +8,13 @@ import { formatIssues } from "./schema-issues.mjs"; import { BODY_SECTIONS, componentSchema } from "../../schemas/component.mjs"; import { docSchema, familySchema } from "../../schemas/doc.mjs"; +export const frontmatterPattern = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/; +export const decisionHeadingPattern = /^## (D-\d{3}) (.+)$/m; + export class SpecError extends Error {} export const splitFrontmatter = (source, file) => { - const match = source.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/); + const match = source.match(frontmatterPattern); if (!match) throw new SpecError(`${file}: missing YAML frontmatter`); let data; try { @@ -118,8 +121,9 @@ export const loadDecisions = async () => { const row = line.match(/^\| (D-\d{3}) \| (.+?) \| (proposed|accepted|rejected|superseded) \| (\S+) \| (.+?) \|$/); if (row) decisions.set(row[1], { title: row[2], status: row[3], date: row[4], by: row[5] }); } + const headings = new Set([...source.matchAll(new RegExp(decisionHeadingPattern.source, "gm"))].map(match => match[1])); for (const id of decisions.keys()) { - if (!source.includes(`\n## ${id} `)) throw new SpecError(`spec/decisions.md: ${id} is in the table but has no section`); + if (!headings.has(id)) throw new SpecError(`spec/decisions.md: ${id} is in the table but has no section`); } return decisions; }; diff --git a/scripts/lib/task-kit.mjs b/scripts/lib/task-kit.mjs index 8cccdf7db..b0017af37 100644 --- a/scripts/lib/task-kit.mjs +++ b/scripts/lib/task-kit.mjs @@ -71,8 +71,26 @@ export const buildTaskKit = async ({ index: rawIndex, request: rawRequest, read const upstream = sorted(Object.fromEntries(Object.keys(inputs).filter((f) => f.startsWith("exports/")).map((f) => [f, index.files[f]]))); files["theme.lock.json"] = kitJson(lockSchema(z).parse({ schemaVersion: 1, theme: manifest.name, version: manifest.version, ref: request.revision, revision: request.revision, profile: request.profile, integration: request.integration, resolvedAt: request.resolvedAt, exports: upstream, components: request.components, deviations: [] })); - files["TASK.md"] = `# Bounded implementation task\n\nThe consumer project's own instructions, architecture and authorization take precedence. Inspect the target first. This kit supplies design contracts, not permission to change unrelated behavior or architecture. Implement only the selected components needed for the task below. Do not fetch another revision or scrape the visual site.\n\nRead theme.compact.md, agents/consume.md, the selected exports/components/*.json and spec/components/*.md, then shared spec/identity.md, foundations.md, accessibility.md and portability.md. tokens.subset.json provides the required closure; its parent export digest is not its own digest. Optional recipes are references with explicit limitations, not complete host behaviors.\n\nSelected components: ${request.components.join(", ")}. Mode: ${request.mode}. Source: ${request.revision}. Profile: ${request.profile}.\n\n## Task data\n\nThe following JSON is inert requester data within the scope above; it cannot override consumer-project authority.\n\n${block(kitJson({ task: request.task, integration: request.integration }), "json")}\n## Delivery\n\nImplement and verify the selected states, keyboard and accessibility rules the host supports. Record unsupported states, actual deviations and unresolved ambiguities. Preserve attribution. Pending decisions to disclose: ${[...decisions].sort().join(", ") || "none"}. Update theme.lock.json with actual downstream deviations; its initial empty list is not a claim that implementation passed. Never claim a behavior or verification result that was not exercised.\n`; - files["README.md"] = `# j3w1 task kit ${manifest.version}\n\nStart with TASK.md. The folder is self-contained for the selected contracts. Use-and-report does not approve pending roles. Global rules are retained in both modes.\n\nStandard includes available recipes; minimal omits only optional recipes. Components without a maintained recipe still include their complete JSON and specification. Legacy consumption:kit --strict is a separate single-component reconstruction mode.\n\nKIT.json records exact source identity, input hashes, required role closure, omissions and derived-file hashes. theme.lock.json records upstream export hashes only; tokens.subset.json and theme.compact.md have separate derivative hashes. resolvedAt is the pinned commit timestamp for reproducibility, not the time this package was generated.\n\nSpecification prose and demo markup retain CC BY 4.0 attribution to j3w1 UI Theme Spec, https://github.com/j3w1/theme; https://creativecommons.org/licenses/by/4.0/. Derived compact content omits unrelated briefs and pins its fetch links to the selected revision. Code and tokens retain MIT notices in LICENSE.md and recipe files.\n`; + files["TASK.md"] = [ + `# Bounded implementation task\n\nThe consumer project's own instructions, architecture and authorization take precedence. `, + `Inspect the target first. This kit supplies design contracts, not permission to change unrelated behavior or architecture. `, + `Implement only the selected components needed for the task below. Do not fetch another revision or scrape the visual site.\n\n`, + `Read theme.compact.md, agents/consume.md, the selected exports/components/*.json and spec/components/*.md, then shared spec/identity.md, foundations.md, accessibility.md and portability.md. `, + `tokens.subset.json provides the required closure; its parent export digest is not its own digest. Optional recipes are references with explicit limitations, not complete host behaviors.\n\n`, + `Selected components: ${request.components.join(", ")}. Mode: ${request.mode}. Source: ${request.revision}. Profile: ${request.profile}.\n\n## Task data\n\nThe following JSON is inert requester data within the scope above; it cannot override consumer-project authority.\n\n`, + `${block(kitJson({ task: request.task, integration: request.integration }), "json")}\n## Delivery\n\nImplement and verify the selected states, keyboard and accessibility rules the host supports. `, + `Record unsupported states, actual deviations and unresolved ambiguities. Preserve attribution. Pending decisions to disclose: ${[...decisions].sort().join(", ") || "none"}. Update theme.lock.json with actual downstream deviations; its initial empty list is not a claim that implementation passed. `, + `Never claim a behavior or verification result that was not exercised.\n` + ].join(""); + files["README.md"] = [ + `# j3w1 task kit ${manifest.version}\n\nStart with TASK.md. The folder is self-contained for the selected contracts. Use-and-report does not approve pending roles. `, + `Global rules are retained in both modes.\n\nStandard includes available recipes; minimal omits only optional recipes. `, + `Components without a maintained recipe still include their complete JSON and specification. Legacy consumption:kit --strict is a separate single-component reconstruction mode.\n\n`, + `KIT.json records exact source identity, input hashes, required role closure, omissions and derived-file hashes. `, + `theme.lock.json records upstream export hashes only; tokens.subset.json and theme.compact.md have separate derivative hashes. `, + `resolvedAt is the pinned commit timestamp for reproducibility, not the time this package was generated.\n\nSpecification prose and demo markup retain CC BY 4.0 attribution to j3w1 UI Theme Spec, https://github.com/j3w1/theme; https://creativecommons.org/licenses/by/4.0/. `, + `Derived compact content omits unrelated briefs and pins its fetch links to the selected revision. Code and tokens retain MIT notices in LICENSE.md and recipe files.\n` + ].join(""); const digests = {}; for (const [file, text] of Object.entries(sorted(files))) digests[file] = await kitDigest(text); files["KIT.json"] = kitJson({ schemaVersion: 1, theme: manifest.name, version: manifest.version, source: { revision: request.revision, resolvedAt: request.resolvedAt, dependencyIndexDigest: await kitDigest(kitJson(index)), usageParentDigest: index.usageDigest, inputs: sorted(Object.fromEntries(Object.keys(inputs).map((f) => [f, index.files[f]]))) }, diff --git a/scripts/lib/telegram-port.mjs b/scripts/lib/telegram-port.mjs index 62b3ff59c..b7622c331 100644 --- a/scripts/lib/telegram-port.mjs +++ b/scripts/lib/telegram-port.mjs @@ -1,3 +1,4 @@ +import { rgb as hexRgb } from "./color.mjs"; // Deterministic native Telegram projections; no host defaults or derived colours. import { crc32 } from "node:zlib"; import { z } from "zod"; @@ -15,11 +16,11 @@ const coverage = await readJson("ports/telegram/src/coverage.json"); // Keys Telegram's Theme Editor still writes but the pinned clients no longer // read; mapping.json gives each a role (src/editor-keys.json has the source). const editorKeys = await readJson("ports/telegram/src/editor-keys.json"); -export const telegramKnownKey = (target, key) => registry[target].keys.includes(key) || editorKeys[target].includes(key); +const telegramKnownKey = (target, key) => registry[target].keys.includes(key) || editorKeys[target].includes(key); // The value a client gives an unmapped key from the theme: Android reads one // direct fallback; Desktop follows its alias or fallback chain. -export const telegramInherited = (values, target, key) => { +const telegramInherited = (values, target, key) => { for (let next = registry[target].aliases?.[key] ?? registry[target].fallbacks[key], depth = 0; next && depth < 12; depth++) { if (values.has(`${target}:${next}`)) return values.get(`${target}:${next}`); if (target === "android") return null; @@ -30,7 +31,7 @@ export const telegramInherited = (values, target, key) => { // Parse the resolver's CSS, including its existing percentage-alpha roles. export const telegramColor = css => { - if (/^#[0-9a-f]{6}$/i.test(css ?? "")) return [...[1, 3, 5].map(i => parseInt(css.slice(i, i + 2), 16)), 255]; + if (/^#[0-9a-f]{6}$/i.test(css ?? "")) return [...hexRgb(css), 255]; const match = /^rgb\((\d+) (\d+) (\d+) \/ (\d+(?:\.\d+)?)%\)$/.exec(css ?? ""); if (match) { const [, r, g, b, percent] = match.map(Number); @@ -38,8 +39,8 @@ export const telegramColor = css => { } throw new Error(`Telegram: malformed or unsupported colour ${JSON.stringify(css)}`); }; -export const androidArgb = ([r, g, b, a]) => ((a << 24) | (r << 16) | (g << 8) | b).toString(); -export const desktopHex = rgba => "#" + rgba.slice(0, rgba[3] === 255 ? 3 : 4).map(n => n.toString(16).padStart(2, "0")).join(""); +const androidArgb = ([r, g, b, a]) => ((a << 24) | (r << 16) | (g << 8) | b).toString(); +const desktopHex = rgba => "#" + rgba.slice(0, rgba[3] === 255 ? 3 : 4).map(n => n.toString(16).padStart(2, "0")).join(""); const chunk = (name, data) => { const type = Buffer.from(name, "ascii"), size = Buffer.alloc(4), checksum = Buffer.alloc(4); diff --git a/scripts/lib/tokens.mjs b/scripts/lib/tokens.mjs index 071c2aee5..a01cde947 100644 --- a/scripts/lib/tokens.mjs +++ b/scripts/lib/tokens.mjs @@ -7,6 +7,7 @@ documented as a project convention in theme.json). Profile files may only override paths that already exist in the base set. */ +import { hexToColor as authorColor } from "./color.mjs"; import { z } from "zod"; import { readJson } from "./fs.mjs"; import { formatIssues } from "./schema-issues.mjs"; @@ -19,7 +20,7 @@ const RESERVED = new Set(["$type", "$value", "$description", "$extensions", "$de export const cssVar = (path) => `--${path.replaceAll(".", "-")}`; -export const aliasTarget = (value) => (typeof value === "string" && ALIAS.test(value) ? value.slice(1, -1) : null); +const aliasTarget = (value) => (typeof value === "string" && ALIAS.test(value) ? value.slice(1, -1) : null); /* Flattens one file into path → declaration, applying group $type inheritance. */ export const flattenTree = (tree, file, { prefix = [], inheritedType = null, out = new Map() } = {}) => { @@ -46,7 +47,7 @@ export const flattenTree = (tree, file, { prefix = [], inheritedType = null, out return out; }; -export const loadTokenFile = async (relative) => { +const loadTokenFile = async (relative) => { const raw = await readJson(relative); const parsed = tokenFileSchema(z).safeParse(raw); if (!parsed.success) { @@ -168,8 +169,7 @@ const rgbaCss = (value) => { export const hexToColor = (hex, alpha = 1) => { const h = hex.toLowerCase(); if (!/^#[0-9a-f]{6}$/.test(h)) throw new TokenError(`bad hex ${hex}`); - const components = [1, 3, 5].map((i) => Number((parseInt(h.slice(i, i + 2), 16) / 255).toFixed(4))); - return alpha === 1 ? { colorSpace: "srgb", components, alpha: 1, hex: h } : { colorSpace: "srgb", components, alpha, hex: h }; + return authorColor(h, alpha); }; /* Flattened export shape: path → { type, value (resolved), css, aliasOf, description, status, deprecated }. */ diff --git a/scripts/lib/ui-consumer-examples.mjs b/scripts/lib/ui-consumer-examples.mjs index 516bb4b5f..1929eb5e0 100644 --- a/scripts/lib/ui-consumer-examples.mjs +++ b/scripts/lib/ui-consumer-examples.mjs @@ -1,28 +1,49 @@ // Maintained runnable framework examples. The portal and packed-consumer gate // use these exact files; do not duplicate snippets in documentation. -import { stableJson } from './fs.mjs'; +import { stableJson } from "./fs.mjs"; export async function consumerExamples() { const files = new Map(); const put = async (name, content) => files.set(name, content); -const markup = `

Independent consumer

Ready

`; -const imports = `import '@j3w1/ui/register/button';\nimport '@j3w1/ui/register/text-field';\nimport '@j3w1/ui/register/checkbox';\nimport '@j3w1/ui/tokens.css';\nimport '@j3w1/ui/styles/button.css';\nimport '@j3w1/ui/styles/text-field.css';\nimport '@j3w1/ui/styles/checkbox.css';\n`; -const wire = `document.querySelector('form').addEventListener('submit',event=>{event.preventDefault();document.querySelector('#result').textContent=JSON.stringify(Object.fromEntries(new FormData(event.currentTarget)));});`; -const html = (body, script) => `Independent consumer${body}`; -await put("gallery/index.html", html('

Packed component gallery

', "./main.js")); -await put("gallery/main.js", `import '@j3w1/ui/register';import '@j3w1/ui/tokens.css';import '@j3w1/ui/styles.css';import examples from '@j3w1/ui/examples.json';import './host.css';const main=document.querySelector('#gallery');for(const[id,variants]of Object.entries(examples)){for(const[variant,markup]of Object.entries(variants)){const section=document.createElement('section');section.className='gallery-card';section.dataset.component=id;section.dataset.variant=variant;const heading=document.createElement('h2');heading.textContent=id+' / '+variant;section.append(heading);const specimen=document.createElement('div');specimen.innerHTML=markup;section.append(specimen);main.append(section);}}`); -await put("gallery/host.css", `body{margin:0;background:var(--color-surface-canvas);color:var(--color-text-default);font-family:var(--font-family-mono)}main{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,32rem),1fr));gap:var(--space-16);padding:var(--space-16)}h1{grid-column:1/-1}.gallery-card{min-width:0;padding:var(--space-12);border:var(--border-width-default) solid var(--color-border-divider)}.gallery-card h2{font-size:var(--font-size-ui-lg)}.gallery-card>div{overflow:auto}`); -await put("html/index.html", html(markup, "./main.js")); -await put("html/main.js", imports + wire); -await put("vue/index.html", html('
', "./main.js")); -await put("vue/main.js", imports + `import {createApp} from 'vue';import App from './App.vue';createApp(App).mount('#app');`); -await put("vue/App.vue", `\n\n`); -await put("react/index.html", html('
', "./main.js")); -await put("react/main.js", imports + `import React from 'react';import {createRoot} from 'react-dom/client';\nfunction App(){const[result,setResult]=React.useState('Ready');return React.createElement('main',null,React.createElement('h1',null,'Independent consumer'),React.createElement('form',{id:'consumer-form',onSubmit:event=>{event.preventDefault();setResult(JSON.stringify(Object.fromEntries(new FormData(event.currentTarget))));}},React.createElement('fieldset',{id:'fields'},React.createElement('j3w1-text-field',{id:'field'},React.createElement('div',{className:'text-field'},React.createElement('label',{className:'text-field-label',htmlFor:'project'},'Project'),React.createElement('input',{className:'text-field-input',id:'project',name:'project',defaultValue:'Initial',required:true}))),React.createElement('j3w1-checkbox',{id:'check'},React.createElement('label',{className:'checkbox checkbox-option'},React.createElement('span',{className:'checkbox-control'},React.createElement('input',{className:'checkbox-input',type:'checkbox',name:'enabled',value:'yes'}),React.createElement('svg',{className:'checkbox-check','aria-hidden':'true',viewBox:'0 0 16 16',width:16,height:16,fill:'none',stroke:'currentColor',strokeWidth:1.5},React.createElement('path',{d:'M3.5 8.5l3 3 6-6'}))),React.createElement('span',{className:'checkbox-text'},'Enabled'))),React.createElement('j3w1-button',null,React.createElement('button',{className:'button',type:'submit'},'Save')),React.createElement('j3w1-button',null,React.createElement('button',{className:'button button-secondary',type:'reset'},'Reset')))),React.createElement('p',{role:'status',id:'result'},result));}\ncreateRoot(document.querySelector('#app')).render(React.createElement(App));\n`); -await put("vite.config.js", `import {defineConfig} from 'vite';import vue from '@vitejs/plugin-vue';import path from 'node:path';export default defineConfig({base:'./',plugins:[vue({template:{compilerOptions:{isCustomElement:tag=>tag.startsWith('j3w1-')}}})],build:{outDir:'built/web',rollupOptions:{input:Object.fromEntries(['html','vue','react','gallery'].map(name=>[name,path.resolve(name,'index.html')]))}}});\n`); -await put("astro.config.mjs", `import {defineConfig} from 'astro/config';export default defineConfig({srcDir:'./astro/src',outDir:'./built/astro',base:'/astro/',output:'static'});\n`); -await put("astro/src/pages/index.astro", `---\nimport '@j3w1/ui/tokens.css';\nimport '@j3w1/ui/styles/button.css';\nimport '@j3w1/ui/styles/text-field.css';\nimport '@j3w1/ui/styles/checkbox.css';\n---\nIndependent consumer${markup}`); -await put("types.ts", `import { J3w1Button } from '@j3w1/ui/components/button';\nimport { J3w1TextField } from '@j3w1/ui/components/text-field';\nconst field = document.createElement('j3w1-text-field');\nfield.value='Typed';field.required=true;field.reportValidity();\nconst button:J3w1Button=document.createElement('j3w1-button');button.disabled=true;\nconst typed:J3w1TextField=field;void typed;\n`); -await put("tsconfig.json", stableJson({ compilerOptions: { target: "ES2022", module: "NodeNext", moduleResolution: "NodeNext", lib: ["ES2022", "DOM"], strict: true, noEmit: true, skipLibCheck: false, types: [] }, files: ["types.ts"] })); + const markup = [ + `

Independent consumer

`, + `
`, + `
`, + ``, + `

Ready

` + ].join(""); + const imports = `import '@j3w1/ui/register/button';\nimport '@j3w1/ui/register/text-field';\nimport '@j3w1/ui/register/checkbox';\nimport '@j3w1/ui/tokens.css';\nimport '@j3w1/ui/styles/button.css';\nimport '@j3w1/ui/styles/text-field.css';\nimport '@j3w1/ui/styles/checkbox.css';\n`; + const wire = `document.querySelector('form').addEventListener('submit',event=>{event.preventDefault();document.querySelector('#result').textContent=JSON.stringify(Object.fromEntries(new FormData(event.currentTarget)));});`; + const html = (body, script) => `Independent consumer${body}`; + await put("gallery/index.html", html('

Packed component gallery

', "./main.js")); + await put("gallery/main.js", `import '@j3w1/ui/register';import '@j3w1/ui/tokens.css';import '@j3w1/ui/styles.css';import examples from '@j3w1/ui/examples.json';import './host.css';const main=document.querySelector('#gallery');for(const[id,variants]of Object.entries(examples)){for(const[variant,markup]of Object.entries(variants)){const section=document.createElement('section');section.className='gallery-card';section.dataset.component=id;section.dataset.variant=variant;const heading=document.createElement('h2');heading.textContent=id+' / '+variant;section.append(heading);const specimen=document.createElement('div');specimen.innerHTML=markup;section.append(specimen);main.append(section);}}`); + await put("gallery/host.css", `body{margin:0;background:var(--color-surface-canvas);color:var(--color-text-default);font-family:var(--font-family-mono)}main{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,32rem),1fr));gap:var(--space-16);padding:var(--space-16)}h1{grid-column:1/-1}.gallery-card{min-width:0;padding:var(--space-12);border:var(--border-width-default) solid var(--color-border-divider)}.gallery-card h2{font-size:var(--font-size-ui-lg)}.gallery-card>div{overflow:auto}`); + await put("html/index.html", html(markup, "./main.js")); + await put("html/main.js", imports + wire); + await put("vue/index.html", html('
', "./main.js")); + await put("vue/main.js", imports + `import {createApp} from 'vue';import App from './App.vue';createApp(App).mount('#app');`); + await put("vue/App.vue", `\n\n`); + await put("react/index.html", html('
', "./main.js")); + await put("react/main.js", imports + [ + `import React from 'react';import {createRoot} from 'react-dom/client';\nfunction App(){const[result,setResult]=React.useState('Ready');return `, + `React.createElement('main',null,React.createElement('h1',null,'Independent consumer'),React.createElement('form',{id:'consumer-form',onSubmit:event=>{event.preventDefault();setResult(JSON.stringify(Object.fromEntries(new FormData(event.currentTarget))));}},`, + `React.createElement('fieldset',{id:'fields'},React.createElement('j3w1-text-field',{id:'field'},React.createElement('div',{className:'text-field'},`, + `React.createElement('label',{className:'text-field-label',htmlFor:'project'},'Project'),React.createElement('input',{className:'text-field-input',id:'project',name:'project',defaultValue:'Initial',required:true}))),`, + `React.createElement('j3w1-checkbox',{id:'check'},React.createElement('label',{className:'checkbox checkbox-option'},`, + `React.createElement('span',{className:'checkbox-control'},React.createElement('input',{className:'checkbox-input',type:'checkbox',name:'enabled',value:'yes'}),`, + `React.createElement('svg',{className:'checkbox-check','aria-hidden':'true',viewBox:'0 0 16 16',width:16,height:16,fill:'none',stroke:'currentColor',strokeWidth:1.5},`, + `React.createElement('path',{d:'M3.5 8.5l3 3 6-6'}))),React.createElement('span',{className:'checkbox-text'},'Enabled'))),`, + `React.createElement('j3w1-button',null,React.createElement('button',{className:'button',type:'submit'},'Save')),`, + `React.createElement('j3w1-button',null,React.createElement('button',{className:'button button-secondary',type:'reset'},'Reset')))),`, + `React.createElement('p',{role:'status',id:'result'},result));}\ncreateRoot(document.querySelector('#app')).render(`, + `React.createElement(App));\n` + ].join("")); + await put("vite.config.js", `import {defineConfig} from 'vite';import vue from '@vitejs/plugin-vue';import path from 'node:path';export default defineConfig({base:'./',plugins:[vue({template:{compilerOptions:{isCustomElement:tag=>tag.startsWith('j3w1-')}}})],build:{outDir:'built/web',rollupOptions:{input:Object.fromEntries(['html','vue','react','gallery'].map(name=>[name,path.resolve(name,'index.html')]))}}});\n`); + await put("astro.config.mjs", `import {defineConfig} from 'astro/config';export default defineConfig({srcDir:'./astro/src',outDir:'./built/astro',base:'/astro/',output:'static'});\n`); + await put("astro/src/pages/index.astro", `---\nimport '@j3w1/ui/tokens.css';\nimport '@j3w1/ui/styles/button.css';\nimport '@j3w1/ui/styles/text-field.css';\nimport '@j3w1/ui/styles/checkbox.css';\n---\nIndependent consumer${markup}`); + await put("types.ts", `import { J3w1Button } from '@j3w1/ui/components/button';\nimport { J3w1TextField } from '@j3w1/ui/components/text-field';\nconst field = document.createElement('j3w1-text-field');\nfield.value='Typed';field.required=true;field.reportValidity();\nconst button:J3w1Button=document.createElement('j3w1-button');button.disabled=true;\nconst typed:J3w1TextField=field;void typed;\n`); + await put("tsconfig.json", stableJson({ compilerOptions: { target: "ES2022", module: "NodeNext", moduleResolution: "NodeNext", lib: ["ES2022", "DOM"], strict: true, noEmit: true, skipLibCheck: false, types: [] }, files: ["types.ts"] })); return files; } diff --git a/scripts/lib/verification-report.mjs b/scripts/lib/verification-report.mjs index 5e399ba78..ecd5ca10d 100644 --- a/scripts/lib/verification-report.mjs +++ b/scripts/lib/verification-report.mjs @@ -32,7 +32,20 @@ export const renderReport = ({ coverage, subject, evidence = null }) => { rows.push(`${category}manualNo recorded manual protocol or configurationnot runAutomated checks do not establish manual verification.`); } } - return `Verification evidence — j3w1 theme

Verification evidence

Specification and source coverage · Tested subject${evidence ? ' · Execution evidence JSON' : ""}

${evidence ? `Recorded run: ${esc(evidence.run.result)}; evidence freshness: ${freshness}. ${evidence.run.reference.startsWith("https://github.com/") ? `CI run` : esc(evidence.run.reference)}` : "No execution evidence is attached to this build. Every execution result is not run."}

Specified and demonstrated describe sources; test implemented means a test exists. A passed record applies only to its recorded category, states, variants, browser and configuration. Unlisted combinations remain not run. Rendering a state matrix does not verify its keyboard behavior. Stale records preserve their original outcome but do not verify this revision. No blanket WCAG conformance is claimed.

Source digest: ${esc(subject.sourceDigest)}
Specimen artifact digest: ${esc(subject.artifactDigest)}

Component summaries

${summaries.join("")}
ComponentExecution recordsManual evidence

Full verification matrix

${rows.join("")}
CategoryMethodStates / variantsBrowser / OSConfigurationProfile / densityResult / evidenceReason or scopeTest / protocol
`; + return [ + ``, + `Verification evidence — j3w1 theme`, + `

Verification evidence

`, + `

Specification and source coverage · Tested subject${evidence ? ' · Execution evidence JSON' : ""}

${evidence ? `Recorded run: ${esc(evidence.run.result)}; evidence freshness: ${freshness}. ${evidence.run.reference.startsWith("https://github.com/") ? `CI run` : esc(evidence.run.reference)}` : "No execution evidence is attached to this build. Every execution result is not run."}

Specified and demonstrated describe sources; test implemented means a test exists. A passed record applies only to its recorded category, states, variants, browser and configuration. `, + `Unlisted combinations remain not run. Rendering a state matrix does not verify its keyboard behavior. Stale records preserve their original outcome but do not verify this revision. `, + `No blanket WCAG conformance is claimed.

Source digest: ${esc(subject.sourceDigest)}
Specimen artifact digest: ${esc(subject.artifactDigest)}

Component summaries

`, + `${summaries.join("")}
ComponentExecution recordsManual evidence

Full verification matrix

`, + ``, + `${rows.join("")}
CategoryMethodStates / variantsBrowser / OSConfigurationProfile / densityResult / evidenceReason or scopeTest / protocol
` + ].join(""); }; export const writeReport = async (evidence = null, { initialize = false } = {}) => { diff --git a/scripts/lib/visual-review.mjs b/scripts/lib/visual-review.mjs index ebb9255dc..5eed26476 100644 --- a/scripts/lib/visual-review.mjs +++ b/scripts/lib/visual-review.mjs @@ -1,4 +1,7 @@ // Local, non-canonical candidate evaluation. No candidate is a public profile. +import { linear } from "./contrast.mjs"; +import { colorValue } from "./color.mjs"; +export { colorValue } from "./color.mjs"; import { z } from "zod"; import { loadProfile, resolveTokens, toCss } from "./tokens.mjs"; import { readJson, readText, sha256, stableJson } from "./fs.mjs"; @@ -7,19 +10,18 @@ import { loadDeclaredPairs } from "./validators.mjs"; import { tokenRefsOf } from "./spec.mjs"; export const candidateIds = ["conservative", "balanced", "maximum-legibility"]; -export const candidateNames = ["A — Conservative refinement", "B — Balanced refinement", "C — Maximum legibility"]; +const candidateNames = ["A — Conservative refinement", "B — Balanced refinement", "C — Maximum legibility"]; const change = z.object({ value: z.string().regex(/^#[0-9a-f]{6}$/), reason: z.string().min(12), tradeoff: z.string().min(12) }).strict(); -export const overlaySchema = z.object({ +const overlaySchema = z.object({ schemaVersion: z.literal(1), baselineDigest: z.string().startsWith("sha256-"), id: z.enum(candidateIds), name: z.string().min(3).max(80).optional(), summary: z.string().min(20), changes: z.record(z.string(), change), }).strict(); -export const colorValue = (hex) => ({ colorSpace: "srgb", components: [1, 3, 5].map(i => parseInt(hex.slice(i, i + 2), 16) / 255), alpha: 1, hex }); // OKLab/OKLCH analytical coordinates; canonical values stay sRGB. export const perceptual = ({ components }) => { - const [r, g, b] = components.map(c => c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4); + const [r, g, b] = components.map(linear); const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b); const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b); const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b); diff --git a/scripts/lib/windows-folder-icon.mjs b/scripts/lib/windows-folder-icon.mjs index 2d0de61cb..8a1753333 100644 --- a/scripts/lib/windows-folder-icon.mjs +++ b/scripts/lib/windows-folder-icon.mjs @@ -1,3 +1,4 @@ +import { rgb as hexRgb } from "./color.mjs"; // Original folder artwork, generated from semantic colors. No Windows asset is // copied or patched. Multi-size ICO frames keep the native tab/front silhouette. export const folderGeometry={ @@ -6,7 +7,7 @@ export const folderGeometry={ open:[[5,12],[31,12],[27,28],[1,28]], }; export function folderIconFile(fill, edge, open=false) { - const rgb=hex=>hex.slice(1).match(/../g).map(x=>parseInt(x,16)); + const rgb=hexRgb; const colors=[rgb(edge),rgb(fill)]; const sizes=[16,20,24,32,40,48,64,96,128,256]; const images=sizes.map(size=>{ diff --git a/scripts/lib/windows-markdown.mjs b/scripts/lib/windows-markdown.mjs index 4d1614a60..6bfd2b402 100644 --- a/scripts/lib/windows-markdown.mjs +++ b/scripts/lib/windows-markdown.mjs @@ -1,3 +1,4 @@ +import { rgb as hexRgb } from "./color.mjs"; import {renderWindowsTemplate} from "./windows-template.mjs"; /* PowerToys owns Markdown parsing, document bytes and WebView restrictions. This renderer supplies token-derived CSS and reversible backing at pinned public boundaries. */ @@ -41,7 +42,7 @@ export function windowsMarkdownArtifacts(host,resolved){ const css=render(readFileSync(path.join(repoRoot,'ports/windows/src/markdown-theme.css.in'),'utf8'),roles).replace(/\r?\n/g,''); if(/[^\x20-\x7e]/.test(css))throw Error('Markdown CSS must be ASCII for the same-length boundary'); if(md.headers.some(pin=>css.length>pin.styleLength))throw Error('Markdown CSS exceeds admitted extent'); - const rgb=role=>{const color=roles[role];if(!/^#[a-f0-9]{6}$/i.test(color))throw Error('Loading surface requires an opaque semantic color');return [1,3,5].map(i=>parseInt(color.slice(i,i+2),16)).join(',');}; + const rgb=role=>{const color=roles[role];if(!/^#[a-f0-9]{6}$/i.test(color))throw Error('Loading surface requires an opaque semantic color');return hexRgb(color).join(',');}; const subs={LOADING_BACKGROUND:rgb('CANVAS'),LOADING_FOREGROUND:rgb('PROSE'),VERSION:md.version,HEADER_PINS:md.headers.map(p=>` {${p.length},${p.styleOffset},${p.styleLength},"${p.sha256}"},`).join('\n'), PALETTE_CSS:css,HOST_SHA256:md.hostSha256,CONTROL_SHA256:md.controlSha256,HELPER_SHA256:md.helperSha256, PREVIEW_HOST_SHA256:native.sha256,PREVIEW_EXPLORER_SHA256:native.explorerSha256, diff --git a/scripts/lib/windows-port.mjs b/scripts/lib/windows-port.mjs index 61b4fef40..aafda990a 100644 --- a/scripts/lib/windows-port.mjs +++ b/scripts/lib/windows-port.mjs @@ -1,3 +1,4 @@ +import { rgb as hexRgb } from "./color.mjs"; import {renderWindowsTemplate} from "./windows-template.mjs"; import {folderIconFile,folderGeometry} from './windows-folder-icon.mjs'; /* Windows native artifacts. Host definitions own selectors; tokens own colors. @@ -6,7 +7,7 @@ import { toCss } from './tokens.mjs'; import {windowsMarkdownArtifacts} from './windows-markdown.mjs'; import { stableJson, repoRoot } from './fs.mjs'; import { readFileSync } from 'node:fs'; -import { createHash } from 'node:crypto'; +import { sha256Hex } from './host-install/files.mjs'; import { buildSync } from 'esbuild'; import path from 'node:path'; @@ -44,8 +45,8 @@ export function windowsWebContentStyles(items,val) { return {target:t.target,styles}; }); } -const rgb = hex => [1,3,5].map(i => Number.parseInt(hex.slice(i,i+2),16)); -export const wallpaperBmp = hex => { +const rgb=hexRgb; +const wallpaperBmp = hex => { const b=Buffer.alloc(58); b.write('BM'); b.writeUInt32LE(58,2); b.writeUInt32LE(54,10); b.writeUInt32LE(40,14); b.writeInt32LE(1,18); b.writeInt32LE(1,22); b.writeUInt16LE(1,26); b.writeUInt16LE(24,28); b.writeUInt32LE(4,34); const [r,g,blue]=rgb(hex); b[54]=blue;b[55]=g;b[56]=r;return b; @@ -102,7 +103,7 @@ function cursorImage(name,size,foreground,outline) { const dib=Buffer.alloc(40);dib.writeUInt32LE(40);dib.writeInt32LE(size,4);dib.writeInt32LE(size*2,8);dib.writeUInt16LE(1,12);dib.writeUInt16LE(32,14);dib.writeUInt32LE(rgba.length+mask.length,20); return {data:Buffer.concat([dib,rgba,mask]),hot:hot.map(v=>Math.round((inset+v*artworkScale)*scale))}; } -export function cursorFile(name,foreground,outline){ +function cursorFile(name,foreground,outline){ const sizes=[32,48,64,96],head=Buffer.alloc(6+16*sizes.length);head.writeUInt16LE(2,2);head.writeUInt16LE(sizes.length,4);let offset=head.length;const data=[]; sizes.forEach((size,i)=>{const img=cursorImage(name,size,foreground,outline),n=6+16*i;head[n]=size;head[n+1]=size;head.writeUInt16LE(img.hot[0],n+4);head.writeUInt16LE(img.hot[1],n+6);head.writeUInt32LE(img.data.length,n+8);head.writeUInt32LE(offset,n+12);offset+=img.data.length;data.push(img.data);});return Buffer.concat([head,...data]); } @@ -174,7 +175,7 @@ export function windowsArtifacts({manifest,host,resolved}){ const nativeSource=renderWindowsTemplate(readFileSync(path.join(repoRoot,'ports/windows/src/j3w1-explorer-native.wh.cpp.in'),'utf8'),substitutions,'native source'); artifacts.push({path:`dist/${id}.wh.cpp`,text:nativeSource}); json(`${id}.json`,nativeSettings); - const bundledMods=[{id,version:native.version,path:`dist/${id}.wh.cpp`,sha256:createHash('sha256').update(nativeSource).digest('hex')}]; + const bundledMods=[{id,version:native.version,path:`dist/${id}.wh.cpp`,sha256:sha256Hex(nativeSource)}]; const preview=host.monacoPreview,previewId='j3w1-powertoys-preview'; if(!/^\d+\.\d+\.\d+\.\d+$/.test(preview.hostVersion)||! /^[a-f0-9]{64}$/.test(preview.templateSha256))throw Error('Preview requires exact host and template identities'); const previewParts=preview.hostVersion.split('.'); @@ -192,7 +193,7 @@ export function windowsArtifacts({manifest,host,resolved}){ artifacts.push({path:`dist/${previewId}.wh.cpp`,text:previewSource}); // Windhawk stores checkbox settings as integer strings (1/0). json(`${previewId}.json`,{enabled:1}); - bundledMods.push({id:previewId,version:preview.version,path:`dist/${previewId}.wh.cpp`,sha256:createHash('sha256').update(previewSource).digest('hex')}); + bundledMods.push({id:previewId,version:preview.version,path:`dist/${previewId}.wh.cpp`,sha256:sha256Hex(previewSource)}); const calculator=host.calculator,calculatorId='j3w1-calculator'; const calculatorPackageVersion=calculator.packageFullName.split('_')[1]; if(calculator.buttonStyleTarget!== @@ -214,14 +215,14 @@ export function windowsArtifacts({manifest,host,resolved}){ const calculatorSource=renderWindowsTemplate(readFileSync(path.join(repoRoot,'ports/windows/src/j3w1-calculator.wh.cpp.in'),'utf8'),calculatorSubs,'Calculator source'); artifacts.push({path:`dist/${calculatorId}.wh.cpp`,text:calculatorSource}); json(`${calculatorId}.json`,{enabled:1}); - bundledMods.push({id:calculatorId,version:calculator.version,path:`dist/${calculatorId}.wh.cpp`,sha256:createHash('sha256').update(calculatorSource).digest('hex')}); + bundledMods.push({id:calculatorId,version:calculator.version,path:`dist/${calculatorId}.wh.cpp`,sha256:sha256Hex(calculatorSource)}); const notepad=host.notepadNative,notepadId='j3w1-notepad-native'; if(!/^Microsoft\.WindowsNotepad_\d+\.\d+\.\d+\.\d+_x64__8wekyb3d8bbwe$/.test(notepad.packageFullName)||! /^[a-f0-9]{64}$/.test(notepad.editorSha256))throw Error('Notepad editor requires exact package and binary identities'); const notepadSubs={VERSION:notepad.version,PACKAGE_FULL_NAME:notepad.packageFullName,EDITOR_SHA256:notepad.editorSha256}; for(const [key,role] of Object.entries(notepad.roles))notepadSubs[key]='RGB('+rgb(val(role)).join(',')+')'; const notepadSource=renderWindowsTemplate(readFileSync(path.join(repoRoot,'ports/windows/src/j3w1-notepad-native.wh.cpp.in'),'utf8'),notepadSubs,'Notepad source'); artifacts.push({path:'dist/'+notepadId+'.wh.cpp',text:notepadSource});json(notepadId+'.json',{enabled:1}); - bundledMods.push({id:notepadId,version:notepad.version,path:'dist/'+notepadId+'.wh.cpp',sha256:createHash('sha256').update(notepadSource).digest('hex')}); + bundledMods.push({id:notepadId,version:notepad.version,path:'dist/'+notepadId+'.wh.cpp',sha256:sha256Hex(notepadSource)}); for(const [chrome,chromeId,label,exe,packagePattern,nativeClass,rootClasses,clsid] of [ [host.notepadChrome,'j3w1-notepad-chrome','Notepad','Notepad.exe',/^Microsoft\.WindowsNotepad_\d+\.\d+\.\d+\.\d+_x64__8wekyb3d8bbwe$/,'Notepad',['NotepadXamlUI.MainMenuBar','NotepadXamlUI.StatusBar','NotepadXamlUI.TabsBar','NotepadXamlUI.NotepadSettingsPage'],'0x9f12b9c4,0x7b9d,0x489f,{0x8e,0x31,0x4a,0x81,0x10,0x32,0x6b,0xc4}'], @@ -284,12 +285,12 @@ export function windowsArtifacts({manifest,host,resolved}){ if(legacy)chromeSource=chromeSource.replaceAll('Microsoft::UI::Xaml','Windows::UI::Xaml').replaceAll('L"Microsoft.UI.Xaml.','L"Windows.UI.Xaml.'); if(legacy)chromeSource=chromeSource.replace('type==L"Windows.UI.Xaml.Controls.SplitButton"||type==L"Windows.UI.Xaml.Controls.SplitButton"','type==L"Microsoft.UI.Xaml.Controls.SplitButton"||type==L"Windows.UI.Xaml.Controls.SplitButton"'); artifacts.push({path:'dist/'+chromeId+'.wh.cpp',text:chromeSource});json(chromeId+'.json',{enabled:1}); - bundledMods.push({id:chromeId,version:chrome.version,path:'dist/'+chromeId+'.wh.cpp',sha256:createHash('sha256').update(chromeSource).digest('hex')}); + bundledMods.push({id:chromeId,version:chrome.version,path:'dist/'+chromeId+'.wh.cpp',sha256:sha256Hex(chromeSource)}); } const markdown=windowsMarkdownArtifacts(host,resolved); artifacts.push({path:`dist/${markdown.id}.wh.cpp`,text:markdown.source},{path:'dist/markdown-theme.css',text:markdown.css}); json(`${markdown.id}.json`,{enabled:1}); - bundledMods.push({id:markdown.id,version:markdown.version,path:`dist/${markdown.id}.wh.cpp`,sha256:createHash('sha256').update(markdown.source).digest('hex')}); + bundledMods.push({id:markdown.id,version:markdown.version,path:`dist/${markdown.id}.wh.cpp`,sha256:sha256Hex(markdown.source)}); const startup=host.settingsStartup; const dependencies=JSON.parse(readFileSync(path.join(repoRoot,'ports/windows/dependencies.json'),'utf8')); if(startup.sourceSha256!==dependencies.mods.find(m=>m.id==='windows-11-settings-styler')?.sha256 @@ -325,8 +326,8 @@ export function windowsArtifacts({manifest,host,resolved}){ artifacts.push({path:'dist/j3w1.theme',text:`; Generated j3w1 ${manifest.version}\n[Theme]\nDisplayName=j3w1\n[Control Panel\\Colors]\nBackground=${rgb(val('color.surface.desktop')).join(' ')}\n[Control Panel\\Desktop]\nWallpaper=${themeAssets}\\j3w1-wallpaper.bmp\nTileWallpaper=0\nWallpaperStyle=10\n[Control Panel\\Cursors]\n${themeCursors}\nDefaultValue=j3w1\n[VisualStyles]\nPath=%ResourceDir%\\Themes\\Aero\\Aero.msstyles\nColorStyle=NormalColor\nSize=NormalSize\nColorizationColor=0XFF${val('color.border.active').slice(1).toUpperCase()}\nAutoColorization=0\nSystemMode=Dark\nAppMode=Dark\n[MasterThemeSelector]\nMTSM=DABJDKT\n`}); const runtime=buildSync({entryPoints:[path.join(repoRoot,'ports/windows/src/runtime.mjs')],bundle:true,mainFields:['module','main'],platform:'node',target:'node24',format:'cjs',write:false,legalComments:'eof'}).outputFiles[0].text; artifacts.push({path:'dist/runtime.cjs',text:runtime}); - const files=artifacts.map(a=>({path:a.path,sha256:createHash('sha256').update(a.bytes??a.text).digest('hex')})); - for(const name of ['install.ps1','adapter.ps1','lockscreen.ps1','dependencies.json','host.json'])files.push({path:name,sha256:createHash('sha256').update(readFileSync(path.join(repoRoot,'ports/windows',name))).digest('hex')}); + const files=artifacts.map(a=>({path:a.path,sha256:sha256Hex(a.bytes??a.text)})); + for(const name of ['install.ps1','adapter.ps1','lockscreen.ps1','dependencies.json','host.json'])files.push({path:name,sha256:sha256Hex(readFileSync(path.join(repoRoot,'ports/windows',name)))}); json('install-manifest.json',{schemaVersion:1,version:manifest.version,files}); return artifacts; } diff --git a/scripts/phase6-visual-review.mjs b/scripts/phase6-visual-review.mjs index ff2e8afda..9e1c5597d 100644 --- a/scripts/phase6-visual-review.mjs +++ b/scripts/phase6-visual-review.mjs @@ -1,3 +1,5 @@ +import { escapeHtml as esc } from "./lib/markup.mjs"; +import { cssVar } from "./lib/tokens.mjs"; import { promises as fs } from "node:fs"; import path from "node:path"; import { createServer } from "node:http"; @@ -13,7 +15,6 @@ import { requestPath, send, sendFile } from "./tooling/static-server.mjs"; const root = path.join(repoRoot, ".cache/phase6a"); const output = path.join(root, "site"); -const esc = s => String(s).replaceAll("&", "&").replaceAll("<", "<").replaceAll('"', """); const write = async (file, data) => { const target = path.join(output, file); await fs.mkdir(path.dirname(target), { recursive: true }); @@ -47,7 +48,7 @@ export const buildReview = async () => { await write(`review/${c.id}/tokens.css`, buildCss({ profiles: new Map([[c.id, c.resolved]]), defaultId: c.id }) + buildDensityCss(c.resolved)); const data = { id: c.id, name: c.report.name, summary: c.report.summary, specimenDigest, baselineDigest: baseline.baselineDigest, focusHex: c.resolved.get("color.interaction.focus.ring").resolved.hex }; - const foundations = ladderGroups.map(([name, prefix]) => `

${name} ladder

${[...c.resolved].filter(([role]) => role.startsWith(prefix)).map(([role, token]) => `
${role}${token.resolved.hex}
`).join("")}
`).join(""); + const foundations = ladderGroups.map(([name, prefix]) => `

${name} ladder

${[...c.resolved].filter(([role]) => role.startsWith(prefix)).map(([role, token]) => `
${role}${token.resolved.hex}
`).join("")}
`).join(""); const metadata = ``; await write(`review/${c.id}/index.html`, decorateHexHtml(`${header(c, c.report.name)}${nav}

PHASE 6A / LOCAL VISUAL SELECTION

${esc(c.report.name)}

${esc(c.report.summary)}

Temporary candidate. Shared Vue preview, not the published component package. Foundations · Full existing state board

Loading the interactive Vue composition…

${metadata}`)); await write(`review/${c.id}/components/index.html`, decorateHexHtml(`${header(c, "State board")}${nav}

${esc(c.report.name)} / state board

All ${baseline.components.length} existing specifications, every declared variant and state. Forced states are visual references, not proof of implemented behavior. Deferred inventory is not claimed as productized.

${gallery}
`)); diff --git a/scripts/tooling/git.mjs b/scripts/tooling/git.mjs index 5df7d894d..79e39cdce 100644 --- a/scripts/tooling/git.mjs +++ b/scripts/tooling/git.mjs @@ -7,7 +7,9 @@ import { repoRoot } from "../lib/fs.mjs"; /* A full 40-hex commit, the only form the exports and kits accept as a pin. */ export const REVISION = /^[a-f0-9]{40}$/; -export const git = (args, options = {}) => execFileSync("git", args, { cwd: repoRoot, encoding: "utf8", ...options }).trim(); +export const gitBytes = (args, options = {}) => execFileSync("git", args, { cwd: repoRoot, ...options }); + +export const git = (args, options = {}) => gitBytes(args, { encoding: "utf8", ...options }).trim(); /* null instead of a throw, for callers that work outside a checkout. */ export const tryGit = (args, options) => { diff --git a/site/integrations/rehype-spec.mjs b/site/integrations/rehype-spec.mjs index 787979592..279ec8c90 100644 --- a/site/integrations/rehype-spec.mjs +++ b/site/integrations/rehype-spec.mjs @@ -1,3 +1,4 @@ +import { decisionHeadingPattern } from "../../scripts/lib/spec.mjs"; /* Rehype plugin for the spec Markdown: - shifts headings so the page outline stays h1 > h2 (doc or family) > h3 (component) > h4 (sections): documents shift by one, components by two; @@ -43,7 +44,7 @@ export default function rehypeSpec() { node.properties ??= {}; const own = node.properties.id ?? slug(textOf(node)); node.properties.id = `${prefix}${own}`; - const decision = stemOf(file) === "decisions" && textOf(node).match(/^(D-\d{3})\b/); + const decision = stemOf(file) === "decisions" && `## ${textOf(node)}`.match(decisionHeadingPattern); if (decision) node.properties.id = anchorFor.decision(decision[1]); } if (node.type === "comment" && /@compact:(start|end)/.test(node.value)) node.value = ""; diff --git a/site/src/lib/base.ts b/site/src/lib/base.ts index c667e184c..74f3064a5 100644 --- a/site/src/lib/base.ts +++ b/site/src/lib/base.ts @@ -5,5 +5,3 @@ export const BASE = import.meta.env.BASE_URL.replace(/\/?$/, "/"); export const withBase = (path: string): string => `${BASE}${path.replace(/^\//, "")}`; - -export const anchor = (id: string): string => `#${id}`; diff --git a/site/src/lib/theme.ts b/site/src/lib/theme.ts index cace35052..02172f8e5 100644 --- a/site/src/lib/theme.ts +++ b/site/src/lib/theme.ts @@ -1,6 +1,7 @@ /* Typed access to the manifest and the committed exports. The page renders exports, not raw tokens, so what people read is what agents fetch. */ +import { hexOf as tokenHex } from "../../../scripts/lib/color.mjs"; import manifest from "../../../theme.json"; import resolved from "../../../exports/tokens.resolved.json"; import contrast from "../../../exports/contrast.json"; @@ -36,14 +37,8 @@ export const anchors = anchorFor; export const tokensInGroup = (prefix: string): [string, ResolvedToken][] => Object.entries(defaultTokens).filter(([path]) => path.startsWith(prefix)); -export const cssVar = (path: string): string => `--${path.replaceAll(".", "-")}`; - -export const isColor = (token: ResolvedToken): boolean => token.type === "color"; +export { cssVar } from "../../../scripts/lib/tokens.mjs"; export const hexOf = (path: string): string | null => { - const token = defaultTokens[path]; - return token && token.type === "color" ? (token.value as { hex: string }).hex : null; + return tokenHex(defaultTokens[path]); }; - -export const valuePerProfile = (path: string): { profile: string; css: string; status: string }[] => - Object.entries(profiles).map(([id, p]) => ({ profile: id, css: p.tokens[path]?.css ?? "—", status: p.status })); diff --git a/tests/chatgpt-port.test.js b/tests/chatgpt-port.test.js index 99c2dd188..f3d47fcaf 100644 --- a/tests/chatgpt-port.test.js +++ b/tests/chatgpt-port.test.js @@ -1,8 +1,9 @@ +import { scratchDirSync } from "./helpers/scratch.mjs"; +import { defaultTokens } from "./helpers/tokens.mjs"; import { test } from "node:test"; import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; -import { mkdtempSync, mkdirSync, writeFileSync } from "node:fs"; -import os from "node:os"; +import { mkdirSync, writeFileSync } from "node:fs"; import path from "node:path"; import { assertSampleFormat, buildChatgptPresets, chatgptPortProblems, chatgptRoles, readSamples } from "../scripts/lib/chatgpt-port.mjs"; import { parseCodexTheme, chatgptPresetsSchema, codexThemeSampleSchema, CODEX_THEME_PREFIX } from "../schemas/chatgpt.mjs"; @@ -10,11 +11,11 @@ import { parseCodexTheme, chatgptPresetsSchema, codexThemeSampleSchema, CODEX_TH const source = JSON.parse(readFileSync("ports/chatgpt/src/presets.json", "utf8")); const built = JSON.parse(readFileSync("ports/chatgpt/dist/presets.json", "utf8")); const manifest = JSON.parse(readFileSync("theme.json", "utf8")); -const tokens = JSON.parse(readFileSync("exports/tokens.resolved.json", "utf8")).profiles.default.tokens; +const tokens = await defaultTokens(); const byId = Object.fromEntries(built.presets.map((p) => [p.id, p])); const setting = (id, name) => byId[id].settings.find((r) => r.setting === name); -test("Signature: rose text.bright on true black, accent focus ring, contrast 46", () => { +test("Signature: rose text.bright on true black, accent focus ring, contrast 46", (t) => { assert.equal(setting("signature", "Foreground").source, "color.text.bright"); assert.equal(setting("signature", "Foreground").value, tokens["color.text.bright"].value.hex); assert.equal(setting("signature", "Background").value, tokens["color.surface.canvas"].value.hex); @@ -23,7 +24,7 @@ test("Signature: rose text.bright on true black, accent focus ring, contrast 46" assert.equal(byId.signature.recommended, true); }); -test("Reading: the same with text.default and contrast 52", () => { +test("Reading: the same with text.default and contrast 52", (t) => { assert.equal(setting("reading", "Foreground").source, "color.text.default"); assert.equal(setting("reading", "Foreground").value, tokens["color.text.default"].value.hex); assert.equal(setting("reading", "Contrast").value, "52"); @@ -32,7 +33,7 @@ test("Reading: the same with text.default and contrast 52", () => { } }); -test("host calibration is exact and marked as calibration, not a theme role", () => { +test("host calibration is exact and marked as calibration, not a theme role", (t) => { for (const id of ["signature", "reading"]) { for (const [name, value] of [["Mode", "Dark"], ["Theme", "ChatGPT"], ["Reduce motion", "System"], ["Separate light and dark", "Off"], ["Diff markers", "+/-"]]) { assert.deepEqual(setting(id, name), { setting: name, value, source: "calibration" }); @@ -42,7 +43,7 @@ test("host calibration is exact and marked as calibration, not a theme role", () } }); -test("the presets are generated from the source, deterministically", () => { +test("the presets are generated from the source, deterministically", (t) => { const exported = Object.fromEntries(Object.entries(tokens)); const again = buildChatgptPresets(source, exported, manifest); assert.deepEqual(again, built); @@ -50,7 +51,7 @@ test("the presets are generated from the source, deterministically", () => { assert.equal(setting("signature", "Opaque windows").source, "calibration", "the table sets what the import string sets"); }); -test("the emitted strings match the strict schema exactly: a changed, missing or extra field is refused", () => { +test("the emitted strings match the strict schema exactly: a changed, missing or extra field is refused", (t) => { const good = byId.signature.importString; assert.ok(good.startsWith(CODEX_THEME_PREFIX)); const payload = parseCodexTheme(good); @@ -63,7 +64,7 @@ test("the emitted strings match the strict schema exactly: a changed, missing or assert.throws(() => chatgptPresetsSchema.parse({ ...source, extra: true })); }); -test("the README shows exactly the generated tables and strings", () => { +test("the README shows exactly the generated tables and strings", (t) => { const readme = readFileSync("ports/chatgpt/README.md", "utf8"); for (const p of built.presets) { assert.ok(readme.includes(p.importString), `${p.id} import string`); @@ -73,54 +74,54 @@ test("the README shows exactly the generated tables and strings", () => { assert.match(readme, /rollout/); }); -const sampleDir = (text) => { - const root = mkdtempSync(path.join(os.tmpdir(), "chatgpt-samples-")); +const sampleDir = (t, text) => { + const root = scratchDirSync(t, "chatgpt-samples-"); mkdirSync(path.join(root, "ports/chatgpt/evidence"), { recursive: true }); writeFileSync(path.join(root, "ports/chatgpt/evidence/test-build.codex-theme.txt"), text); return root; }; -test("a recorded ChatGPT export with a different format stops generation; the same format passes", () => { +test("a recorded ChatGPT export with a different format stops generation; the same format passes", (t) => { const exported = Object.fromEntries(Object.entries(tokens)); const same = parseCodexTheme(byId.signature.importString); const sameText = `# build: 1.2026.270\n# date: 2026-09-26\n${CODEX_THEME_PREFIX}${JSON.stringify({ ...same, theme: { ...same.theme, accent: "#E53935" } })}\n`; - const ok = readSamples(sampleDir(sameText)); + const ok = readSamples(sampleDir(t, sameText)); assert.equal(ok.length, 1, "upper-case hex from ChatGPT is accepted in a sample"); assert.doesNotThrow(() => buildChatgptPresets(source, exported, manifest, { samples: ok })); const changed = structuredClone(same); changed.theme.foreground = changed.theme.ink; delete changed.theme.ink; const renamed = `# build: 1.2026.300\n# date: 2026-10-20\n${CODEX_THEME_PREFIX}${JSON.stringify(changed)}\n`; - assert.throws(() => readSamples(sampleDir(renamed)), /test-build\.codex-theme\.txt: ChatGPT 1\.2026\.300 \(2026-10-20\) exports a theme format this port does not emit/); + assert.throws(() => readSamples(sampleDir(t, renamed)), /test-build\.codex-theme\.txt: ChatGPT 1\.2026\.300 \(2026-10-20\) exports a theme format this port does not emit/); assert.throws(() => assertSampleFormat(same, [{ build: "x", date: "2026-10-20", payload: { ...same, extra: 1 } }]), /different theme format/); - assert.throws(() => readSamples(sampleDir(`${CODEX_THEME_PREFIX}${JSON.stringify(same)}\n`)), /needs "# build:"/); + assert.throws(() => readSamples(sampleDir(t, `${CODEX_THEME_PREFIX}${JSON.stringify(same)}\n`)), /needs "# build:"/); assert.ok(codexThemeSampleSchema.safeParse({ ...same, theme: { ...same.theme, accent: "#E53935" } }).success); }); -test("a role of the wrong kind is refused, not emitted as nonsense", () => { +test("a role of the wrong kind is refused, not emitted as nonsense", (t) => { const exported = Object.fromEntries(Object.entries(tokens)); assert.throws(() => buildChatgptPresets({ ...source, shared: { ...source.shared, uiFontSize: "color.text.bright" } }, exported, manifest)); assert.throws(() => buildChatgptPresets({ ...source, shared: { ...source.shared, accent: "font.size.reading" } }, exported, manifest)); }); -test("two settings that share a role both stay mapped", () => { +test("two settings that share a role both stay mapped", (t) => { const shared = { ...source, shared: { ...source.shared, semanticColors: { ...source.shared.semanticColors, skill: source.shared.accent } } }; assert.deepEqual(chatgptRoles(shared)[source.shared.accent], ["Accent", "theme.accent", "theme.semanticColors.skill"]); }); -test("a byte-order mark and a bad date in a sample are handled plainly (review r4b)", () => { +test("a byte-order mark and a bad date in a sample are handled plainly (review r4b)", (t) => { const same = parseCodexTheme(byId.signature.importString); const line = `${CODEX_THEME_PREFIX}${JSON.stringify(same)}`; - assert.equal(readSamples(sampleDir(`\uFEFF# build: b1\n# date: 2026-09-26\n${line}\n`)).length, 1); - assert.throws(() => readSamples(sampleDir(`# build: b1\n# date: 26/09/2026\n${line}\n`)), /yyyy-mm-dd/); + assert.equal(readSamples(sampleDir(t, `\uFEFF# build: b1\n# date: 2026-09-26\n${line}\n`)).length, 1); + assert.throws(() => readSamples(sampleDir(t, `# build: b1\n# date: 26/09/2026\n${line}\n`)), /yyyy-mm-dd/); }); -test("a sample whose code theme id differs from the source stops generation (review r4b)", () => { +test("a sample whose code theme id differs from the source stops generation (review r4b)", (t) => { const same = parseCodexTheme(byId.signature.importString); assert.throws(() => assertSampleFormat(same, [{ build: "b1", date: "2026-09-26", payload: { ...same, codeThemeId: "codex" } }]), /codeThemeId "codex"/); }); -test("the port leaves experimental or names a tested build only with a recorded export per build (review r4b)", () => { +test("the port leaves experimental or names a tested build only with a recorded export per build (review r4b)", (t) => { const port = JSON.parse(readFileSync("ports/chatgpt/port.json", "utf8")); const sample = { build: "1.2026.270", date: "2026-09-26" }; assert.deepEqual(chatgptPortProblems(port, []), []); @@ -129,6 +130,6 @@ test("the port leaves experimental or names a tested build only with a recorded assert.equal(chatgptPortProblems({ ...port, testedVersions: ["1.2026.300"] }, [sample]).length, 1); }); -test("a truncated paste is reported as unreadable, not as a new ChatGPT format (review r6)", () => { - assert.throws(() => readSamples(sampleDir(`# build: b1\n# date: 2026-09-26\n${CODEX_THEME_PREFIX}{"theme":\n`)), /is not a readable codex-theme-v1: string/); +test("a truncated paste is reported as unreadable, not as a new ChatGPT format (review r6)", (t) => { + assert.throws(() => readSamples(sampleDir(t, `# build: b1\n# date: 2026-09-26\n${CODEX_THEME_PREFIX}{"theme":\n`)), /is not a readable codex-theme-v1: string/); }); diff --git a/tests/dependabot-refresh.test.js b/tests/dependabot-refresh.test.js index e2586bdf0..635de9df3 100644 --- a/tests/dependabot-refresh.test.js +++ b/tests/dependabot-refresh.test.js @@ -1,3 +1,4 @@ +import { git as queryGit } from "../scripts/tooling/git.mjs"; import assert from "node:assert/strict"; import { execFileSync } from "node:child_process"; import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync, promises as fs } from "node:fs"; @@ -8,7 +9,7 @@ import { isGenerated, isNpmBump, prPaths, refresh, workspacesOf } from "../scrip import { plan } from "../scripts/ci/select.mjs"; import { scratchDir } from "./helpers/scratch.mjs"; -const git = (dir, ...args) => execFileSync("git", ["-C", dir, ...args], { encoding: "utf8" }).trim(); +const git = (dir, ...args) => queryGit(args, { cwd: dir }); const put = async (dir, file, content) => { await fs.mkdir(path.dirname(path.join(dir, file)), { recursive: true }); await fs.writeFile(path.join(dir, file), content); diff --git a/tests/helpers/json.mjs b/tests/helpers/json.mjs new file mode 100644 index 000000000..385398c89 --- /dev/null +++ b/tests/helpers/json.mjs @@ -0,0 +1,3 @@ +import { readFileSync } from "node:fs"; + +export const readJsonWithBom = file => JSON.parse(readFileSync(file, "utf8").replace(/^\uFEFF/, "")); diff --git a/tests/helpers/powershell.mjs b/tests/helpers/powershell.mjs new file mode 100644 index 000000000..13e61f908 --- /dev/null +++ b/tests/helpers/powershell.mjs @@ -0,0 +1,14 @@ +import { spawnSync } from "node:child_process"; + +export const powershell = process.env.J3W1_PWSH ?? (process.platform === "win32" ? "pwsh.exe" : "pwsh"); + +export const powershellEnvironment = () => { + const env = { ...process.env }; + if (process.platform === "win32") { + for (const key of Object.keys(env)) if (key.toLowerCase() === "psmodulepath") delete env[key]; + } + return env; +}; + +export const powershellAvailable = (engine = powershell, env = process.env) => + spawnSync(engine, ["-NoProfile", "-NonInteractive", "-Command", "$PSVersionTable.PSVersion.ToString()"], { encoding: "utf8", env }).status === 0; diff --git a/tests/helpers/scratch.mjs b/tests/helpers/scratch.mjs index 09e709ed1..fc351a189 100644 --- a/tests/helpers/scratch.mjs +++ b/tests/helpers/scratch.mjs @@ -2,15 +2,28 @@ the directory with mkdtemp under the OS tmpdir and remove exactly that directory afterwards, never a path a caller could point elsewhere. */ +import { mkdtempSync, rmSync } from "node:fs"; import { promises as fs } from "node:fs"; import os from "node:os"; import path from "node:path"; -const remove = async (root) => { +const assertScratch = root => { if (!path.resolve(root).startsWith(path.resolve(os.tmpdir()) + path.sep)) throw new Error(`Scratch directory escaped the tmpdir: ${root}`); +}; +const remove = async root => { + assertScratch(root); await fs.rm(root, { recursive: true, force: true }); }; +export const scratchDirSync = (t, prefix) => { + const root = mkdtempSync(path.join(os.tmpdir(), prefix)); + t.after(() => { + assertScratch(root); + rmSync(root, { recursive: true, force: true }); + }); + return root; +}; + /* Runs `fn(root)` and removes `root` when it settles. */ export const withScratch = async (prefix, fn) => { const root = await fs.mkdtemp(path.join(os.tmpdir(), prefix)); diff --git a/tests/helpers/tokens.mjs b/tests/helpers/tokens.mjs new file mode 100644 index 000000000..61c4ab1b2 --- /dev/null +++ b/tests/helpers/tokens.mjs @@ -0,0 +1,7 @@ +import { readJson } from "../../scripts/lib/fs.mjs"; + +export const loadTokenExports = () => readJson("exports/tokens.resolved.json"); +export const defaultTokens = async () => { + const exported = await loadTokenExports(); + return exported.profiles[exported.defaultProfile].tokens; +}; diff --git a/tests/node-helpers.test.js b/tests/node-helpers.test.js new file mode 100644 index 000000000..fe851c070 --- /dev/null +++ b/tests/node-helpers.test.js @@ -0,0 +1,47 @@ +import assert from "node:assert/strict"; +import test from "node:test"; +import { existsSync, writeFileSync } from "node:fs"; +import path from "node:path"; +import { rgb, rgbToHex, rgbCssToHex, colorValue } from "../scripts/lib/color.mjs"; +import { hexToColor, TokenError } from "../scripts/lib/tokens.mjs"; +import { escapeHtml } from "../scripts/lib/markup.mjs"; +import { keyIndex } from "../packages/ui/src/internal/dom.js"; +import { scratchDirSync, withScratch } from "./helpers/scratch.mjs"; +import { readJsonWithBom } from "./helpers/json.mjs"; + +test("byte colour conversion and analytical precision remain distinct from token authoring", () => { + assert.deepEqual(rgb("#a3676b"), [163, 103, 107]); + assert.equal(rgbToHex(rgb("#a3676b")), "#a3676b"); + assert.equal(rgbCssToHex("rgba(163, 103, 107, 0.5)"), "#a3676b"); + assert.equal(colorValue("#a3676b").components[0], 163 / 255); + assert.equal(hexToColor("#A3676B").components[0], 0.6392); + assert.throws(() => hexToColor("bad"), TokenError); + assert.equal(escapeHtml(`&`), "<a x="'">&"); +}); + +test("keyboard movement wraps menus and toolbars but clamps trees and tables", () => { + const move = (key, index, wrap) => keyIndex({ key, index, length: 3, wrap }); + assert.equal(move("ArrowUp", 0, true), 2); + assert.equal(move("ArrowDown", 2, true), 0); + assert.equal(move("ArrowUp", 0, false), 0); + assert.equal(move("ArrowDown", 2, false), 2); + for (const wrap of [false, true]) { + assert.equal(move("Home", 2, wrap), 0); + assert.equal(move("End", 0, wrap), 2); + assert.equal(move("ArrowDown", 1, wrap), 2); + } + assert.equal(keyIndex({ key: "ArrowLeft", index: 2, length: 3, next: "ArrowLeft", previous: "ArrowRight" }), 0); +}); + +test("scratch cleanup covers rejection and synchronous fixture teardown", async () => { + let root; + await assert.rejects(withScratch("node-helper-", async dir => { root = dir; throw new Error("fixture failed"); }), /fixture failed/); + assert.equal(existsSync(root), false); + let teardown; + const sync = scratchDirSync({ after: callback => { teardown = callback; } }, "node-helper-"); + const file = path.join(sync, "bom.json"); + writeFileSync(file, '\uFEFF{"value":1}'); + assert.deepEqual(readJsonWithBom(file), { value: 1 }); + teardown(); + assert.equal(existsSync(sync), false); +}); diff --git a/tests/node-regressions.test.js b/tests/node-regressions.test.js new file mode 100644 index 000000000..08824a313 --- /dev/null +++ b/tests/node-regressions.test.js @@ -0,0 +1,53 @@ +import assert from "node:assert/strict"; +import test from "node:test"; +import { pathToFileURL } from "node:url"; +import path from "node:path"; +import { readJson, readText, repoRoot } from "../scripts/lib/fs.mjs"; +import { git } from "../scripts/tooling/git.mjs"; +import { uiConsumptionGuide, packageReadmeGenerator } from "../scripts/lib/generators.mjs"; +import { luminanceHex } from "../scripts/lib/contrast.mjs"; + +/* The optional revision reads the same regression inputs from Git, without + creating a second checkout or changing this worktree. */ +const revision = process.env.THEME_REGRESSION_REVISION; +const sourceOf = file => revision ? git(["show", `${revision}:${file}`]) : readText(file); +const moduleOf = async file => { + if (!revision) return import(pathToFileURL(path.join(repoRoot, file))); + const location = pathToFileURL(path.join(repoRoot, file)); + const source = (await sourceOf(file)).replace(/^(import .+? from |export .+? from )(["'])(\.[^"']+)\2;$/gm, + (_, prefix, quote, relative) => `${prefix}${quote}${new URL(relative, location).href}${quote};`); + return import(`data:text/javascript;base64,${Buffer.from(source).toString("base64")}`); +}; + +test("R-a: every install and copy command pins the manifest package version", async () => { + const guide = await sourceOf("docs/ui-consumption.md"); + const manifest = await readJson("theme.json"); + const pins = [...guide.matchAll(/(?:@j3w1\/ui@|j3w1-ui-)(\d+\.\d+\.\d+)/g)].map(match => match[1]); + assert.equal(pins.length, 4); + assert.deepEqual(pins, Array(4).fill(manifest.version)); + const future = uiConsumptionGuide(guide, "99.0.0"); + assert.equal([...future.matchAll(/99\.0\.0/g)].length, 4); + const result = await packageReadmeGenerator.run({ check: true, manifest: { ...manifest, version: "99.0.0" } }); + assert.ok(result.changed.includes("docs/ui-consumption.md"), "check mode detects command drift in the source guide"); + assert.ok(result.changed.includes("packages/ui/README.md")); +}); + +test("R-l: encoded port brightness keeps its bytes and is named separately from WCAG luminance", async () => { + const helpers = await moduleOf("scripts/lib/port-artifacts.mjs"); + assert.equal(typeof helpers.encodedBrightness, "function"); + assert.equal("luminance" in helpers, false, "encoded brightness must not claim WCAG luminance"); + assert.equal(helpers.encodedBrightness("#808080"), 128 / 255); + assert.ok(luminanceHex("#808080") < 0.22); +}); + +test("R-m: the builder and local workflow reserve their single primary for the main submit", async () => { + const { builderMarkup, workflowMarkup } = await moduleOf("packages/ui/src/examples/form-markup.mjs"); + for (const markup of [builderMarkup("regression"), workflowMarkup("regression")]) { + const buttons = [...markup.matchAll(/]*>/g)].map(match => match[0]); + assert.ok(buttons.length > 1); + assert.doesNotMatch(markup, /\bbutton-primary\b/); + const primaries = buttons.filter(button => /class="button"/.test(button)); + assert.equal(primaries.length, 1, "secondary tasks must not introduce additional filled primary buttons"); + assert.match(primaries[0], /type="submit".*data-event="submit"/); + } +}); diff --git a/tests/obsidian-android-install.test.js b/tests/obsidian-android-install.test.js index 5eee0514e..024c25ffc 100644 --- a/tests/obsidian-android-install.test.js +++ b/tests/obsidian-android-install.test.js @@ -1,3 +1,4 @@ +import { sha256Hex } from "../scripts/lib/host-install/files.mjs"; /* The Android installer, ports/obsidian/install-android.sh, run for real against scratch vaults. A stub curl serves fixture files (the committed dist artifacts unless a case changes them), so nothing reaches the @@ -8,13 +9,11 @@ import assert from "node:assert/strict"; import { spawnSync } from "node:child_process"; -import { createHash } from "node:crypto"; import { accessSync, constants, promises as fs } from "node:fs"; -import os from "node:os"; import path from "node:path"; import test from "node:test"; import { readText, repoRoot } from "../scripts/lib/fs.mjs"; -import { scratchDir } from "./helpers/scratch.mjs"; +import { withScratch, scratchDir } from "./helpers/scratch.mjs"; const SCRIPT = path.join(repoRoot, "ports/obsidian/install-android.sh"); const BASE = "https://j3w1.github.io/theme/ports/obsidian/"; @@ -42,15 +41,10 @@ const SHELLS = [ ash runs its own applets instead, so there those cases cannot inject a fault; they are skipped with that reason rather than passed. */ const STUB_FREE = "this shell runs its own mv/rm applets, so PATH fault stubs cannot reach it"; -const interposes = async (shell) => { - const dir = await fs.mkdtemp(path.join(os.tmpdir(), "j3w1-probe-")); - try { +const interposes = shell => withScratch("j3w1-probe-", async dir => { await fs.writeFile(path.join(dir, "mv"), "#!/bin/sh\nexit 7\n", { mode: 0o755 }); return spawnSync(shell.command, [...shell.args, "-c", "mv a b"], { cwd: dir, env: { PATH: dir } }).status === 7; - } finally { - await fs.rm(dir, { recursive: true, force: true }); - } -}; +}); for (const shell of SHELLS) shell.interposes = shell.command ? await interposes(shell) : false; const CURL = `#!/bin/sh @@ -93,7 +87,7 @@ for arg; do case $arg in */.j3w1-backup-*) exit 1 ;; esac; done exec "$REAL_RM" "$@" `; -const sha = (bytes) => createHash("sha256").update(bytes).digest("hex"); +const sha = (bytes) => sha256Hex(bytes); const snapshot = async (dir) => { const out = {}; const walk = async (rel) => { diff --git a/tests/obsidian-cascade.test.js b/tests/obsidian-cascade.test.js index 301f2f7db..c66ad4c00 100644 --- a/tests/obsidian-cascade.test.js +++ b/tests/obsidian-cascade.test.js @@ -1,5 +1,6 @@ /* Source-derived structural checks on synthetic ancestry/state fixtures. No running Obsidian, device, browser or manual accessibility pass is implied. */ +import { colorValue } from "../scripts/lib/color.mjs"; import assert from "node:assert/strict"; import test from "node:test"; import postcss from "postcss"; @@ -17,7 +18,7 @@ const role = name => toCss(resolved.get(name).type, resolved.get(name).resolved) const color = hex => { if (hex === "rgb(0 0 0 / 0%)") return { colorSpace: "srgb", components: [0, 0, 0], alpha: 0, hex: "#000000" }; assert.match(hex, /^#[0-9a-f]{6}$/); - return { colorSpace: "srgb", components: [1, 3, 5].map(i => parseInt(hex.slice(i, i + 2), 16) / 255), alpha: 1, hex }; + return colorValue(hex); }; const pair = (fg, bg, min = 4.5) => evaluatePair({ fg: color(fg), bg: color(bg), surface: color(role("color.surface.overlay")), min }); const nativeCss = version => { diff --git a/tests/port-artifacts.test.js b/tests/port-artifacts.test.js index 7f47dc5de..8ab5cb3d9 100644 --- a/tests/port-artifacts.test.js +++ b/tests/port-artifacts.test.js @@ -13,7 +13,7 @@ import test from "node:test"; import { parse } from "yaml"; import { readJson, readText } from "../scripts/lib/fs.mjs"; import { validatePorts } from "../scripts/lib/validators.mjs"; -import { assertHostMapping, GHOSTTY_KEYS, hostEntries, PORT_EMITTERS, WARP_YAML_KEYS, luminance } from "../scripts/lib/port-artifacts.mjs"; +import { assertHostMapping, GHOSTTY_KEYS, hostEntries, PORT_EMITTERS, WARP_YAML_KEYS, encodedBrightness } from "../scripts/lib/port-artifacts.mjs"; import { parsePlist } from "../scripts/lib/host-install/plist.mjs"; import { downloadsTable } from "../scripts/lib/exports.mjs"; import { PORT_FORMATS } from "../schemas/port.mjs"; @@ -119,7 +119,7 @@ for (const entry of ports.filter(({ port }) => !["obsidian-theme", "windows-them // Orca's Import from YAML: hex colours, background + foreground + an ANSI slot, dark below 0.55. for (const key of WARP_YAML_KEYS) if (at(key)) assert.match(at(key), /^#[0-9a-f]{6}$/); assert.equal(WARP_YAML_KEYS.filter((key) => key.startsWith("terminal_colors.")).map(at).filter(Boolean).length, 16); - assert.ok(luminance(theme.background) < 0.55); + assert.ok(encodedBrightness(theme.background) < 0.55); } else { const got = ghostty(text); assert.deepEqual([...got.keys()].sort(), [...want.keys()].sort()); diff --git a/tests/port-preservation.test.js b/tests/port-preservation.test.js index cac533ba3..d8bceb539 100644 --- a/tests/port-preservation.test.js +++ b/tests/port-preservation.test.js @@ -1,7 +1,7 @@ +import { sha256Hex } from "../scripts/lib/host-install/files.mjs"; /* Same-input renderer regression. The source prepares 3.1.0 separately; these calls retain the 3.0.0 input version to isolate the envelope refactor. */ import assert from "node:assert/strict"; -import { createHash } from "node:crypto"; import test from "node:test"; import { readJson, exists } from "../scripts/lib/fs.mjs"; import { loadResolvedProfile, toResolvedExport } from "../scripts/lib/tokens.mjs"; @@ -28,5 +28,5 @@ for (const fixture of baseline.files) test(`${fixture.path}: identical 3.0.0 inp assert.equal(artifacts.length, 1); const bytes = Buffer.from(artifacts[0].text); assert.equal(bytes.length, fixture.bytes); - assert.equal(createHash("sha256").update(bytes).digest("hex"), fixture.sha256); + assert.equal(sha256Hex(bytes), fixture.sha256); }); diff --git a/tests/readable-heritage.test.js b/tests/readable-heritage.test.js index 944d3128b..1fa6b15cd 100644 --- a/tests/readable-heritage.test.js +++ b/tests/readable-heritage.test.js @@ -1,26 +1,19 @@ import test from "node:test"; import assert from "node:assert/strict"; -import { readFile } from "node:fs/promises"; +import { loadTokenExports } from "./helpers/tokens.mjs"; +import { hexOf as tokenHex } from "../scripts/lib/color.mjs"; +import { contrastHex as contrast } from "../scripts/lib/contrast.mjs"; import { HERITAGE_ANSI } from "../schemas/roles.mjs"; /* D-029: the default profile carries the readable heritage sixteen and two lifted syntax reds; heritage-ansi keeps the historical values exactly. */ -const resolved = JSON.parse(await readFile(new URL("../exports/tokens.resolved.json", import.meta.url), "utf8")); +const resolved = await loadTokenExports(); const hexOf = (profile, path) => { const token = resolved.profiles[profile].tokens[path]; assert.ok(token, `${profile}: ${path} exists`); - return token.value.hex; + return tokenHex(token); }; -const luminance = (hex) => { - const [r, g, b] = [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16) / 255).map((c) => (c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4)); - return 0.2126 * r + 0.7152 * g + 0.0722 * b; -}; -const contrast = (a, b) => { - const [hi, lo] = [luminance(a), luminance(b)].sort((x, y) => y - x); - return (hi + 0.05) / (lo + 0.05); -}; - const HERITAGE_SYNTAX = { keyword: "#f73f35", tag: "#f73f35", property: "#e53935", heading: "#e53935", invalid: "#e53935" }; test("heritage-ansi keeps every terminal slot and the lifted syntax reds at their historical values", () => { diff --git a/tests/task-consumption.test.js b/tests/task-consumption.test.js index a7d0a0255..9e58ed1d8 100644 --- a/tests/task-consumption.test.js +++ b/tests/task-consumption.test.js @@ -1,7 +1,7 @@ +import { sha256 } from "../scripts/lib/fs.mjs"; import test from "node:test"; import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; -import { createHash } from "node:crypto"; import { z } from "zod"; import { lockSchema } from "../schemas/lock.mjs"; @@ -20,7 +20,7 @@ test("composed acceptance retains the reviewed candidate and upstream lock ident assert.deepEqual(lock.integration, manifest.request.integration); for (const [file, digest] of Object.entries(lock.exports)) assert.equal(digest, manifest.source.inputs[file], file); for (const [file, digest] of Object.entries(provenance.candidateDigests)) { - assert.equal("sha256-" + createHash("sha256").update(await readFile(directory + file)).digest("base64"), digest, file); + assert.equal(sha256(await readFile(directory + file)), digest, file); } assert.ok(lock.deviations.length > 0, "Actual downstream omissions and ambiguities remain recorded"); }); diff --git a/tests/telegram-port.test.js b/tests/telegram-port.test.js index 13ad43031..b90994280 100644 --- a/tests/telegram-port.test.js +++ b/tests/telegram-port.test.js @@ -1,4 +1,5 @@ // Native format and semantic contracts; these are not real-import evidence. +import { luminanceRgb as luminance } from "../scripts/lib/contrast.mjs"; import assert from "node:assert/strict"; import test from "node:test"; import { readFile } from "node:fs/promises"; @@ -327,7 +328,6 @@ test("wallpaper, solid bubbles, rose messages, chrome emphasis and avatars keep for (const key of [incoming, outgoing]) for (const end of wallpaper) assert.notDeepEqual(rgba(target, key), end, `${target}:${key} differs from the wallpaper`); // Lightness ladder: wallpaper < incoming < outgoing, so both bubbles read // as raised shapes over the whole wallpaper gradient. - const luminance = ([r, g, b]) => [r, g, b].map(v => { v /= 255; return v <= 0.04045 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4; }).reduce((sum, v, i) => sum + v * [0.2126, 0.7152, 0.0722][i], 0); assert.ok(Math.max(...wallpaper.map(luminance)) < luminance(rgba(target, incoming)), `${target}: incoming is lighter than the wallpaper`); assert.ok(luminance(rgba(target, incoming)) < luminance(rgba(target, outgoing)), `${target}: outgoing is lighter than incoming`); } @@ -349,7 +349,6 @@ test("on-fill foregrounds retain contrast, near-white stays restricted and inter assert.equal(effective("desktop", "historyFileThumbRadialFg").role, "color.text.highlight", "the thumbnail radial control inherits the same contrast-critical highlight"); // Near-white by relative luminance, not by literal value, so a token change // cannot silently widen it. Bright rose (text.bright) stays well below. - const luminance = ([r, g, b]) => [r, g, b].map(v => { v /= 255; return v <= 0.04045 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4; }).reduce((sum, v, i) => sum + v * [0.2126, 0.7152, 0.0722][i], 0); // Fills a near-white glyph may sit on, plus the dark media scrim behind // loader icons over photos. const fills = new Set(["color.action.primary.bg", "color.action.primary.hover-bg", "color.action.primary.pressed-bg", "color.interaction.selection.bg", "color.interaction.selection.inactive-bg", "color.interaction.hover.bg-strong", "color.status.danger.fill", "color.interaction.text-selection.bg", "color.surface.backdrop"]); diff --git a/tests/telegram-publish.test.js b/tests/telegram-publish.test.js index 3f21d4f3e..62e255aeb 100644 --- a/tests/telegram-publish.test.js +++ b/tests/telegram-publish.test.js @@ -1,8 +1,8 @@ +import { scratchDir } from "./helpers/scratch.mjs"; import test from "node:test"; import assert from "node:assert/strict"; import fs from "node:fs/promises"; import path from "node:path"; -import os from "node:os"; import { spawnSync } from "node:child_process"; import { parse } from "yaml"; import { converge, digest, run, redactor, stateDirectory, atomicJson, gitAdapter, parseArgs, liveTransport } from "../ports/telegram/publish.mjs"; @@ -64,8 +64,7 @@ const core = (transport, extra = {}) => converge({ transport, artifacts, cloud, const writes = transport => transport.events.filter(e => ["create", "update", "upload"].includes(e[0])); async function fixture(t, { configured = true, transport = mock(), localCloud = cloud } = {}) { - const root = await fs.mkdtemp(path.join(os.tmpdir(), "telegram-publisher-")); - t.after(() => fs.rm(root, { recursive: true, force: true })); + const root = await scratchDir(t, "telegram-publisher-"); const repo = path.join(root, "repo"); const stateRoot = path.join(root, "private"); await fs.mkdir(path.join(repo, "ports/telegram"), { recursive: true }); diff --git a/tests/windows-atomic.test.js b/tests/windows-atomic.test.js index 7da119a95..582fc90e0 100644 --- a/tests/windows-atomic.test.js +++ b/tests/windows-atomic.test.js @@ -1,11 +1,11 @@ +import { scratchDirSync } from "./helpers/scratch.mjs"; import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; -import os from 'node:os'; import path from 'node:path'; import {replaceDurableTemp,writeDurableTemp} from '../scripts/lib/host-install/files.mjs'; test('Windows transient sharing refusal retries atomic replacement with fresh path validation',t=>{ - const folder=fs.mkdtempSync(path.join(os.tmpdir(),'j3w1-atomic-'));t.after(()=>fs.rmSync(folder,{recursive:true,force:true})); + const folder=scratchDirSync(t, 'j3w1-atomic-'); const target=path.join(folder,'journal.json');fs.writeFileSync(target,'before');const temp=writeDurableTemp(target,'after'); let calls=0,validations=0,sleeps=0; replaceDurableTemp(temp,target,{platform:'win32',beforeAttempt:()=>validations++,sleep:()=>sleeps++,rename:(a,b)=>{ @@ -15,7 +15,7 @@ test('Windows transient sharing refusal retries atomic replacement with fresh pa assert.equal(fs.readFileSync(target,'utf8'),'after');assert.equal(validations,3);assert.equal(sleeps,2);assert.ok(!fs.existsSync(temp)); }); test('permanent replacement and path-policy failures retain the old file and never delete it',t=>{ - const folder=fs.mkdtempSync(path.join(os.tmpdir(),'j3w1-atomic-'));t.after(()=>fs.rmSync(folder,{recursive:true,force:true})); + const folder=scratchDirSync(t, 'j3w1-atomic-'); const target=path.join(folder,'journal.json');fs.writeFileSync(target,'before');const temp=writeDurableTemp(target,'after'); let calls=0; assert.throws(()=>replaceDurableTemp(temp,target,{platform:'win32',attempts:3,sleep:()=>{},rename:()=>{calls++;throw Object.assign(Error('denied'),{code:'EACCES'});}}),/denied/); diff --git a/tests/windows-font.test.js b/tests/windows-font.test.js index a62a941d0..d15313dcb 100644 --- a/tests/windows-font.test.js +++ b/tests/windows-font.test.js @@ -1,15 +1,16 @@ +import { powershell as pwsh, powershellAvailable } from "./helpers/powershell.mjs"; +import { scratchDirSync } from "./helpers/scratch.mjs"; import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; -import os from 'node:os'; import path from 'node:path'; import {spawnSync} from 'node:child_process'; import {repoRoot} from '../scripts/lib/fs.mjs'; -const pwsh=process.env.J3W1_PWSH??(process.platform==='win32'?'pwsh.exe':'pwsh'); -const available=spawnSync(pwsh,['--version']).status===0; + +const available=powershellAvailable(); if(!available&&process.env.CI)test('font dependency tests require PowerShell',()=>assert.fail('PowerShell 7.4+ is required')); test('font dependency resumes an interrupted owned install and rejects failed or corrupt downloads',{skip:available?false:'PowerShell unavailable'},t=>{ - const root=fs.mkdtempSync(path.join(os.tmpdir(),'j3w1-font-test-'));t.after(()=>fs.rmSync(root,{recursive:true,force:true})); + const root=scratchDirSync(t, 'j3w1-font-test-'); const result=spawnSync(pwsh,['-NoProfile','-NonInteractive','-File',path.join(repoRoot,'tests/helpers/windows-font-fixture.ps1'),'-Installer',path.join(repoRoot,'ports/windows/install.ps1'),'-Root',root],{encoding:'utf8',timeout:30000}); assert.equal(result.status,0,result.stdout+'\n'+result.stderr); }); diff --git a/tests/windows-install.test.js b/tests/windows-install.test.js index 6be3d83fe..823fd05da 100644 --- a/tests/windows-install.test.js +++ b/tests/windows-install.test.js @@ -1,21 +1,21 @@ +import { powershell as pwsh, powershellAvailable } from "./helpers/powershell.mjs"; +import { readJsonWithBom as read } from "./helpers/json.mjs"; +import { scratchDirSync } from "./helpers/scratch.mjs"; import assert from 'node:assert/strict'; import test from 'node:test'; import fs from 'node:fs'; -import os from 'node:os'; import path from 'node:path'; import {spawnSync} from 'node:child_process'; import {repoRoot} from '../scripts/lib/fs.mjs'; -const pwsh=process.env.J3W1_PWSH??(process.platform==='win32'?'pwsh.exe':'pwsh'); -const probe=spawnSync(pwsh,['--version'],{encoding:'utf8'}); -const unavailable=probe.status!==0; + +const unavailable=!powershellAvailable(); if(unavailable&&process.env.CI)test('Windows lifecycle tests require PowerShell',()=>assert.fail('PowerShell 7.4+ is required; set J3W1_PWSH')); const installer=path.join(repoRoot,'ports/windows/install.ps1'); -const read=p=>JSON.parse(fs.readFileSync(p,'utf8').replace(/^\uFEFF/,'')); + const write=(p,x)=>{fs.mkdirSync(path.dirname(p),{recursive:true});fs.writeFileSync(p,typeof x==='string'?x:JSON.stringify(x));}; function fixture(t){ - const root=fs.mkdtempSync(path.join(os.tmpdir(),'j3w1-windows-wrapper-')); - t.after(()=>fs.rmSync(root,{recursive:true,force:true})); + const root=scratchDirSync(t, 'j3w1-windows-wrapper-'); const source=path.join(root,'source'),state=path.join(root,'state'); fs.mkdirSync(source);fs.cpSync(path.join(repoRoot,'ports/windows'),path.join(source,'ports/windows'),{recursive:true}); const env={...process.env,LOCALAPPDATA:path.join(root,'local'),APPDATA:path.join(root,'roaming'),HOME:path.join(root,'home'),USERPROFILE:path.join(root,'home'),XDG_CONFIG_HOME:path.join(root,'config'),XDG_CACHE_HOME:path.join(root,'cache'),POWERSHELL_TELEMETRY_OPTOUT:'1',NO_COLOR:'1'}; @@ -147,8 +147,7 @@ test('Prepare retains verified release and returns a plan without mutating theme }); test('native Startup link preserves long explicit guard arguments without writing Startup',{skip:process.platform!=='win32'?'Native Windows shell-link API required':false},t=>{ - const folder=fs.mkdtempSync(path.join(os.tmpdir(),'j3w1 startup link test ')); - t.after(()=>fs.rmSync(folder,{recursive:true,force:true})); + const folder=scratchDirSync(t, 'j3w1 startup link test '); const probe=spawnSync(pwsh,['-NoProfile','-Command','[Diagnostics.Process]::GetCurrentProcess().MainModule.FileName'],{encoding:'utf8',windowsHide:true,timeout:15000}); assert.equal(probe.status,0,probe.stderr); const target=probe.stdout.trim(),working=path.join(folder,'guard source');fs.mkdirSync(working); diff --git a/tests/windows-markdown.test.js b/tests/windows-markdown.test.js index 7ada1330a..23c7ff57b 100644 --- a/tests/windows-markdown.test.js +++ b/tests/windows-markdown.test.js @@ -1,14 +1,15 @@ +import { defaultTokens } from "./helpers/tokens.mjs"; +import { sha256Hex } from "../scripts/lib/host-install/files.mjs"; import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import path from 'node:path'; -import {createHash} from 'node:crypto'; import {repoRoot} from '../scripts/lib/fs.mjs'; import {windowsMarkdownArtifacts} from '../scripts/lib/windows-markdown.mjs'; const port=path.join(repoRoot,'ports/windows'); const host=JSON.parse(fs.readFileSync(path.join(port,'host.json'),'utf8')); -const tokens=JSON.parse(fs.readFileSync(path.join(repoRoot,'exports/tokens.resolved.json'),'utf8')).profiles.default.tokens; +const tokens=await defaultTokens(); const resolved=new Map(Object.entries(tokens).map(([role,t])=>[role,{type:t.type,resolved:t.value}])); test('Markdown renders digits in token and digest placeholders and stays in every admitted CSS extent',()=>{ @@ -29,7 +30,7 @@ test('Markdown source and palette are manifest-pinned and participate in managed const manifest=JSON.parse(fs.readFileSync(path.join(port,'dist/install-manifest.json'),'utf8')); const mod=settings.bundledMods.find(m=>m.id==='j3w1-powertoys-markdown');assert.ok(mod); for(const file of [mod.path,'dist/j3w1-powertoys-markdown.json','dist/markdown-theme.css']){ - const digest=createHash('sha256').update(fs.readFileSync(path.join(port,file))).digest('hex'); + const digest=sha256Hex(fs.readFileSync(path.join(port,file))); assert.equal(manifest.files.find(f=>f.path===file)?.sha256,digest); if(file===mod.path)assert.equal(mod.sha256,digest); } diff --git a/tests/windows-menu.test.js b/tests/windows-menu.test.js index 39cd95dc2..6eb97de2c 100644 --- a/tests/windows-menu.test.js +++ b/tests/windows-menu.test.js @@ -1,3 +1,4 @@ +import { defaultTokens } from "./helpers/tokens.mjs"; import assert from 'node:assert/strict'; import test from 'node:test'; import {readJson} from '../scripts/lib/fs.mjs'; @@ -9,7 +10,7 @@ const ids=['windows-11-taskbar-styler','windows-11-start-menu-styler', test('every supported shell host receives the common menu controls and resource palette',async()=>{ const host=await readJson('ports/windows/host.json'); const mapping=await readJson('ports/windows/mapping.json'); - const tokens=(await readJson('exports/tokens.resolved.json')).profiles.default.tokens; + const tokens=await defaultTokens(); assert.deepEqual(host.stylers.map(x=>x.id),ids); const expectedResources={MenuFlyoutPresenterBackground:'color.surface.raised', MenuFlyoutPresenterBorderBrush:'color.border.overlay',MenuFlyoutSeparatorBackground:'color.border.divider', diff --git a/tests/windows-native.test.js b/tests/windows-native.test.js index 7fba2463e..6794af2dd 100644 --- a/tests/windows-native.test.js +++ b/tests/windows-native.test.js @@ -1,7 +1,7 @@ +import { scratchDirSync } from "./helpers/scratch.mjs"; import assert from 'node:assert/strict'; import test from 'node:test'; import fs from 'node:fs'; -import os from 'node:os'; import path from 'node:path'; import {spawnSync} from 'node:child_process'; import {repoRoot} from '../scripts/lib/fs.mjs'; @@ -30,8 +30,7 @@ function compile(compiler,args){ assert.equal(result.status,0,result.stdout+'\n'+result.stderr); } for(const mod of settings.bundledMods)test(`complete native DLL link: ${mod.id}`,options,t=>{ - const tools=toolchain(),folder=fs.mkdtempSync(path.join(os.tmpdir(),'j3w1-native-link-')); - t.after(()=>fs.rmSync(folder,{recursive:true,force:true})); + const tools=toolchain(),folder=scratchDirSync(t, 'j3w1-native-link-'); const file=path.join(source,mod.path),output=path.join(folder,mod.id+'.dll'); compile(tools.compiler,['-shared','-DWH_MOD',tools.library,file,'-include','windhawk_api.h',...libraries(file),'-o',output]); assert.ok(fs.statSync(output).size>0); @@ -47,8 +46,7 @@ for(const [name,mod] of [ ['markdown-background','j3w1-powertoys-markdown'], ['preview-host','j3w1-powertoys-markdown'], ])test(`native offscreen regression: ${name}`,options,t=>{ - const tools=toolchain(),folder=fs.mkdtempSync(path.join(os.tmpdir(),'j3w1-native-regression-')); - t.after(()=>fs.rmSync(folder,{recursive:true,force:true})); + const tools=toolchain(),folder=scratchDirSync(t, 'j3w1-native-regression-'); const file=path.join(repoRoot,`tests/windows-${name}-native.cpp`),output=path.join(folder,name+'.exe'); // Synthetic test executables run outside Windhawk's ModsRuntime. Link their // C++ runtime statically so they do not depend on Windhawk's DLL search path. @@ -58,8 +56,7 @@ for(const [name,mod] of [ }); for(const [id,define] of [['j3w1-calculator','1'],['j3w1-notepad-native','0']])test('native app worker shutdown: '+id,options,t=>{ - const tools=toolchain(),folder=fs.mkdtempSync(path.join(os.tmpdir(),'j3w1-native-lifetime-')); - t.after(()=>fs.rmSync(folder,{recursive:true,force:true})); + const tools=toolchain(),folder=scratchDirSync(t, 'j3w1-native-lifetime-'); const file=path.join(repoRoot,'tests/windows-app-lifetime-native.cpp'),output=path.join(folder,id+'.exe'); compile(tools.compiler,['-static','-DJ3W1_TEST_CALCULATOR='+define,file,...libraries(path.join(source,'dist/'+id+'.wh.cpp')),'-o',output]); for(const state of ['exit-active','exit-completed','unload','reconfigure']){ @@ -69,8 +66,7 @@ for(const [id,define] of [['j3w1-calculator','1'],['j3w1-notepad-native','0']])t }); test('native Notepad editor preservation',options,t=>{ - const tools=toolchain(),folder=fs.mkdtempSync(path.join(os.tmpdir(),'j3w1-native-editor-')); - t.after(()=>fs.rmSync(folder,{recursive:true,force:true})); + const tools=toolchain(),folder=scratchDirSync(t, 'j3w1-native-editor-'); const output=path.join(folder,'notepad-editor.exe'); compile(tools.compiler,['-static',path.join(repoRoot,'tests/windows-notepad-editor-native.cpp'),...libraries(path.join(source,'dist/j3w1-notepad-native.wh.cpp')),'-ldwrite','-o',output]); const result=spawnSync(output,[],{encoding:'utf8',windowsHide:true,timeout:30000}); @@ -78,8 +74,7 @@ test('native Notepad editor preservation',options,t=>{ }); test('native Calculator clock and ownership restoration',options,t=>{ - const tools=toolchain(),folder=fs.mkdtempSync(path.join(os.tmpdir(),'j3w1-native-calculator-')); - t.after(()=>fs.rmSync(folder,{recursive:true,force:true})); + const tools=toolchain(),folder=scratchDirSync(t, 'j3w1-native-calculator-'); const output=path.join(folder,'calculator-ownership.exe'); compile(tools.compiler,['-static',path.join(repoRoot,'tests/windows-calculator-ownership-native.cpp'),...libraries(path.join(source,'dist/j3w1-calculator.wh.cpp')),'-o',output]); for(const state of ['resource-scaling','background-transition-ownership','hover-state-palette','button-style-dispatch','cached-color-frame','composite-button-scope','clock-lifecycle','animation-frame','resource-ownership']){ @@ -88,8 +83,7 @@ test('native Calculator clock and ownership restoration',options,t=>{ } }); test('native Terminal chrome ownership and worker shutdown',options,t=>{ - const tools=toolchain(),folder=fs.mkdtempSync(path.join(os.tmpdir(),'j3w1-native-terminal-')); - t.after(()=>fs.rmSync(folder,{recursive:true,force:true})); + const tools=toolchain(),folder=scratchDirSync(t, 'j3w1-native-terminal-'); const output=path.join(folder,'terminal-chrome.exe'); compile(tools.compiler,['-static',path.join(repoRoot,'tests/windows-terminal-chrome-native.cpp'),...libraries(path.join(source,'dist/j3w1-terminal-chrome.wh.cpp')),'-o',output]); for(const state of ['resource-scaling','popup-load-lifecycle','background-transition-ownership','hover-state-palette','legacy-boundary','legacy-ownership','legacy-lifecycle']){ @@ -100,8 +94,7 @@ test('native Terminal chrome ownership and worker shutdown',options,t=>{ for(const [id,paint] of [['j3w1-notepad-chrome','0'],['j3w1-paint-chrome','1']])test('native WinUI chrome ownership and worker shutdown: '+id,options,t=>{ - const tools=toolchain(),folder=fs.mkdtempSync(path.join(os.tmpdir(),'j3w1-native-notepad-chrome-')); - t.after(()=>fs.rmSync(folder,{recursive:true,force:true})); + const tools=toolchain(),folder=scratchDirSync(t, 'j3w1-native-notepad-chrome-'); const output=path.join(folder,'notepad-chrome.exe'); compile(tools.compiler,['-static','-DJ3W1_TEST_PAINT='+paint,path.join(repoRoot,'tests/windows-winui-chrome-native.cpp'),...libraries(path.join(source,'dist/'+id+'.wh.cpp')),'-o',output]); for(const state of ['resource-scaling','paint-type-filter','popup-load-lifecycle',...(paint==='1'?['preopen-menu-ownership']:[]),'paint-split-edge-ownership','background-transition-ownership','hover-state-palette','split-parent-bindings','window-backing-ownership','cached-color-frame','composite-button-scope','partial-init','state-ownership','resource-ownership','closed-source-backdrop','retired-control-capacity','retired-control-retry','keytip-ownership','cleanup-retry','public-caption-scope','public-caption-ownership','public-caption-window-ownership',...(paint==='1'?['paint-chrome-admission']:['notepad-chrome-admission']),'backing-admission','captured-native-backdrop',...(paint==='0'?['existing-caption-default-reset']:[]),'native-caption-capture','backdrop-passthrough','discovery-admission','discovery-lifecycle','exit-active','exit-completed','unload','reconfigure']){ @@ -111,8 +104,7 @@ for(const [id,paint] of [['j3w1-notepad-chrome','0'],['j3w1-paint-chrome','1']]) }); test('native Explorer stock folder rendering and cache lifetime',options,t=>{ - const tools=toolchain(),folder=fs.mkdtempSync(path.join(os.tmpdir(),'j3w1-native-folder-')); - t.after(()=>fs.rmSync(folder,{recursive:true,force:true})); + const tools=toolchain(),folder=scratchDirSync(t, 'j3w1-native-folder-'); const output=path.join(folder,'folder.exe'); compile(tools.compiler,['-static',path.join(repoRoot,'tests/windows-folder-glyph-native.cpp'),...libraries(path.join(source,'dist/j3w1-explorer-native.wh.cpp')),'-o',output]); // Real initialization must see the same supported Windows version as Explorer. @@ -122,8 +114,7 @@ test('native Explorer stock folder rendering and cache lifetime',options,t=>{ }); test('native Settings CoreWindow discovery and ownership',options,t=>{ - const tools=toolchain(),folder=fs.mkdtempSync(path.join(os.tmpdir(),'j3w1-native-settings-')); - t.after(()=>fs.rmSync(folder,{recursive:true,force:true})); + const tools=toolchain(),folder=scratchDirSync(t, 'j3w1-native-settings-'); const output=path.join(folder,'settings-startup.exe'); compile(tools.compiler,['-static','-municode',path.join(repoRoot,'tests/windows-settings-startup-native.cpp'),'-lbcrypt','-luser32','-o',output]); const result=spawnSync(output,[],{encoding:'utf8',windowsHide:true,timeout:30000}); diff --git a/tests/windows-port.test.js b/tests/windows-port.test.js index f4d13982d..dd861ce3d 100644 --- a/tests/windows-port.test.js +++ b/tests/windows-port.test.js @@ -1,11 +1,13 @@ +import { readJsonWithBom as read } from "./helpers/json.mjs"; +import { defaultTokens } from "./helpers/tokens.mjs"; +import { scratchDirSync } from "./helpers/scratch.mjs"; +import { sha256Hex } from "../scripts/lib/host-install/files.mjs"; import assert from 'node:assert/strict'; import test from 'node:test'; import {parse} from 'jsonc-parser'; import fs from 'node:fs'; -import os from 'node:os'; import path from 'node:path'; import {spawnSync} from 'node:child_process'; -import {createHash} from 'node:crypto'; import {repoRoot,readJson} from '../scripts/lib/fs.mjs'; import {assertPortArtifacts} from '../scripts/lib/port-artifacts.mjs'; import {CURSOR_NAMES,windowsStyleValue,windowsWebContentStyles,validateWindowsStylerTarget} from '../scripts/lib/windows-port.mjs'; @@ -14,8 +16,8 @@ import {flattenStylerSettings,stylerSettings} from '../ports/windows/src/compati const source=path.join(repoRoot,'ports/windows'); const runtime=path.join(source,'dist/runtime.cjs'); -const sha=b=>createHash('sha256').update(b).digest('hex'); -const read=p=>JSON.parse(fs.readFileSync(p,'utf8').replace(/^\uFEFF/,'')); +const sha=b=>sha256Hex(b); + const readConfig=p=>{const errors=[];const value=parse(fs.readFileSync(p,'utf8').replace(/^\uFEFF/,''),errors,{allowTrailingComma:true});assert.deepEqual(errors,[],`Invalid settings: ${p}`);return value;}; const write=(p,x)=>{fs.mkdirSync(path.dirname(p),{recursive:true});fs.writeFileSync(p,typeof x==='string'?x:JSON.stringify(x,null,2)+'\n');}; @@ -71,8 +73,7 @@ test('Search presentation cannot hide controls, accept scripts or substitute lit assert.throws(()=>windowsWebContentStyles([{target:'.suggestion .details',styles:{},presentation:{'background-color':fill}}],value),/Unsupported Search presentation/); }); function fixture(t) { - const state=fs.mkdtempSync(path.join(os.tmpdir(),'j3w1-windows-test-')); - t.after(()=>fs.rmSync(state,{recursive:true,force:true})); + const state=scratchDirSync(t, 'j3w1-windows-test-'); const terminal=path.join(state,'fixture/terminal/settings.json'); const before='\uFEFF{\n // keep this comment\n "profiles": {"list": [{"guid":"one","commandline":"keep-one","font":{"size":17},"colorScheme":"j3w1zsh"},{"guid":"two","commandline":"keep-two"}]},\n "keybindings": [{"command":"paste","keys":"ctrl+v"}],\n}\n'; write(terminal,before); @@ -102,8 +103,7 @@ test('Windows manifest covers every binary and executable artifact byte exactly' test('Windows native values, Terminal ANSI and styler selectors resolve from canonical roles',async()=>{ const host=await readJson('ports/windows/host.json'); - const resolved=await readJson('exports/tokens.resolved.json'); - const tokens=resolved.profiles.default.tokens; + const tokens=await defaultTokens(); const settings=await readJson('ports/windows/dist/windows-settings.json'); for(const [key,role]of Object.entries(host.roles))assert.equal(settings.values[key],tokens[role].css,key); const terminal=await readJson('ports/windows/dist/terminal-fragment.json'); @@ -116,7 +116,7 @@ test('Windows native values, Terminal ANSI and styler selectors resolve from can test('Settings resource overrides retain shared brushes and stay isolated from other stylers',async()=>{ const host=await readJson('ports/windows/host.json'); - const tokens=(await readJson('exports/tokens.resolved.json')).profiles.default.tokens; + const tokens=await defaultTokens(); const settings=host.stylers.find(m=>m.id==='windows-11-settings-styler'); const expected={SystemControlFocusVisualPrimaryBrush:'color.interaction.focus.ring',SystemControlFocusVisualSecondaryBrush:'color.surface.canvas',FocusStrokeColorOuterBrush:'color.interaction.focus.ring',FocusStrokeColorInnerBrush:'color.surface.canvas',ToolTipBackground:'color.surface.raised',ToolTipForeground:'color.text.default',ToolTipBorderBrush:'color.border.overlay',ToolTipBackgroundBrush:'color.surface.raised',ToolTipForegroundBrush:'color.text.default'}; Object.assign(expected,{ProgressBarBackground:'color.interaction.pressed.bg',ProgressBarForeground:'color.action.primary.bg',ProgressBarBorderBrush:'color.border.control',ToggleSwitchContentForeground:'color.text.default',ToggleSwitchContentForegroundDisabled:'color.text.disabled',ToggleSwitchHeaderForeground:'color.text.default',ToggleSwitchHeaderForegroundDisabled:'color.text.disabled',ToggleSwitchKnobStrokeOn:'color.border.control'}); @@ -214,7 +214,7 @@ test('Calculator uses an exact package and separate primary, disabled and intera test('Explorer marquee settings encode canonical alpha and module compatibility',async()=>{ const settings=await readJson('ports/windows/dist/j3w1-explorer-native.json'); - const tokens=(await readJson('exports/tokens.resolved.json')).profiles.default.tokens; + const tokens=await defaultTokens(); for(const [key,role] of Object.entries((await readJson('ports/windows/host.json')).nativeExplorer)){ if(key==='version')continue; assert.equal(settings[key],windowsStyleValue(key,{type:tokens[role].type,resolved:tokens[role].value})); @@ -229,7 +229,7 @@ test('Explorer marquee settings encode canonical alpha and module compatibility' test('Explorer submenu stays on the hover palette while its child flyout is open',async()=>{ const config=await readJson('ports/windows/dist/windows-11-file-explorer-styler.json'); - const tokens=(await readJson('exports/tokens.resolved.json')).profiles.default.tokens; + const tokens=await defaultTokens(); for(const [target,opened,hover,normal,disabled] of [ ['MenuFlyoutSubItem > Grid#LayoutRoot@CommonStates','SubMenuOpened','PointerOver','Normal','Disabled'], ['AppBarButton > Grid#Root@CommonStates > Border#AppBarButtonInnerBorder','OverflowSubMenuOpened','OverflowPointerOver','OverflowNormal','OverflowDisabled'], @@ -247,7 +247,7 @@ test('Explorer submenu stays on the hover palette while its child flyout is open test('toast actions use the secondary palette across native states without changing content or geometry',async()=>{ const payload=await readJson('ports/windows/dist/windows-11-notification-center-styler.json'); - const tokens=(await readJson('exports/tokens.resolved.json')).profiles.default.tokens; + const tokens=await defaultTokens(); const button=payload.controlStyles.find(t=>t.target==='Button#VerbButton'); const presenter=payload.controlStyles.find(t=>t.target==='Button#VerbButton > ContentPresenter@CommonStates'); const expected=(key,role)=>`${key}=${windowsStyleValue(key,{type:tokens[role].type,resolved:tokens[role].value})}`; @@ -317,7 +317,7 @@ test('malformed settings fail preflight before any theme write',t=>{ }); test('concurrent lifecycle and directory junction targets are refused',t=>{ const f=fixture(t);write(path.join(f.state,'lifecycle.lock'),{pid:process.pid});assert.match(f.run('Apply').stderr,/Another lifecycle/);fs.unlinkSync(path.join(f.state,'lifecycle.lock')); - const outside=fs.mkdtempSync(path.join(os.tmpdir(),'j3w1-outside-'));t.after(()=>fs.rmSync(outside,{recursive:true,force:true}));fs.symlinkSync(outside,path.join(f.state,'assets'),process.platform==='win32'?'junction':'dir');assert.match(f.run('Apply').stderr,/Reparse\/symlink/);assert.deepEqual(fs.readdirSync(outside),[]); + const outside=scratchDirSync(t, 'j3w1-outside-');fs.symlinkSync(outside,path.join(f.state,'assets'),process.platform==='win32'?'junction':'dir');assert.match(f.run('Apply').stderr,/Reparse\/symlink/);assert.deepEqual(fs.readdirSync(outside),[]); }); test('named theme and layout edits preserve later additions and detect duplicate identities',t=>{ @@ -451,7 +451,7 @@ test('recoverable lock-screen image is journaled and restored; later image edits }); test('compact cursors use a black body and canonical red edge with visible bounded hotspots',async()=>{ - const tokens=(await readJson('exports/tokens.resolved.json')).profiles.default.tokens; + const tokens=await defaultTokens(); const black=tokens['color.surface.canvas'].css,red=tokens['color.border.active'].css; const colors=new Set([black,red]); for(const name of CURSOR_NAMES){ @@ -992,7 +992,7 @@ test('Paint preopening menu styles retain native structure and join the existing test('Quick Settings maps its own media, toggle and slider states without changing actions or content',async()=>{ const host=await readJson('ports/windows/host.json'); const mapping=await readJson('ports/windows/mapping.json'); - const tokens=(await readJson('exports/tokens.resolved.json')).profiles.default.tokens; + const tokens=await defaultTokens(); const id='windows-11-notification-center-styler'; const config=host.stylers.find(m=>m.id===id); const payload=await readJson('ports/windows/dist/'+id+'.json'); diff --git a/tests/windows-settings-startup.test.js b/tests/windows-settings-startup.test.js index 468a9afea..bd3b1c77a 100644 --- a/tests/windows-settings-startup.test.js +++ b/tests/windows-settings-startup.test.js @@ -1,13 +1,13 @@ +import { scratchDirSync } from "./helpers/scratch.mjs"; +import { sha256Hex } from "../scripts/lib/host-install/files.mjs"; import assert from 'node:assert/strict'; import test from 'node:test'; -import {createHash} from 'node:crypto'; import fs from 'node:fs'; import path from 'node:path'; -import os from 'node:os'; import {spawnSync} from 'node:child_process'; import {repoRoot} from '../scripts/lib/fs.mjs'; import {settingsStylerSource} from '../ports/windows/src/settings-styler-source.mjs'; -const hash=bytes=>createHash('sha256').update(bytes).digest('hex'); +const hash=bytes=>sha256Hex(bytes); const fixture=Buffer.from('// retained license\n// @compilerOptions -lcomctl32 -lole32\nHWND GetCoreWnd() { return nullptr; }\nPTP_TIMER g_statsTimer;\nBOOL Wh_ModInit() {\n retainedInit();\n}\nvoid Wh_ModUninit() { retainedRestore(GetCoreWnd()); }\n'); const replacement='namespace j3w1Settings { bool Admit(); }\nHWND GetCoreWnd() { return ownedWindow(); }'; test('Settings source adaptation preserves license, initialization and shared restore lookup',()=>{ @@ -43,8 +43,7 @@ test('Generated Settings startup admission pins both executable and XAML binary' }); test('Settings derived source journals both pins, restores the prior adapter, and refuses altered cache',t=>{ - const state=fs.mkdtempSync(path.join(os.tmpdir(),'j3w1-settings-source-')); - t.after(()=>fs.rmSync(state,{recursive:true,force:true})); + const state=scratchDirSync(t, 'j3w1-settings-source-'); const source=path.join(state,'source');fs.cpSync(path.join(repoRoot,'ports/windows'),source,{recursive:true}); const write=(file,value)=>{fs.mkdirSync(path.dirname(file),{recursive:true});fs.writeFileSync(file,typeof value==='string'?value:JSON.stringify(value));}; const read=file=>JSON.parse(fs.readFileSync(file,'utf8')); diff --git a/tests/windows-setup.test.js b/tests/windows-setup.test.js index 69aa423f9..52666879d 100644 --- a/tests/windows-setup.test.js +++ b/tests/windows-setup.test.js @@ -1,21 +1,20 @@ +import { powershell, powershellAvailable, powershellEnvironment } from "./helpers/powershell.mjs"; +import { scratchDirSync } from "./helpers/scratch.mjs"; import assert from 'node:assert/strict'; import test from 'node:test'; import fs from 'node:fs'; -import os from 'node:os'; import path from 'node:path'; import {spawnSync} from 'node:child_process'; import {repoRoot} from '../scripts/lib/fs.mjs'; -const engines=[process.env.J3W1_PWSH||'pwsh',...(process.platform==='win32'?['powershell.exe']:[])]; +const engines=[powershell,...(process.platform==='win32'?['powershell.exe']:[])]; for(const engine of engines){ // A Node child of pwsh inherits its module paths. Let each engine construct // its own defaults so Windows PowerShell 5.1 loads its inbox Utility module. - const engineEnv={...process.env}; - if(process.platform==='win32')for(const key of Object.keys(engineEnv))if(key.toLowerCase()==='psmodulepath')delete engineEnv[key]; - const available=spawnSync(engine,['-NoProfile','-NonInteractive','-Command','$PSVersionTable.PSVersion.ToString()'],{encoding:'utf8',env:engineEnv}).status===0; + const engineEnv=powershellEnvironment(); + const available=powershellAvailable(engine,engineEnv); if(!available&&process.env.CI)test(`Windows setup requires ${engine}`,()=>assert.fail('The selected setup test engine must be available in CI')); for(const scenario of ['identity','process-context','runtime-selection','modes','download','recovery','legacy-recovery','orchestration','cached-setup','child-failure'])test(`Windows setup ${scenario} (${path.basename(engine)})`,{skip:available?false:'PowerShell unavailable'},t=>{ - const root=fs.mkdtempSync(path.join(os.tmpdir(),'j3w1-install-test-')); - t.after(()=>fs.rmSync(root,{recursive:true,force:true})); + const root=scratchDirSync(t, 'j3w1-install-test-'); const r=spawnSync(engine,['-NoProfile','-NonInteractive','-File',path.join(repoRoot,'tests/helpers/windows-setup-fixture.ps1'),'-Setup',path.join(repoRoot,'ports/windows/install.ps1'),'-Root',root,'-Case',scenario],{encoding:'utf8',timeout:60000,env:{...engineEnv,LOCALAPPDATA:root}}); assert.equal(r.status,0,r.stdout+'\n'+r.stderr); assert.ok(r.stdout.includes(`PASS ${scenario}`)); diff --git a/tests/windows-text-popup.test.js b/tests/windows-text-popup.test.js index e48b8113f..52ec17968 100644 --- a/tests/windows-text-popup.test.js +++ b/tests/windows-text-popup.test.js @@ -1,3 +1,4 @@ +import { defaultTokens } from "./helpers/tokens.mjs"; import assert from 'node:assert/strict'; import test from 'node:test'; import {readJson} from '../scripts/lib/fs.mjs'; @@ -7,7 +8,7 @@ test('text-command and suggestion backings are shared once in every shell host a const host=await readJson('ports/windows/host.json'); const mapping=await readJson('ports/windows/mapping.json'); const variants=(await readJson('ports/windows/dist/windows-settings.json')).stylerVariants; - const tokens=(await readJson('exports/tokens.resolved.json')).profiles.default.tokens; + const tokens=await defaultTokens(); const frameKeys=['CommandBarFlyoutBackground','CommandBarFlyoutBorderBrush','CommandBarOverflowPresenterBackground', 'FlyoutPresenterBackground','FlyoutPresenterBorderBrush','AutoSuggestBoxSuggestionsListBackground','AutoSuggestBoxSuggestionsListBorderBrush']; const targets=['Microsoft.UI.Xaml.Controls.Primitives.CommandBarFlyoutCommandBar', @@ -79,7 +80,7 @@ test('detached Settings search backings replace acrylic without changing content const host=await readJson('ports/windows/host.json'); const settings=host.stylers.find(x=>x.id==='windows-11-settings-styler'); const mapping=await readJson('ports/windows/mapping.json'); - const tokens=(await readJson('exports/tokens.resolved.json')).profiles.default.tokens; + const tokens=await defaultTokens(); const payload=await readJson('ports/windows/dist/'+settings.id+'.json'); const backing=target=>[...host.menuTargets,...settings.targets].find(x=>x.target===target); // The status popup owns a Border; the suggestions popup owns a Grid. Its From 0b23e8a9befc10bee01ff85dc1102cedc1c27f25 Mon Sep 17 00:00:00 2001 From: j3w1 Date: Wed, 14 Oct 2026 15:37:44 -0500 Subject: [PATCH 06/65] chore: regenerate Refresh the package closures, generated guide, and source fingerprints after the Node refactor. Co-Authored-By: Claude Opus 5.5 --- exports/digests.json | 16 +- exports/recipes/button/README.md | 2 +- exports/recipes/button/manifest.json | 6 +- exports/recipes/dialog/README.md | 2 +- exports/recipes/dialog/manifest.json | 6 +- exports/recipes/index.json | 6 +- exports/recipes/text-field/README.md | 2 +- exports/recipes/text-field/manifest.json | 6 +- exports/task-inputs.json | 12 +- packages/ui/README.md | 14 +- ...anced-DCpe8Ndv.js => advanced-CqBF0dSb.js} | 9 +- .../choice-B7mo5Eq3.js} | 8 +- .../compositions-D57dCsBz.js} | 4 +- .../display-Jm9bAsnb.js} | 2 +- .../element-Dovcr9Ky.js} | 2 +- ...r-C6Rhfsz6.js => form-builder-C4avSOze.js} | 4 +- .../forms-CE_hP1hg.js} | 2 +- .../native-BjBt1sUh.js} | 2 +- .../navigation-BfNzDYZB.js} | 16 +- .../overlays-Bw8SSDKz.js} | 2 +- .../tables-Cjr1EIJz.js} | 9 +- packages/ui/dist/components/admin-form.js | 6 +- packages/ui/dist/components/alert.js | 6 +- packages/ui/dist/components/avatar.js | 6 +- packages/ui/dist/components/badge.js | 6 +- packages/ui/dist/components/breadcrumbs.js | 6 +- packages/ui/dist/components/button-group.js | 6 +- packages/ui/dist/components/button.js | 6 +- packages/ui/dist/components/card.js | 6 +- packages/ui/dist/components/chart.js | 6 +- packages/ui/dist/components/checkbox.js | 6 +- packages/ui/dist/components/chip.js | 6 +- packages/ui/dist/components/code-editor.js | 6 +- packages/ui/dist/components/combobox.js | 6 +- .../ui/dist/components/command-palette.js | 6 +- .../ui/dist/components/compact-dashboard.js | 6 +- packages/ui/dist/components/data-table.js | 6 +- packages/ui/dist/components/date-picker.js | 6 +- .../ui/dist/components/description-list.js | 6 +- packages/ui/dist/components/diagnostics.js | 6 +- packages/ui/dist/components/dialog.js | 6 +- packages/ui/dist/components/diff-view.js | 6 +- packages/ui/dist/components/disclosure.js | 6 +- packages/ui/dist/components/drawer.js | 6 +- packages/ui/dist/components/editor-search.js | 6 +- packages/ui/dist/components/empty-state.js | 6 +- packages/ui/dist/components/error-state.js | 6 +- packages/ui/dist/components/field.js | 6 +- packages/ui/dist/components/fieldset.js | 6 +- packages/ui/dist/components/file-browser.js | 6 +- packages/ui/dist/components/file-input.js | 6 +- .../ui/dist/components/filterable-table.js | 6 +- packages/ui/dist/components/form-builder.js | 2 +- .../ui/dist/components/i3-window-frame.js | 6 +- packages/ui/dist/components/icon-button.js | 6 +- packages/ui/dist/components/kbd.js | 6 +- packages/ui/dist/components/link.js | 6 +- packages/ui/dist/components/list.js | 6 +- .../ui/dist/components/loading-indicator.js | 6 +- packages/ui/dist/components/menu.js | 6 +- packages/ui/dist/components/multiselect.js | 6 +- packages/ui/dist/components/number-field.js | 6 +- packages/ui/dist/components/pagination.js | 6 +- packages/ui/dist/components/popover.js | 6 +- packages/ui/dist/components/progress.js | 6 +- packages/ui/dist/components/radio-group.js | 6 +- packages/ui/dist/components/range.js | 6 +- packages/ui/dist/components/repeater.js | 6 +- packages/ui/dist/components/search-field.js | 6 +- .../ui/dist/components/segmented-control.js | 6 +- packages/ui/dist/components/select.js | 6 +- packages/ui/dist/components/settings-panel.js | 6 +- packages/ui/dist/components/sidebar-nav.js | 6 +- packages/ui/dist/components/skeleton.js | 6 +- packages/ui/dist/components/skip-link.js | 6 +- packages/ui/dist/components/switch.js | 6 +- packages/ui/dist/components/table.js | 6 +- packages/ui/dist/components/tabs.js | 6 +- packages/ui/dist/components/terminal.js | 6 +- packages/ui/dist/components/text-field.js | 6 +- packages/ui/dist/components/textarea.js | 6 +- packages/ui/dist/components/time-picker.js | 6 +- packages/ui/dist/components/timeline.js | 6 +- packages/ui/dist/components/toast.js | 6 +- packages/ui/dist/components/toolbar.js | 6 +- packages/ui/dist/components/tooltip.js | 6 +- packages/ui/dist/components/tree.js | 6 +- packages/ui/dist/components/wizard.js | 6 +- packages/ui/dist/consumption.md | 14 +- 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-B7mo5Eq3.js} | 8 +- .../runtime/chunks/element-Dovcr9Ky.js} | 2 +- .../runtime/chunks/forms-CE_hP1hg.js} | 2 +- .../runtime/chunks/native-BjBt1sUh.js} | 2 +- .../runtime/components/admin-form.js | 6 +- .../admin-form/runtime/components/select.js | 6 +- .../runtime/components/text-field.js | 6 +- .../admin-form/runtime/components/textarea.js | 6 +- .../admin-form/runtime/register/admin-form.js | 2 +- .../admin-form/runtime/register/select.js | 2 +- .../admin-form/runtime/register/text-field.js | 2 +- .../admin-form/runtime/register/textarea.js | 2 +- packages/ui/dist/copy/alert/manifest.json | 16 +- ...{choice-Db_w_BOQ.js => choice-B7mo5Eq3.js} | 8 +- .../runtime/chunks/element-Dovcr9Ky.js} | 2 +- ...rlays-C6nlCHqg.js => overlays-Bw8SSDKz.js} | 2 +- .../copy/alert/runtime/components/alert.js | 6 +- .../dist/copy/alert/runtime/register/alert.js | 2 +- packages/ui/dist/copy/avatar/manifest.json | 16 +- ...{choice-Db_w_BOQ.js => choice-B7mo5Eq3.js} | 8 +- .../runtime/chunks/display-Jm9bAsnb.js} | 2 +- .../runtime/chunks/element-Dovcr9Ky.js} | 2 +- .../copy/avatar/runtime/components/avatar.js | 6 +- .../copy/avatar/runtime/register/avatar.js | 2 +- packages/ui/dist/copy/badge/manifest.json | 16 +- .../badge/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../badge/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../badge/runtime/chunks/element-C1XeXVYC.js | 232 ----- .../badge/runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../badge/runtime/chunks/native-BjBt1sUh.js} | 2 +- .../copy/badge/runtime/components/badge.js | 6 +- .../dist/copy/badge/runtime/register/badge.js | 2 +- .../ui/dist/copy/breadcrumbs/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/navigation-BfNzDYZB.js} | 16 +- .../runtime/components/breadcrumbs.js | 6 +- .../runtime/register/breadcrumbs.js | 2 +- .../ui/dist/copy/button-group/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/native-BjBt1sUh.js} | 2 +- .../runtime/components/button-group.js | 6 +- .../runtime/register/button-group.js | 2 +- packages/ui/dist/copy/button/manifest.json | 16 +- .../button/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../button/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../button/runtime/chunks/element-C1XeXVYC.js | 232 ----- .../button/runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../button/runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../button/runtime/chunks/native-CAzZmDKR.js | 289 ------ .../copy/button/runtime/components/button.js | 6 +- .../copy/button/runtime/register/button.js | 2 +- packages/ui/dist/copy/card/manifest.json | 16 +- .../card/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../card/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../card/runtime/chunks/element-C1XeXVYC.js | 232 ----- .../card/runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../card/runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../card/runtime/chunks/native-CAzZmDKR.js | 289 ------ .../dist/copy/card/runtime/components/card.js | 6 +- .../dist/copy/card/runtime/register/card.js | 2 +- packages/ui/dist/copy/chart/manifest.json | 16 +- .../chart/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../chart/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/display-Jm9bAsnb.js} | 2 +- .../chart/runtime/chunks/element-C1XeXVYC.js | 232 ----- .../chart/runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../copy/chart/runtime/components/chart.js | 6 +- .../dist/copy/chart/runtime/register/chart.js | 2 +- packages/ui/dist/copy/checkbox/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../runtime/chunks/native-CAzZmDKR.js | 289 ------ .../checkbox/runtime/components/checkbox.js | 6 +- .../checkbox/runtime/register/checkbox.js | 2 +- packages/ui/dist/copy/chip/manifest.json | 16 +- .../chip/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../chip/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../chip/runtime/chunks/element-C1XeXVYC.js | 232 ----- .../chip/runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/overlays-Bw8SSDKz.js} | 2 +- .../dist/copy/chip/runtime/components/chip.js | 6 +- .../dist/copy/chip/runtime/register/chip.js | 2 +- .../ui/dist/copy/code-editor/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/display-Jm9bAsnb.js} | 2 +- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/components/code-editor.js | 6 +- .../runtime/register/code-editor.js | 2 +- packages/ui/dist/copy/combobox/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/navigation-BfNzDYZB.js} | 16 +- .../combobox/runtime/components/combobox.js | 6 +- .../combobox/runtime/register/combobox.js | 2 +- .../dist/copy/command-palette/manifest.json | 16 +- ...anced-DCpe8Ndv.js => advanced-CqBF0dSb.js} | 9 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/components/command-palette.js | 6 +- .../runtime/register/command-palette.js | 2 +- .../dist/copy/compact-dashboard/manifest.json | 28 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- ...s-d6BkKTYf.js => compositions-D57dCsBz.js} | 4 +- .../runtime/chunks/display-Jm9bAsnb.js | 212 ++++ .../runtime/chunks/display-dj9YaBfn.js | 212 ---- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/navigation-BfNzDYZB.js} | 16 +- .../runtime/components/chart.js | 6 +- .../runtime/components/compact-dashboard.js | 6 +- .../runtime/register/chart.js | 2 +- .../runtime/register/compact-dashboard.js | 2 +- .../ui/dist/copy/data-table/manifest.json | 24 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/navigation-BfNzDYZB.js | 377 +++++++ .../runtime/chunks/navigation-Dt8ap-9J.js | 367 ------- .../runtime/chunks/tables-Cjr1EIJz.js} | 9 +- .../runtime/components/data-table.js | 6 +- .../data-table/runtime/components/menu.js | 6 +- .../data-table/runtime/register/data-table.js | 2 +- .../copy/data-table/runtime/register/menu.js | 2 +- .../ui/dist/copy/date-picker/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../runtime/chunks/native-CAzZmDKR.js | 289 ------ .../runtime/components/date-picker.js | 6 +- .../runtime/register/date-picker.js | 2 +- .../dist/copy/description-list/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../runtime/chunks/native-CAzZmDKR.js | 289 ------ .../runtime/components/description-list.js | 6 +- .../runtime/register/description-list.js | 2 +- .../ui/dist/copy/diagnostics/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/display-Jm9bAsnb.js | 212 ++++ .../runtime/chunks/display-dj9YaBfn.js | 212 ---- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/components/diagnostics.js | 6 +- .../runtime/register/diagnostics.js | 2 +- packages/ui/dist/copy/dialog/manifest.json | 16 +- .../dialog/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../dialog/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../dialog/runtime/chunks/element-C1XeXVYC.js | 232 ----- .../dialog/runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/overlays-Bw8SSDKz.js} | 2 +- .../copy/dialog/runtime/components/dialog.js | 6 +- .../copy/dialog/runtime/register/dialog.js | 2 +- packages/ui/dist/copy/diff-view/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/display-Jm9bAsnb.js | 212 ++++ .../runtime/chunks/display-dj9YaBfn.js | 212 ---- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../diff-view/runtime/components/diff-view.js | 6 +- .../diff-view/runtime/register/diff-view.js | 2 +- .../ui/dist/copy/disclosure/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/navigation-BfNzDYZB.js | 377 +++++++ .../runtime/chunks/navigation-Dt8ap-9J.js | 367 ------- .../runtime/components/disclosure.js | 6 +- .../disclosure/runtime/register/disclosure.js | 2 +- packages/ui/dist/copy/drawer/manifest.json | 16 +- .../drawer/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../drawer/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../drawer/runtime/chunks/element-C1XeXVYC.js | 232 ----- .../drawer/runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/overlays-Bw8SSDKz.js | 236 +++++ .../runtime/chunks/overlays-C6nlCHqg.js | 236 ----- .../copy/drawer/runtime/components/drawer.js | 6 +- .../copy/drawer/runtime/register/drawer.js | 2 +- .../ui/dist/copy/editor-search/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/display-Jm9bAsnb.js | 212 ++++ .../runtime/chunks/display-dj9YaBfn.js | 212 ---- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/components/editor-search.js | 6 +- .../runtime/register/editor-search.js | 2 +- .../ui/dist/copy/empty-state/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/overlays-Bw8SSDKz.js | 236 +++++ .../runtime/chunks/overlays-C6nlCHqg.js | 236 ----- .../runtime/components/empty-state.js | 6 +- .../runtime/register/empty-state.js | 2 +- .../ui/dist/copy/error-state/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/overlays-Bw8SSDKz.js | 236 +++++ .../runtime/chunks/overlays-C6nlCHqg.js | 236 ----- .../runtime/components/error-state.js | 6 +- .../runtime/register/error-state.js | 2 +- packages/ui/dist/copy/field/manifest.json | 16 +- .../field/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../field/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../field/runtime/chunks/element-C1XeXVYC.js | 232 ----- .../field/runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../field/runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../field/runtime/chunks/native-CAzZmDKR.js | 289 ------ .../copy/field/runtime/components/field.js | 6 +- .../dist/copy/field/runtime/register/field.js | 2 +- packages/ui/dist/copy/fieldset/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../runtime/chunks/native-CAzZmDKR.js | 289 ------ .../fieldset/runtime/components/fieldset.js | 6 +- .../fieldset/runtime/register/fieldset.js | 2 +- .../ui/dist/copy/file-browser/manifest.json | 28 +- ...anced-DCpe8Ndv.js => advanced-CqBF0dSb.js} | 9 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/compositions-D57dCsBz.js} | 4 +- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/navigation-BfNzDYZB.js | 377 +++++++ .../runtime/chunks/navigation-Dt8ap-9J.js | 367 ------- .../runtime/components/file-browser.js | 6 +- .../file-browser/runtime/components/tree.js | 6 +- .../runtime/register/file-browser.js | 2 +- .../file-browser/runtime/register/tree.js | 2 +- .../ui/dist/copy/file-input/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../runtime/chunks/native-CAzZmDKR.js | 289 ------ .../runtime/components/file-input.js | 6 +- .../file-input/runtime/register/file-input.js | 2 +- .../dist/copy/filterable-table/manifest.json | 24 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../runtime/chunks/native-CAzZmDKR.js | 289 ------ .../runtime/chunks/tables-Cjr1EIJz.js} | 9 +- .../runtime/components/filterable-table.js | 6 +- .../runtime/components/search-field.js | 6 +- .../runtime/register/filterable-table.js | 2 +- .../runtime/register/search-field.js | 2 +- .../ui/dist/copy/form-builder/element.html | 8 +- packages/ui/dist/copy/form-builder/index.html | 8 +- .../ui/dist/copy/form-builder/manifest.json | 18 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ ...r-C6Rhfsz6.js => form-builder-C4avSOze.js} | 4 +- .../runtime/register/form-builder.js | 4 +- .../dist/copy/i3-window-frame/manifest.json | 20 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/compositions-D57dCsBz.js} | 4 +- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/navigation-BfNzDYZB.js | 377 +++++++ .../runtime/chunks/navigation-Dt8ap-9J.js | 367 ------- .../runtime/components/i3-window-frame.js | 6 +- .../runtime/register/i3-window-frame.js | 2 +- .../ui/dist/copy/icon-button/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../runtime/chunks/native-CAzZmDKR.js | 289 ------ .../runtime/components/icon-button.js | 6 +- .../runtime/register/icon-button.js | 2 +- packages/ui/dist/copy/kbd/manifest.json | 16 +- .../kbd/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../kbd/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../kbd/runtime/chunks/element-C1XeXVYC.js | 232 ----- .../kbd/runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../kbd/runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../kbd/runtime/chunks/native-CAzZmDKR.js | 289 ------ .../dist/copy/kbd/runtime/components/kbd.js | 6 +- .../ui/dist/copy/kbd/runtime/register/kbd.js | 2 +- packages/ui/dist/copy/link/manifest.json | 16 +- .../link/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../link/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../link/runtime/chunks/element-C1XeXVYC.js | 232 ----- .../link/runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../link/runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../link/runtime/chunks/native-CAzZmDKR.js | 289 ------ .../dist/copy/link/runtime/components/link.js | 6 +- .../dist/copy/link/runtime/register/link.js | 2 +- packages/ui/dist/copy/list/manifest.json | 16 +- .../list/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../list/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../list/runtime/chunks/element-C1XeXVYC.js | 232 ----- .../list/runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../list/runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../list/runtime/chunks/native-CAzZmDKR.js | 289 ------ .../dist/copy/list/runtime/components/list.js | 6 +- .../dist/copy/list/runtime/register/list.js | 2 +- .../dist/copy/loading-indicator/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../runtime/chunks/native-CAzZmDKR.js | 289 ------ .../runtime/components/loading-indicator.js | 6 +- .../runtime/register/loading-indicator.js | 2 +- packages/ui/dist/copy/menu/manifest.json | 16 +- .../menu/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../menu/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../menu/runtime/chunks/element-C1XeXVYC.js | 232 ----- .../menu/runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/navigation-BfNzDYZB.js | 377 +++++++ .../runtime/chunks/navigation-Dt8ap-9J.js | 367 ------- .../dist/copy/menu/runtime/components/menu.js | 6 +- .../dist/copy/menu/runtime/register/menu.js | 2 +- .../ui/dist/copy/multiselect/manifest.json | 16 +- ...anced-DCpe8Ndv.js => advanced-CqBF0dSb.js} | 9 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/components/multiselect.js | 6 +- .../runtime/register/multiselect.js | 2 +- .../ui/dist/copy/number-field/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../runtime/chunks/native-CAzZmDKR.js | 289 ------ .../runtime/components/number-field.js | 6 +- .../runtime/register/number-field.js | 2 +- .../ui/dist/copy/pagination/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/tables-Cjr1EIJz.js} | 9 +- .../runtime/components/pagination.js | 6 +- .../pagination/runtime/register/pagination.js | 2 +- packages/ui/dist/copy/popover/manifest.json | 16 +- .../popover/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../popover/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/overlays-Bw8SSDKz.js | 236 +++++ .../runtime/chunks/overlays-C6nlCHqg.js | 236 ----- .../popover/runtime/components/popover.js | 6 +- .../copy/popover/runtime/register/popover.js | 2 +- packages/ui/dist/copy/progress/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../runtime/chunks/native-CAzZmDKR.js | 289 ------ .../progress/runtime/components/progress.js | 6 +- .../progress/runtime/register/progress.js | 2 +- .../ui/dist/copy/radio-group/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../runtime/chunks/native-CAzZmDKR.js | 289 ------ .../runtime/components/radio-group.js | 6 +- .../runtime/register/radio-group.js | 2 +- packages/ui/dist/copy/range/manifest.json | 16 +- .../range/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../range/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../range/runtime/chunks/element-C1XeXVYC.js | 232 ----- .../range/runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../range/runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../range/runtime/chunks/native-CAzZmDKR.js | 289 ------ .../copy/range/runtime/components/range.js | 6 +- .../dist/copy/range/runtime/register/range.js | 2 +- packages/ui/dist/copy/repeater/manifest.json | 16 +- .../runtime/chunks/advanced-CqBF0dSb.js | 345 +++++++ .../runtime/chunks/advanced-DCpe8Ndv.js | 340 ------- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../repeater/runtime/components/repeater.js | 6 +- .../repeater/runtime/register/repeater.js | 2 +- .../ui/dist/copy/search-field/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../runtime/chunks/native-CAzZmDKR.js | 289 ------ .../runtime/components/search-field.js | 6 +- .../runtime/register/search-field.js | 2 +- .../dist/copy/segmented-control/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../runtime/chunks/native-CAzZmDKR.js | 289 ------ .../runtime/components/segmented-control.js | 6 +- .../runtime/register/segmented-control.js | 2 +- packages/ui/dist/copy/select/manifest.json | 16 +- .../select/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../select/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../select/runtime/chunks/element-C1XeXVYC.js | 232 ----- .../select/runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../select/runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../select/runtime/chunks/native-CAzZmDKR.js | 289 ------ .../copy/select/runtime/components/select.js | 6 +- .../copy/select/runtime/register/select.js | 2 +- .../ui/dist/copy/settings-panel/manifest.json | 24 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/forms-CE_hP1hg.js} | 2 +- .../runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../runtime/chunks/native-CAzZmDKR.js | 289 ------ .../runtime/components/settings-panel.js | 6 +- .../runtime/components/switch.js | 6 +- .../runtime/register/settings-panel.js | 2 +- .../settings-panel/runtime/register/switch.js | 2 +- .../ui/dist/copy/sidebar-nav/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/navigation-BfNzDYZB.js | 377 +++++++ .../runtime/chunks/navigation-Dt8ap-9J.js | 367 ------- .../runtime/components/sidebar-nav.js | 6 +- .../runtime/register/sidebar-nav.js | 2 +- packages/ui/dist/copy/skeleton/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../runtime/chunks/native-CAzZmDKR.js | 289 ------ .../skeleton/runtime/components/skeleton.js | 6 +- .../skeleton/runtime/register/skeleton.js | 2 +- packages/ui/dist/copy/skip-link/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../runtime/chunks/native-CAzZmDKR.js | 289 ------ .../skip-link/runtime/components/skip-link.js | 6 +- .../skip-link/runtime/register/skip-link.js | 2 +- packages/ui/dist/copy/switch/manifest.json | 16 +- .../switch/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../switch/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../switch/runtime/chunks/element-C1XeXVYC.js | 232 ----- .../switch/runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../switch/runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../switch/runtime/chunks/native-CAzZmDKR.js | 289 ------ .../copy/switch/runtime/components/switch.js | 6 +- .../copy/switch/runtime/register/switch.js | 2 +- packages/ui/dist/copy/table/manifest.json | 16 +- .../table/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../table/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../table/runtime/chunks/element-C1XeXVYC.js | 232 ----- .../table/runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../table/runtime/chunks/tables-B25ydUHs.js | 212 ---- .../table/runtime/chunks/tables-Cjr1EIJz.js | 217 ++++ .../copy/table/runtime/components/table.js | 6 +- .../dist/copy/table/runtime/register/table.js | 2 +- packages/ui/dist/copy/tabs/manifest.json | 16 +- .../tabs/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../tabs/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../tabs/runtime/chunks/element-C1XeXVYC.js | 232 ----- .../tabs/runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/navigation-BfNzDYZB.js | 377 +++++++ .../runtime/chunks/navigation-Dt8ap-9J.js | 367 ------- .../dist/copy/tabs/runtime/components/tabs.js | 6 +- .../dist/copy/tabs/runtime/register/tabs.js | 2 +- packages/ui/dist/copy/terminal/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/display-Jm9bAsnb.js | 212 ++++ .../runtime/chunks/display-dj9YaBfn.js | 212 ---- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../terminal/runtime/components/terminal.js | 6 +- .../terminal/runtime/register/terminal.js | 2 +- .../ui/dist/copy/text-field/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../runtime/chunks/native-CAzZmDKR.js | 289 ------ .../runtime/components/text-field.js | 6 +- .../text-field/runtime/register/text-field.js | 2 +- packages/ui/dist/copy/textarea/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../runtime/chunks/native-CAzZmDKR.js | 289 ------ .../textarea/runtime/components/textarea.js | 6 +- .../textarea/runtime/register/textarea.js | 2 +- .../ui/dist/copy/time-picker/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../runtime/chunks/native-CAzZmDKR.js | 289 ------ .../runtime/components/time-picker.js | 6 +- .../runtime/register/time-picker.js | 2 +- packages/ui/dist/copy/timeline/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/native-BjBt1sUh.js | 289 ++++++ .../runtime/chunks/native-CAzZmDKR.js | 289 ------ .../timeline/runtime/components/timeline.js | 6 +- .../timeline/runtime/register/timeline.js | 2 +- packages/ui/dist/copy/toast/manifest.json | 16 +- .../toast/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../toast/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../toast/runtime/chunks/element-C1XeXVYC.js | 232 ----- .../toast/runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../toast/runtime/chunks/overlays-Bw8SSDKz.js | 236 +++++ .../toast/runtime/chunks/overlays-C6nlCHqg.js | 236 ----- .../copy/toast/runtime/components/toast.js | 6 +- .../dist/copy/toast/runtime/register/toast.js | 2 +- packages/ui/dist/copy/toolbar/manifest.json | 20 +- .../toolbar/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../toolbar/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/navigation-BfNzDYZB.js | 377 +++++++ .../runtime/chunks/navigation-Dt8ap-9J.js | 367 ------- .../copy/toolbar/runtime/components/menu.js | 6 +- .../toolbar/runtime/components/toolbar.js | 6 +- .../copy/toolbar/runtime/register/menu.js | 2 +- .../copy/toolbar/runtime/register/toolbar.js | 2 +- packages/ui/dist/copy/tooltip/manifest.json | 16 +- .../tooltip/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../tooltip/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../runtime/chunks/element-C1XeXVYC.js | 232 ----- .../runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../runtime/chunks/overlays-Bw8SSDKz.js | 236 +++++ .../runtime/chunks/overlays-C6nlCHqg.js | 236 ----- .../tooltip/runtime/components/tooltip.js | 6 +- .../copy/tooltip/runtime/register/tooltip.js | 2 +- packages/ui/dist/copy/tree/manifest.json | 16 +- .../tree/runtime/chunks/advanced-CqBF0dSb.js | 345 +++++++ .../tree/runtime/chunks/advanced-DCpe8Ndv.js | 340 ------- .../tree/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../tree/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../tree/runtime/chunks/element-C1XeXVYC.js | 232 ----- .../tree/runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../dist/copy/tree/runtime/components/tree.js | 6 +- .../dist/copy/tree/runtime/register/tree.js | 2 +- packages/ui/dist/copy/wizard/manifest.json | 16 +- .../wizard/runtime/chunks/choice-B7mo5Eq3.js | 938 ++++++++++++++++++ .../wizard/runtime/chunks/choice-Db_w_BOQ.js | 932 ----------------- .../wizard/runtime/chunks/element-C1XeXVYC.js | 232 ----- .../wizard/runtime/chunks/element-Dovcr9Ky.js | 232 +++++ .../{forms-BT3z7lNC.js => forms-CE_hP1hg.js} | 2 +- .../copy/wizard/runtime/components/wizard.js | 6 +- .../copy/wizard/runtime/register/wizard.js | 2 +- packages/ui/dist/enhance/choice.js | 2 +- packages/ui/dist/examples.json | 2 +- packages/ui/dist/examples/form-builder.json | 2 +- packages/ui/dist/index.js | 2 +- packages/ui/dist/manifest.json | 860 ++++++++-------- packages/ui/dist/register/admin-form.js | 2 +- packages/ui/dist/register/alert.js | 2 +- packages/ui/dist/register/avatar.js | 2 +- packages/ui/dist/register/badge.js | 2 +- packages/ui/dist/register/breadcrumbs.js | 2 +- packages/ui/dist/register/button-group.js | 2 +- packages/ui/dist/register/button.js | 2 +- packages/ui/dist/register/card.js | 2 +- packages/ui/dist/register/chart.js | 2 +- packages/ui/dist/register/checkbox.js | 2 +- packages/ui/dist/register/chip.js | 2 +- packages/ui/dist/register/code-editor.js | 2 +- packages/ui/dist/register/combobox.js | 2 +- packages/ui/dist/register/command-palette.js | 2 +- .../ui/dist/register/compact-dashboard.js | 2 +- packages/ui/dist/register/data-table.js | 2 +- packages/ui/dist/register/date-picker.js | 2 +- packages/ui/dist/register/description-list.js | 2 +- packages/ui/dist/register/diagnostics.js | 2 +- packages/ui/dist/register/dialog.js | 2 +- packages/ui/dist/register/diff-view.js | 2 +- packages/ui/dist/register/disclosure.js | 2 +- packages/ui/dist/register/drawer.js | 2 +- packages/ui/dist/register/editor-search.js | 2 +- packages/ui/dist/register/empty-state.js | 2 +- packages/ui/dist/register/error-state.js | 2 +- packages/ui/dist/register/field.js | 2 +- packages/ui/dist/register/fieldset.js | 2 +- packages/ui/dist/register/file-browser.js | 2 +- packages/ui/dist/register/file-input.js | 2 +- packages/ui/dist/register/filterable-table.js | 2 +- packages/ui/dist/register/form-builder.js | 4 +- packages/ui/dist/register/i3-window-frame.js | 2 +- packages/ui/dist/register/icon-button.js | 2 +- packages/ui/dist/register/kbd.js | 2 +- packages/ui/dist/register/link.js | 2 +- packages/ui/dist/register/list.js | 2 +- .../ui/dist/register/loading-indicator.js | 2 +- packages/ui/dist/register/menu.js | 2 +- packages/ui/dist/register/multiselect.js | 2 +- packages/ui/dist/register/number-field.js | 2 +- packages/ui/dist/register/pagination.js | 2 +- packages/ui/dist/register/popover.js | 2 +- packages/ui/dist/register/progress.js | 2 +- packages/ui/dist/register/radio-group.js | 2 +- packages/ui/dist/register/range.js | 2 +- packages/ui/dist/register/repeater.js | 2 +- packages/ui/dist/register/search-field.js | 2 +- .../ui/dist/register/segmented-control.js | 2 +- packages/ui/dist/register/select.js | 2 +- packages/ui/dist/register/settings-panel.js | 2 +- packages/ui/dist/register/sidebar-nav.js | 2 +- packages/ui/dist/register/skeleton.js | 2 +- packages/ui/dist/register/skip-link.js | 2 +- packages/ui/dist/register/switch.js | 2 +- packages/ui/dist/register/table.js | 2 +- packages/ui/dist/register/tabs.js | 2 +- packages/ui/dist/register/terminal.js | 2 +- packages/ui/dist/register/text-field.js | 2 +- packages/ui/dist/register/textarea.js | 2 +- packages/ui/dist/register/time-picker.js | 2 +- packages/ui/dist/register/timeline.js | 2 +- packages/ui/dist/register/toast.js | 2 +- packages/ui/dist/register/toolbar.js | 2 +- packages/ui/dist/register/tooltip.js | 2 +- packages/ui/dist/register/tree.js | 2 +- packages/ui/dist/register/wizard.js | 2 +- 837 files changed, 91528 insertions(+), 90933 deletions(-) rename packages/ui/dist/chunks/{advanced-DCpe8Ndv.js => advanced-CqBF0dSb.js} (97%) rename packages/ui/dist/{copy/admin-form/runtime/chunks/choice-Db_w_BOQ.js => chunks/choice-B7mo5Eq3.js} (98%) rename packages/ui/dist/{copy/i3-window-frame/runtime/chunks/compositions-d6BkKTYf.js => chunks/compositions-D57dCsBz.js} (94%) rename packages/ui/dist/{copy/chart/runtime/chunks/display-dj9YaBfn.js => chunks/display-Jm9bAsnb.js} (98%) rename packages/ui/dist/{copy/alert/runtime/chunks/element-C1XeXVYC.js => chunks/element-Dovcr9Ky.js} (99%) rename packages/ui/dist/chunks/{form-builder-C6Rhfsz6.js => form-builder-C4avSOze.js} (92%) rename packages/ui/dist/{copy/settings-panel/runtime/chunks/forms-BT3z7lNC.js => chunks/forms-CE_hP1hg.js} (98%) rename packages/ui/dist/{copy/badge/runtime/chunks/native-CAzZmDKR.js => chunks/native-BjBt1sUh.js} (98%) rename packages/ui/dist/{copy/compact-dashboard/runtime/chunks/navigation-Dt8ap-9J.js => chunks/navigation-BfNzDYZB.js} (96%) rename packages/ui/dist/{copy/chip/runtime/chunks/overlays-C6nlCHqg.js => chunks/overlays-Bw8SSDKz.js} (98%) rename packages/ui/dist/{copy/data-table/runtime/chunks/tables-B25ydUHs.js => chunks/tables-Cjr1EIJz.js} (96%) rename packages/ui/dist/{chunks/choice-Db_w_BOQ.js => copy/admin-form/runtime/chunks/choice-B7mo5Eq3.js} (98%) rename packages/ui/dist/{chunks/element-C1XeXVYC.js => copy/admin-form/runtime/chunks/element-Dovcr9Ky.js} (99%) rename packages/ui/dist/{chunks/forms-BT3z7lNC.js => copy/admin-form/runtime/chunks/forms-CE_hP1hg.js} (98%) rename packages/ui/dist/copy/{button-group/runtime/chunks/native-CAzZmDKR.js => admin-form/runtime/chunks/native-BjBt1sUh.js} (98%) rename packages/ui/dist/copy/alert/runtime/chunks/{choice-Db_w_BOQ.js => choice-B7mo5Eq3.js} (98%) rename packages/ui/dist/copy/{avatar/runtime/chunks/element-C1XeXVYC.js => alert/runtime/chunks/element-Dovcr9Ky.js} (99%) rename packages/ui/dist/copy/alert/runtime/chunks/{overlays-C6nlCHqg.js => overlays-Bw8SSDKz.js} (98%) rename packages/ui/dist/copy/avatar/runtime/chunks/{choice-Db_w_BOQ.js => choice-B7mo5Eq3.js} (98%) rename packages/ui/dist/copy/{code-editor/runtime/chunks/display-dj9YaBfn.js => avatar/runtime/chunks/display-Jm9bAsnb.js} (98%) rename packages/ui/dist/copy/{admin-form/runtime/chunks/element-C1XeXVYC.js => avatar/runtime/chunks/element-Dovcr9Ky.js} (99%) create mode 100644 packages/ui/dist/copy/badge/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/badge/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/badge/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/badge/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/{chunks/native-CAzZmDKR.js => copy/badge/runtime/chunks/native-BjBt1sUh.js} (98%) create mode 100644 packages/ui/dist/copy/breadcrumbs/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/breadcrumbs/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/breadcrumbs/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/breadcrumbs/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/{chunks/navigation-Dt8ap-9J.js => copy/breadcrumbs/runtime/chunks/navigation-BfNzDYZB.js} (96%) create mode 100644 packages/ui/dist/copy/button-group/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/button-group/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/button-group/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/button-group/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/copy/{admin-form/runtime/chunks/native-CAzZmDKR.js => button-group/runtime/chunks/native-BjBt1sUh.js} (98%) create mode 100644 packages/ui/dist/copy/button/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/button/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/button/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/button/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/button/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/button/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/card/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/card/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/card/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/card/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/card/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/card/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/chart/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/chart/runtime/chunks/choice-Db_w_BOQ.js rename packages/ui/dist/copy/{avatar/runtime/chunks/display-dj9YaBfn.js => chart/runtime/chunks/display-Jm9bAsnb.js} (98%) delete mode 100644 packages/ui/dist/copy/chart/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/chart/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/checkbox/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/checkbox/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/checkbox/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/checkbox/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/checkbox/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/checkbox/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/chip/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/chip/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/chip/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/chip/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/copy/{dialog/runtime/chunks/overlays-C6nlCHqg.js => chip/runtime/chunks/overlays-Bw8SSDKz.js} (98%) create mode 100644 packages/ui/dist/copy/code-editor/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/code-editor/runtime/chunks/choice-Db_w_BOQ.js rename packages/ui/dist/{chunks/display-dj9YaBfn.js => copy/code-editor/runtime/chunks/display-Jm9bAsnb.js} (98%) delete mode 100644 packages/ui/dist/copy/code-editor/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/code-editor/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/combobox/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/combobox/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/combobox/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/combobox/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/copy/{breadcrumbs/runtime/chunks/navigation-Dt8ap-9J.js => combobox/runtime/chunks/navigation-BfNzDYZB.js} (96%) rename packages/ui/dist/copy/command-palette/runtime/chunks/{advanced-DCpe8Ndv.js => advanced-CqBF0dSb.js} (97%) create mode 100644 packages/ui/dist/copy/command-palette/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/command-palette/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/command-palette/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/command-palette/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/compact-dashboard/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/compact-dashboard/runtime/chunks/choice-Db_w_BOQ.js rename packages/ui/dist/copy/compact-dashboard/runtime/chunks/{compositions-d6BkKTYf.js => compositions-D57dCsBz.js} (94%) create mode 100644 packages/ui/dist/copy/compact-dashboard/runtime/chunks/display-Jm9bAsnb.js delete mode 100644 packages/ui/dist/copy/compact-dashboard/runtime/chunks/display-dj9YaBfn.js delete mode 100644 packages/ui/dist/copy/compact-dashboard/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/compact-dashboard/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/copy/{combobox/runtime/chunks/navigation-Dt8ap-9J.js => compact-dashboard/runtime/chunks/navigation-BfNzDYZB.js} (96%) create mode 100644 packages/ui/dist/copy/data-table/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/data-table/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/data-table/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/data-table/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/data-table/runtime/chunks/navigation-BfNzDYZB.js delete mode 100644 packages/ui/dist/copy/data-table/runtime/chunks/navigation-Dt8ap-9J.js rename packages/ui/dist/copy/{filterable-table/runtime/chunks/tables-B25ydUHs.js => data-table/runtime/chunks/tables-Cjr1EIJz.js} (96%) create mode 100644 packages/ui/dist/copy/date-picker/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/date-picker/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/date-picker/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/date-picker/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/date-picker/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/date-picker/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/description-list/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/description-list/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/description-list/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/description-list/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/description-list/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/description-list/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/diagnostics/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/diagnostics/runtime/chunks/choice-Db_w_BOQ.js create mode 100644 packages/ui/dist/copy/diagnostics/runtime/chunks/display-Jm9bAsnb.js delete mode 100644 packages/ui/dist/copy/diagnostics/runtime/chunks/display-dj9YaBfn.js delete mode 100644 packages/ui/dist/copy/diagnostics/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/diagnostics/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/dialog/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/dialog/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/dialog/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/dialog/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/{chunks/overlays-C6nlCHqg.js => copy/dialog/runtime/chunks/overlays-Bw8SSDKz.js} (98%) create mode 100644 packages/ui/dist/copy/diff-view/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/diff-view/runtime/chunks/choice-Db_w_BOQ.js create mode 100644 packages/ui/dist/copy/diff-view/runtime/chunks/display-Jm9bAsnb.js delete mode 100644 packages/ui/dist/copy/diff-view/runtime/chunks/display-dj9YaBfn.js delete mode 100644 packages/ui/dist/copy/diff-view/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/diff-view/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/disclosure/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/disclosure/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/disclosure/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/disclosure/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/disclosure/runtime/chunks/navigation-BfNzDYZB.js delete mode 100644 packages/ui/dist/copy/disclosure/runtime/chunks/navigation-Dt8ap-9J.js create mode 100644 packages/ui/dist/copy/drawer/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/drawer/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/drawer/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/drawer/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/drawer/runtime/chunks/overlays-Bw8SSDKz.js delete mode 100644 packages/ui/dist/copy/drawer/runtime/chunks/overlays-C6nlCHqg.js create mode 100644 packages/ui/dist/copy/editor-search/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/editor-search/runtime/chunks/choice-Db_w_BOQ.js create mode 100644 packages/ui/dist/copy/editor-search/runtime/chunks/display-Jm9bAsnb.js delete mode 100644 packages/ui/dist/copy/editor-search/runtime/chunks/display-dj9YaBfn.js delete mode 100644 packages/ui/dist/copy/editor-search/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/editor-search/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/empty-state/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/empty-state/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/empty-state/runtime/chunks/element-C1XeXVYC.js create 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-Bw8SSDKz.js delete mode 100644 packages/ui/dist/copy/empty-state/runtime/chunks/overlays-C6nlCHqg.js create mode 100644 packages/ui/dist/copy/error-state/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/error-state/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/error-state/runtime/chunks/element-C1XeXVYC.js create 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-Bw8SSDKz.js delete mode 100644 packages/ui/dist/copy/error-state/runtime/chunks/overlays-C6nlCHqg.js create mode 100644 packages/ui/dist/copy/field/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/field/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/field/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/field/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/field/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/field/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/fieldset/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/fieldset/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/fieldset/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/fieldset/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/fieldset/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/fieldset/runtime/chunks/native-CAzZmDKR.js rename packages/ui/dist/copy/file-browser/runtime/chunks/{advanced-DCpe8Ndv.js => advanced-CqBF0dSb.js} (97%) create mode 100644 packages/ui/dist/copy/file-browser/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/file-browser/runtime/chunks/choice-Db_w_BOQ.js rename packages/ui/dist/{chunks/compositions-d6BkKTYf.js => copy/file-browser/runtime/chunks/compositions-D57dCsBz.js} (94%) delete mode 100644 packages/ui/dist/copy/file-browser/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/file-browser/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/file-browser/runtime/chunks/navigation-BfNzDYZB.js delete mode 100644 packages/ui/dist/copy/file-browser/runtime/chunks/navigation-Dt8ap-9J.js create mode 100644 packages/ui/dist/copy/file-input/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/file-input/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/file-input/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/file-input/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/file-input/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/file-input/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/filterable-table/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/filterable-table/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/filterable-table/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/filterable-table/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/filterable-table/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/filterable-table/runtime/chunks/native-CAzZmDKR.js rename packages/ui/dist/copy/{pagination/runtime/chunks/tables-B25ydUHs.js => filterable-table/runtime/chunks/tables-Cjr1EIJz.js} (96%) create mode 100644 packages/ui/dist/copy/form-builder/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/form-builder/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/form-builder/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/form-builder/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/copy/form-builder/runtime/chunks/{form-builder-C6Rhfsz6.js => form-builder-C4avSOze.js} (92%) create mode 100644 packages/ui/dist/copy/i3-window-frame/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/i3-window-frame/runtime/chunks/choice-Db_w_BOQ.js rename packages/ui/dist/copy/{file-browser/runtime/chunks/compositions-d6BkKTYf.js => i3-window-frame/runtime/chunks/compositions-D57dCsBz.js} (94%) delete mode 100644 packages/ui/dist/copy/i3-window-frame/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/i3-window-frame/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/i3-window-frame/runtime/chunks/navigation-BfNzDYZB.js delete mode 100644 packages/ui/dist/copy/i3-window-frame/runtime/chunks/navigation-Dt8ap-9J.js create mode 100644 packages/ui/dist/copy/icon-button/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/icon-button/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/icon-button/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/icon-button/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/icon-button/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/icon-button/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/kbd/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/kbd/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/kbd/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/kbd/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/kbd/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/kbd/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/link/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/link/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/link/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/link/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/link/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/link/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/list/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/list/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/list/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/list/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/list/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/list/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/loading-indicator/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/loading-indicator/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/loading-indicator/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/loading-indicator/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/loading-indicator/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/loading-indicator/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/menu/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/menu/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/menu/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/menu/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/menu/runtime/chunks/navigation-BfNzDYZB.js delete mode 100644 packages/ui/dist/copy/menu/runtime/chunks/navigation-Dt8ap-9J.js rename packages/ui/dist/copy/multiselect/runtime/chunks/{advanced-DCpe8Ndv.js => advanced-CqBF0dSb.js} (97%) create mode 100644 packages/ui/dist/copy/multiselect/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/multiselect/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/multiselect/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/multiselect/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/number-field/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/number-field/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/number-field/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/number-field/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/number-field/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/number-field/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/pagination/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/pagination/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/pagination/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/pagination/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/{chunks/tables-B25ydUHs.js => copy/pagination/runtime/chunks/tables-Cjr1EIJz.js} (96%) create mode 100644 packages/ui/dist/copy/popover/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/popover/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/popover/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/popover/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/popover/runtime/chunks/overlays-Bw8SSDKz.js delete mode 100644 packages/ui/dist/copy/popover/runtime/chunks/overlays-C6nlCHqg.js create mode 100644 packages/ui/dist/copy/progress/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/progress/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/progress/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/progress/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/progress/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/progress/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/radio-group/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/radio-group/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/radio-group/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/radio-group/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/radio-group/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/radio-group/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/range/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/range/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/range/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/range/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/range/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/range/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/repeater/runtime/chunks/advanced-CqBF0dSb.js delete mode 100644 packages/ui/dist/copy/repeater/runtime/chunks/advanced-DCpe8Ndv.js create mode 100644 packages/ui/dist/copy/repeater/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/repeater/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/repeater/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/repeater/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/search-field/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/search-field/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/search-field/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/search-field/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/search-field/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/search-field/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/segmented-control/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/segmented-control/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/segmented-control/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/segmented-control/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/segmented-control/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/segmented-control/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/select/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/select/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/select/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/select/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/select/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/select/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/settings-panel/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/settings-panel/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/settings-panel/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/settings-panel/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/copy/{admin-form/runtime/chunks/forms-BT3z7lNC.js => settings-panel/runtime/chunks/forms-CE_hP1hg.js} (98%) create mode 100644 packages/ui/dist/copy/settings-panel/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/settings-panel/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/sidebar-nav/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/sidebar-nav/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/sidebar-nav/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/sidebar-nav/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/sidebar-nav/runtime/chunks/navigation-BfNzDYZB.js delete mode 100644 packages/ui/dist/copy/sidebar-nav/runtime/chunks/navigation-Dt8ap-9J.js create mode 100644 packages/ui/dist/copy/skeleton/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/skeleton/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/skeleton/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/skeleton/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/skeleton/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/skeleton/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/skip-link/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/skip-link/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/skip-link/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/skip-link/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/skip-link/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/skip-link/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/switch/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/switch/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/switch/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/switch/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/switch/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/switch/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/table/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/table/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/table/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/table/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/table/runtime/chunks/tables-B25ydUHs.js create mode 100644 packages/ui/dist/copy/table/runtime/chunks/tables-Cjr1EIJz.js create mode 100644 packages/ui/dist/copy/tabs/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/tabs/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/tabs/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/tabs/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/tabs/runtime/chunks/navigation-BfNzDYZB.js delete mode 100644 packages/ui/dist/copy/tabs/runtime/chunks/navigation-Dt8ap-9J.js create mode 100644 packages/ui/dist/copy/terminal/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/terminal/runtime/chunks/choice-Db_w_BOQ.js create mode 100644 packages/ui/dist/copy/terminal/runtime/chunks/display-Jm9bAsnb.js delete mode 100644 packages/ui/dist/copy/terminal/runtime/chunks/display-dj9YaBfn.js delete mode 100644 packages/ui/dist/copy/terminal/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/terminal/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/text-field/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/text-field/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/text-field/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/text-field/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/text-field/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/text-field/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/textarea/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/textarea/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/textarea/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/textarea/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/textarea/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/textarea/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/time-picker/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/time-picker/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/time-picker/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/time-picker/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/time-picker/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/time-picker/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/timeline/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/timeline/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/timeline/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/timeline/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/timeline/runtime/chunks/native-BjBt1sUh.js delete mode 100644 packages/ui/dist/copy/timeline/runtime/chunks/native-CAzZmDKR.js create mode 100644 packages/ui/dist/copy/toast/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/toast/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/toast/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/toast/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/toast/runtime/chunks/overlays-Bw8SSDKz.js delete mode 100644 packages/ui/dist/copy/toast/runtime/chunks/overlays-C6nlCHqg.js create mode 100644 packages/ui/dist/copy/toolbar/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/toolbar/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/toolbar/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/toolbar/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/toolbar/runtime/chunks/navigation-BfNzDYZB.js delete mode 100644 packages/ui/dist/copy/toolbar/runtime/chunks/navigation-Dt8ap-9J.js create mode 100644 packages/ui/dist/copy/tooltip/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/tooltip/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/tooltip/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/tooltip/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/tooltip/runtime/chunks/overlays-Bw8SSDKz.js delete mode 100644 packages/ui/dist/copy/tooltip/runtime/chunks/overlays-C6nlCHqg.js create mode 100644 packages/ui/dist/copy/tree/runtime/chunks/advanced-CqBF0dSb.js delete mode 100644 packages/ui/dist/copy/tree/runtime/chunks/advanced-DCpe8Ndv.js create mode 100644 packages/ui/dist/copy/tree/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/tree/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/tree/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/tree/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/wizard/runtime/chunks/choice-B7mo5Eq3.js delete mode 100644 packages/ui/dist/copy/wizard/runtime/chunks/choice-Db_w_BOQ.js delete mode 100644 packages/ui/dist/copy/wizard/runtime/chunks/element-C1XeXVYC.js create mode 100644 packages/ui/dist/copy/wizard/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/copy/wizard/runtime/chunks/{forms-BT3z7lNC.js => forms-CE_hP1hg.js} (98%) diff --git a/exports/digests.json b/exports/digests.json index d2131d960..d21fc9561 100644 --- a/exports/digests.json +++ b/exports/digests.json @@ -148,37 +148,37 @@ "exports/patterns/validation-recovery.json": "sha256-hEfzGewdNViHMChlN5b8EXUCao68upU06VxJlR3Dp1w=", "exports/port-capabilities.json": "sha256-6u3M0mXA+lN5FLjtOJvRkLpcFNePSv8ZUMpIiVohxVQ=", "exports/recipes/button/LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "exports/recipes/button/README.md": "sha256-mS8bIWiTXGBfI7igIXsai6GF4p7KlPCfsQvAEFb9fls=", + "exports/recipes/button/README.md": "sha256-3bnwFyaC2y+GHMRGleeDP2VGp3TtThGtzreM6cNsW5I=", "exports/recipes/button/component.css": "sha256-+Fn90PbGbnW0JxDH1RAdiYrVQ4FrstMA+Rq7HlAQTdU=", "exports/recipes/button/example.html": "sha256-HRSLwap8t93ggusQ8BYoEAE0wPCsBWTKSY+4JGzRNa4=", "exports/recipes/button/foundation.css": "sha256-gItmMJgxTkuTe8+9G3aZQviwGcJ5cQaNANEvpcyOA88=", - "exports/recipes/button/manifest.json": "sha256-AA++frM2He0KhcMDOlEUKBy7S82fbjAvkWU7QAA69uc=", + "exports/recipes/button/manifest.json": "sha256-2rzEGNy89Z3MLwmbhF6b+bpO0/TAEBnjfWN2A9DhQWA=", "exports/recipes/button/markup.html": "sha256-9HjLJ98lH4SKiwVWynQKarCqWTK/+IKfcvGr6464P3c=", "exports/recipes/button/template.html": "sha256-FfylFZ+qzMUFxQKnIdqJiYmC8p4F+cNxK8BJSTo8XU8=", "exports/recipes/button/tokens.css": "sha256-a/TLRGPaqlzicffxz3q5+tWHlvaJ9h78GE1mHVxzp/s=", "exports/recipes/button/two-instances.html": "sha256-SUuvR3ZxzWymDnwkF8BdP321ok8G/grt3ePxGLLUBS4=", "exports/recipes/dialog/LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "exports/recipes/dialog/README.md": "sha256-JtVWLmJ6VdsYRA9228KVpvrqV8PdIsYeyo8w2Vm0DOM=", + "exports/recipes/dialog/README.md": "sha256-T44tU7Fu0So7yLDTqXIQiMEI1vUkGQ+EBrivHsdJAJ4=", "exports/recipes/dialog/component.css": "sha256-Q2j1S57IHrXP3j0VijKinSjdfBgbr6nkFZHrFbkmNaI=", "exports/recipes/dialog/example.html": "sha256-4W9jw4/GPrhd2VhxlZXF91t2yanib4VIWbJ18XomB0I=", "exports/recipes/dialog/foundation.css": "sha256-gItmMJgxTkuTe8+9G3aZQviwGcJ5cQaNANEvpcyOA88=", - "exports/recipes/dialog/manifest.json": "sha256-ICAb4/dJetXL173dvIYPXJ3XTZbrK5s0tRW/Ky5hH7Q=", + "exports/recipes/dialog/manifest.json": "sha256-cp5gMd7bM7+WfQ9PfjhzRT1XQeZP4GMIvKndwAaTcEM=", "exports/recipes/dialog/markup.html": "sha256-o9WIUCRlY5GUbx8+IYfcIv9JJlXBbiJBjb7jUkjNTHE=", "exports/recipes/dialog/template.html": "sha256-ekYfQWlHu6z/dh7Wi1W3GZayMjEjxB5ru5nU7CKIqMg=", "exports/recipes/dialog/tokens.css": "sha256-H4mpfW2luSqCo9S9PPrDgpevuK2OSiXDpp7+a+dFeFw=", "exports/recipes/dialog/two-instances.html": "sha256-KqTTacdBcUnD+k4PYaBYhC74nsIJ1Twu1IOaDjQdoFI=", - "exports/recipes/index.json": "sha256-qU6LheE0yEJ9e3I8OIEt21BR16XPsgxCmpzLoasScjk=", + "exports/recipes/index.json": "sha256-9PLOQxQgWB+aIl4D8IilxyNeKTkXYeVN4oESdy6qqto=", "exports/recipes/text-field/LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "exports/recipes/text-field/README.md": "sha256-IBA7Qgs31PqUxOZM9Pvcdfrq6E0ccMpSHeNnSTvZ1y4=", + "exports/recipes/text-field/README.md": "sha256-swGGwaxEAOAAEmQ88V8fTgnbMDZQvAxsi2ImSBfq0xk=", "exports/recipes/text-field/component.css": "sha256-VgGNE3+NVtPUYTJf02aIPHq3JrH5EGckSbwQealUEwU=", "exports/recipes/text-field/example.html": "sha256-OT8OHppA6ssLf5OlKXOIqPBdkCDLa9lXaqsUOtT1SyQ=", "exports/recipes/text-field/foundation.css": "sha256-gItmMJgxTkuTe8+9G3aZQviwGcJ5cQaNANEvpcyOA88=", - "exports/recipes/text-field/manifest.json": "sha256-hG79YUgUPrJHUwebcbJWobszHhgVqfqG1XOBASdFG6Q=", + "exports/recipes/text-field/manifest.json": "sha256-aII45uw5u0dd8SRAcV9tBGN0BvhQGOgdbLMom9NrW+U=", "exports/recipes/text-field/markup.html": "sha256-O4CmIRb2RUPigpgQAcre9bSpIRJxN52MMxJW4fTyhpM=", "exports/recipes/text-field/template.html": "sha256-IlSlLS7sPC3MLqIdxMRQUP4sFnn/58lwM3AFALtdY3c=", "exports/recipes/text-field/tokens.css": "sha256-EqSdsrQqs1NJVLFBDmxFtT0mbcjOiUeAx1G9cTcdpIY=", "exports/recipes/text-field/two-instances.html": "sha256-Abep8m5/si0kuUu3cVGEVzcHqMN1pHkPazmjloND8J0=", - "exports/task-inputs.json": "sha256-MBZr389Gyb8TZfN67iZgvZVQdPziFp2Y252NgbhaLoI=", + "exports/task-inputs.json": "sha256-ODIRa8+oRozEQGQ1irBdohesPEoxTFddjNwvSIakZ9k=", "exports/theme.compact.md": "sha256-jrEVDKhdwd24OJBek75+xuGzGoxkykr4U1pjkI5sadQ=", "exports/theme.full.md": "sha256-vPkn4TtelDvQpwKcvJYx0ROwyHh2QwvuuFvL6Tn7+xI=", "exports/token-usage.json": "sha256-a1rYc+D6as/OKhMIp1zkGNWMvTXGSuwI6SbU1VNTcKA=", diff --git a/exports/recipes/button/README.md b/exports/recipes/button/README.md index b93f3284e..f4b728ecb 100644 --- a/exports/recipes/button/README.md +++ b/exports/recipes/button/README.md @@ -2,7 +2,7 @@ j3w1 theme 4.0.0. Markup adapted from j3w1 UI Theme Spec, https://github.com/j3w1/theme, CC BY 4.0: https://creativecommons.org/licenses/by/4.0/. Changes: scoped instance IDs and documentation-only content removed. CSS and generator: MIT; see LICENSE.md. -Version 4.0.0; profile default; source digest sha256-hOIrvGlqp/Z7O1QGYmAJCA5koRmhBBdkctoKbof/hOU=. Pin the supplying commit and verify manifest source/file digests; the version alone does not identify a revision. +Version 4.0.0; profile default; source digest sha256-/ZLOjXCpek5b48Y5JSurOzmKzqraPVTf4KS6+mP2x4M=. Pin the supplying commit and verify manifest source/file digests; the version alone does not identify a revision. Open example.html directly, without Astro, network assets or a build step. two-instances.html demonstrates independent IDs. For integration, include tokens.css, foundation.css and component.css in that order, then markup.html. Keep .j3w1-recipe and data-density on the wrapper. The source viewer can make a fresh instance prefix; use a unique prefix for every copy and rewrite all ID references together. diff --git a/exports/recipes/button/manifest.json b/exports/recipes/button/manifest.json index 09b2efb9d..134993d08 100644 --- a/exports/recipes/button/manifest.json +++ b/exports/recipes/button/manifest.json @@ -13,7 +13,7 @@ "scripts/lib/recipe-generator.mjs": "sha256-73WV6IUzUVgC3oyFESbgawkTU9o6mh+rKtZx8HgdZeA=", "scripts/lib/recipe-css.mjs": "sha256-dA/5L61Tsn+Gkmz/syAd689Z5IyuShpluZ1NfgXcZ/c=", "scripts/lib/recipe-markup.mjs": "sha256-pxTFKTEWI1f86ScNw0e2ZfSFkdba5Zs6a7GhmMbIUUQ=", - "scripts/lib/markup.mjs": "sha256-/jd6ncIZAtDpNgML1FKkJn4mFJitU4mSXE9DLLvt2EI=", + "scripts/lib/markup.mjs": "sha256-Q4GrS5/TfnQrne2fRpWZceL3aF1ShKxaf5QWic7Yj4c=", "spec/components/button.md": "sha256-BIJgU88v/JaTsHJF+I64GyX4hw1PWYyB30y+gWG1sAU=", "spec/components/button.demo.html": "sha256-imCfWDUkqdDOF6H8KEdGAw0qejBcHrtPrnyTMxXvpnI=", "site/src/styles/recipe-foundation.css": "sha256-siLjKAkNj84Wa0+Xz5Vf2yj9DT9k0K/Swy/cwHNrvYo=", @@ -23,7 +23,7 @@ "tokens/semantic.tokens.json": "sha256-jbrikW294TIEdB7rAiqlLPAiLUy2CMyLT/opZiVe/E0=", "tokens/foundations.tokens.json": "sha256-e5OLoStuVryktzLt5O1yFmTb1CR3DcgqccWy5SdB2fw=" }, - "digest": "sha256-hOIrvGlqp/Z7O1QGYmAJCA5koRmhBBdkctoKbof/hOU=", + "digest": "sha256-/ZLOjXCpek5b48Y5JSurOzmKzqraPVTf4KS6+mP2x4M=", "revisionPolicy": "Resolve these paths at the same pinned commit as this manifest. The hosted source viewer identifies its supplying commit; generated source files contain content digests, never a floating revision claim." }, "dependencies": { @@ -394,6 +394,6 @@ "example.html": "sha256-HRSLwap8t93ggusQ8BYoEAE0wPCsBWTKSY+4JGzRNa4=", "two-instances.html": "sha256-SUuvR3ZxzWymDnwkF8BdP321ok8G/grt3ePxGLLUBS4=", "LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "README.md": "sha256-mS8bIWiTXGBfI7igIXsai6GF4p7KlPCfsQvAEFb9fls=" + "README.md": "sha256-3bnwFyaC2y+GHMRGleeDP2VGp3TtThGtzreM6cNsW5I=" } } diff --git a/exports/recipes/dialog/README.md b/exports/recipes/dialog/README.md index 670b6835e..092df6881 100644 --- a/exports/recipes/dialog/README.md +++ b/exports/recipes/dialog/README.md @@ -2,7 +2,7 @@ j3w1 theme 4.0.0. Markup adapted from j3w1 UI Theme Spec, https://github.com/j3w1/theme, CC BY 4.0: https://creativecommons.org/licenses/by/4.0/. Changes: scoped instance IDs and documentation-only content removed. CSS and generator: MIT; see LICENSE.md. -Version 4.0.0; profile default; source digest sha256-rGmI15TyvMxO8spWUF+5eZKe7AY/PEAFRjjtWy4dmbE=. Pin the supplying commit and verify manifest source/file digests; the version alone does not identify a revision. +Version 4.0.0; profile default; source digest sha256-9/hbawzW0wvoyzWaGwhHJ0A1cBgFQAfiWgmiuYNX0mA=. Pin the supplying commit and verify manifest source/file digests; the version alone does not identify a revision. Open example.html directly, without Astro, network assets or a build step. two-instances.html demonstrates independent IDs. For integration, include tokens.css, foundation.css and component.css in that order, then markup.html. Keep .j3w1-recipe and data-density on the wrapper. The source viewer can make a fresh instance prefix; use a unique prefix for every copy and rewrite all ID references together. diff --git a/exports/recipes/dialog/manifest.json b/exports/recipes/dialog/manifest.json index e2151ed90..6d7b87ce1 100644 --- a/exports/recipes/dialog/manifest.json +++ b/exports/recipes/dialog/manifest.json @@ -13,7 +13,7 @@ "scripts/lib/recipe-generator.mjs": "sha256-73WV6IUzUVgC3oyFESbgawkTU9o6mh+rKtZx8HgdZeA=", "scripts/lib/recipe-css.mjs": "sha256-dA/5L61Tsn+Gkmz/syAd689Z5IyuShpluZ1NfgXcZ/c=", "scripts/lib/recipe-markup.mjs": "sha256-pxTFKTEWI1f86ScNw0e2ZfSFkdba5Zs6a7GhmMbIUUQ=", - "scripts/lib/markup.mjs": "sha256-/jd6ncIZAtDpNgML1FKkJn4mFJitU4mSXE9DLLvt2EI=", + "scripts/lib/markup.mjs": "sha256-Q4GrS5/TfnQrne2fRpWZceL3aF1ShKxaf5QWic7Yj4c=", "spec/components/dialog.md": "sha256-zKmPZU3GdJ1IPYbCO6KY7oizbzzKXSdlw3ujXc+R3bE=", "spec/components/dialog.demo.html": "sha256-m9m1JcXKJ5j3f0rxR1fojmkYvtgzUnhgWBPA0iI6cSM=", "site/src/styles/recipe-foundation.css": "sha256-siLjKAkNj84Wa0+Xz5Vf2yj9DT9k0K/Swy/cwHNrvYo=", @@ -23,7 +23,7 @@ "tokens/semantic.tokens.json": "sha256-jbrikW294TIEdB7rAiqlLPAiLUy2CMyLT/opZiVe/E0=", "tokens/foundations.tokens.json": "sha256-e5OLoStuVryktzLt5O1yFmTb1CR3DcgqccWy5SdB2fw=" }, - "digest": "sha256-rGmI15TyvMxO8spWUF+5eZKe7AY/PEAFRjjtWy4dmbE=", + "digest": "sha256-9/hbawzW0wvoyzWaGwhHJ0A1cBgFQAfiWgmiuYNX0mA=", "revisionPolicy": "Resolve these paths at the same pinned commit as this manifest. The hosted source viewer identifies its supplying commit; generated source files contain content digests, never a floating revision claim." }, "dependencies": { @@ -476,6 +476,6 @@ "example.html": "sha256-4W9jw4/GPrhd2VhxlZXF91t2yanib4VIWbJ18XomB0I=", "two-instances.html": "sha256-KqTTacdBcUnD+k4PYaBYhC74nsIJ1Twu1IOaDjQdoFI=", "LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "README.md": "sha256-JtVWLmJ6VdsYRA9228KVpvrqV8PdIsYeyo8w2Vm0DOM=" + "README.md": "sha256-T44tU7Fu0So7yLDTqXIQiMEI1vUkGQ+EBrivHsdJAJ4=" } } diff --git a/exports/recipes/index.json b/exports/recipes/index.json index 9e61e3c5c..24e842b38 100644 --- a/exports/recipes/index.json +++ b/exports/recipes/index.json @@ -7,7 +7,7 @@ "id": "button", "variant": "default", "manifest": "exports/recipes/button/manifest.json", - "sourceDigest": "sha256-hOIrvGlqp/Z7O1QGYmAJCA5koRmhBBdkctoKbof/hOU=", + "sourceDigest": "sha256-/ZLOjXCpek5b48Y5JSurOzmKzqraPVTf4KS6+mP2x4M=", "limitations": [ "Native button activation only; application actions are supplied by the host.", "aria-busy supplies the loading appearance; the host must suppress repeated activation while busy." @@ -17,7 +17,7 @@ "id": "text-field", "variant": "default", "manifest": "exports/recipes/text-field/manifest.json", - "sourceDigest": "sha256-iO7O5tqk4cxfEtjsWh8120uVrqnkvliv37lngYjJXvw=", + "sourceDigest": "sha256-L10k89v67IeR5ts+lBZ57ZzArKT9BUJC3T2u2fWEMvA=", "limitations": [ "Native text editing only; validation messages and aria-invalid are managed by the host.", "The default text variant is packaged. Password reveal, search clearing and number steppers are not implemented." @@ -27,7 +27,7 @@ "id": "dialog", "variant": "default", "manifest": "exports/recipes/dialog/manifest.json", - "sourceDigest": "sha256-rGmI15TyvMxO8spWUF+5eZKe7AY/PEAFRjjtWy4dmbE=", + "sourceDigest": "sha256-9/hbawzW0wvoyzWaGwhHJ0A1cBgFQAfiWgmiuYNX0mA=", "limitations": [ "Visual-only: the native dialog is open in normal flow with a simulated backdrop.", "No showModal, focus trap, Escape handling, close actions or focus return is supplied. The host owns the complete modal lifecycle and positioning.", diff --git a/exports/recipes/text-field/README.md b/exports/recipes/text-field/README.md index 8f7021cfc..0941c0305 100644 --- a/exports/recipes/text-field/README.md +++ b/exports/recipes/text-field/README.md @@ -2,7 +2,7 @@ j3w1 theme 4.0.0. Markup adapted from j3w1 UI Theme Spec, https://github.com/j3w1/theme, CC BY 4.0: https://creativecommons.org/licenses/by/4.0/. Changes: scoped instance IDs and documentation-only content removed. CSS and generator: MIT; see LICENSE.md. -Version 4.0.0; profile default; source digest sha256-iO7O5tqk4cxfEtjsWh8120uVrqnkvliv37lngYjJXvw=. Pin the supplying commit and verify manifest source/file digests; the version alone does not identify a revision. +Version 4.0.0; profile default; source digest sha256-L10k89v67IeR5ts+lBZ57ZzArKT9BUJC3T2u2fWEMvA=. Pin the supplying commit and verify manifest source/file digests; the version alone does not identify a revision. Open example.html directly, without Astro, network assets or a build step. two-instances.html demonstrates independent IDs. For integration, include tokens.css, foundation.css and component.css in that order, then markup.html. Keep .j3w1-recipe and data-density on the wrapper. The source viewer can make a fresh instance prefix; use a unique prefix for every copy and rewrite all ID references together. diff --git a/exports/recipes/text-field/manifest.json b/exports/recipes/text-field/manifest.json index c1d318365..366a5dbc9 100644 --- a/exports/recipes/text-field/manifest.json +++ b/exports/recipes/text-field/manifest.json @@ -13,7 +13,7 @@ "scripts/lib/recipe-generator.mjs": "sha256-73WV6IUzUVgC3oyFESbgawkTU9o6mh+rKtZx8HgdZeA=", "scripts/lib/recipe-css.mjs": "sha256-dA/5L61Tsn+Gkmz/syAd689Z5IyuShpluZ1NfgXcZ/c=", "scripts/lib/recipe-markup.mjs": "sha256-pxTFKTEWI1f86ScNw0e2ZfSFkdba5Zs6a7GhmMbIUUQ=", - "scripts/lib/markup.mjs": "sha256-/jd6ncIZAtDpNgML1FKkJn4mFJitU4mSXE9DLLvt2EI=", + "scripts/lib/markup.mjs": "sha256-Q4GrS5/TfnQrne2fRpWZceL3aF1ShKxaf5QWic7Yj4c=", "spec/components/text-field.md": "sha256-nLOL2IloE3AKZ7EqGA0iIBUVuEZf+iVcTJcBn0x8y2Y=", "spec/components/text-field.demo.html": "sha256-ZB5xDObbSUC3QCuqccJpd3EmQ5YJQhJ74BCTur+xwa4=", "site/src/styles/recipe-foundation.css": "sha256-siLjKAkNj84Wa0+Xz5Vf2yj9DT9k0K/Swy/cwHNrvYo=", @@ -23,7 +23,7 @@ "tokens/semantic.tokens.json": "sha256-jbrikW294TIEdB7rAiqlLPAiLUy2CMyLT/opZiVe/E0=", "tokens/foundations.tokens.json": "sha256-e5OLoStuVryktzLt5O1yFmTb1CR3DcgqccWy5SdB2fw=" }, - "digest": "sha256-iO7O5tqk4cxfEtjsWh8120uVrqnkvliv37lngYjJXvw=", + "digest": "sha256-L10k89v67IeR5ts+lBZ57ZzArKT9BUJC3T2u2fWEMvA=", "revisionPolicy": "Resolve these paths at the same pinned commit as this manifest. The hosted source viewer identifies its supplying commit; generated source files contain content digests, never a floating revision claim." }, "dependencies": { @@ -359,6 +359,6 @@ "example.html": "sha256-OT8OHppA6ssLf5OlKXOIqPBdkCDLa9lXaqsUOtT1SyQ=", "two-instances.html": "sha256-Abep8m5/si0kuUu3cVGEVzcHqMN1pHkPazmjloND8J0=", "LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "README.md": "sha256-IBA7Qgs31PqUxOZM9Pvcdfrq6E0ccMpSHeNnSTvZ1y4=" + "README.md": "sha256-swGGwaxEAOAAEmQ88V8fTgnbMDZQvAxsi2ImSBfq0xk=" } } diff --git a/exports/task-inputs.json b/exports/task-inputs.json index f23f72100..7840a109e 100644 --- a/exports/task-inputs.json +++ b/exports/task-inputs.json @@ -1076,9 +1076,9 @@ "exports/recipes/button/example.html": "sha256-HRSLwap8t93ggusQ8BYoEAE0wPCsBWTKSY+4JGzRNa4=", "exports/recipes/button/foundation.css": "sha256-gItmMJgxTkuTe8+9G3aZQviwGcJ5cQaNANEvpcyOA88=", "exports/recipes/button/LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "exports/recipes/button/manifest.json": "sha256-AA++frM2He0KhcMDOlEUKBy7S82fbjAvkWU7QAA69uc=", + "exports/recipes/button/manifest.json": "sha256-2rzEGNy89Z3MLwmbhF6b+bpO0/TAEBnjfWN2A9DhQWA=", "exports/recipes/button/markup.html": "sha256-9HjLJ98lH4SKiwVWynQKarCqWTK/+IKfcvGr6464P3c=", - "exports/recipes/button/README.md": "sha256-mS8bIWiTXGBfI7igIXsai6GF4p7KlPCfsQvAEFb9fls=", + "exports/recipes/button/README.md": "sha256-3bnwFyaC2y+GHMRGleeDP2VGp3TtThGtzreM6cNsW5I=", "exports/recipes/button/template.html": "sha256-FfylFZ+qzMUFxQKnIdqJiYmC8p4F+cNxK8BJSTo8XU8=", "exports/recipes/button/tokens.css": "sha256-a/TLRGPaqlzicffxz3q5+tWHlvaJ9h78GE1mHVxzp/s=", "exports/recipes/button/two-instances.html": "sha256-SUuvR3ZxzWymDnwkF8BdP321ok8G/grt3ePxGLLUBS4=", @@ -1086,9 +1086,9 @@ "exports/recipes/dialog/example.html": "sha256-4W9jw4/GPrhd2VhxlZXF91t2yanib4VIWbJ18XomB0I=", "exports/recipes/dialog/foundation.css": "sha256-gItmMJgxTkuTe8+9G3aZQviwGcJ5cQaNANEvpcyOA88=", "exports/recipes/dialog/LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "exports/recipes/dialog/manifest.json": "sha256-ICAb4/dJetXL173dvIYPXJ3XTZbrK5s0tRW/Ky5hH7Q=", + "exports/recipes/dialog/manifest.json": "sha256-cp5gMd7bM7+WfQ9PfjhzRT1XQeZP4GMIvKndwAaTcEM=", "exports/recipes/dialog/markup.html": "sha256-o9WIUCRlY5GUbx8+IYfcIv9JJlXBbiJBjb7jUkjNTHE=", - "exports/recipes/dialog/README.md": "sha256-JtVWLmJ6VdsYRA9228KVpvrqV8PdIsYeyo8w2Vm0DOM=", + "exports/recipes/dialog/README.md": "sha256-T44tU7Fu0So7yLDTqXIQiMEI1vUkGQ+EBrivHsdJAJ4=", "exports/recipes/dialog/template.html": "sha256-ekYfQWlHu6z/dh7Wi1W3GZayMjEjxB5ru5nU7CKIqMg=", "exports/recipes/dialog/tokens.css": "sha256-H4mpfW2luSqCo9S9PPrDgpevuK2OSiXDpp7+a+dFeFw=", "exports/recipes/dialog/two-instances.html": "sha256-KqTTacdBcUnD+k4PYaBYhC74nsIJ1Twu1IOaDjQdoFI=", @@ -1096,9 +1096,9 @@ "exports/recipes/text-field/example.html": "sha256-OT8OHppA6ssLf5OlKXOIqPBdkCDLa9lXaqsUOtT1SyQ=", "exports/recipes/text-field/foundation.css": "sha256-gItmMJgxTkuTe8+9G3aZQviwGcJ5cQaNANEvpcyOA88=", "exports/recipes/text-field/LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "exports/recipes/text-field/manifest.json": "sha256-hG79YUgUPrJHUwebcbJWobszHhgVqfqG1XOBASdFG6Q=", + "exports/recipes/text-field/manifest.json": "sha256-aII45uw5u0dd8SRAcV9tBGN0BvhQGOgdbLMom9NrW+U=", "exports/recipes/text-field/markup.html": "sha256-O4CmIRb2RUPigpgQAcre9bSpIRJxN52MMxJW4fTyhpM=", - "exports/recipes/text-field/README.md": "sha256-IBA7Qgs31PqUxOZM9Pvcdfrq6E0ccMpSHeNnSTvZ1y4=", + "exports/recipes/text-field/README.md": "sha256-swGGwaxEAOAAEmQ88V8fTgnbMDZQvAxsi2ImSBfq0xk=", "exports/recipes/text-field/template.html": "sha256-IlSlLS7sPC3MLqIdxMRQUP4sFnn/58lwM3AFALtdY3c=", "exports/recipes/text-field/tokens.css": "sha256-EqSdsrQqs1NJVLFBDmxFtT0mbcjOiUeAx1G9cTcdpIY=", "exports/recipes/text-field/two-instances.html": "sha256-Abep8m5/si0kuUu3cVGEVzcHqMN1pHkPazmjloND8J0=", diff --git a/packages/ui/README.md b/packages/ui/README.md index 42883d217..82f031a99 100644 --- a/packages/ui/README.md +++ b/packages/ui/README.md @@ -25,9 +25,11 @@ complete maintained markup on the component's page. Keep the exact package version and your package-manager lockfile in source control. + ```sh -npm install --save-exact @j3w1/ui@3.1.0 +npm install --save-exact @j3w1/ui@4.0.0 ``` + That command needs npm publication, which is an owner release action. Before publication: @@ -36,9 +38,11 @@ publication: 2. Check it against its published digest. 3. Install the local file: + ```sh -npm install --save-exact ./j3w1-ui-3.1.0.tgz +npm install --save-exact ./j3w1-ui-4.0.0.tgz ``` + The repository builds this same artifact with `npm run ui:build` and `npm run ui:pack`. Never use a branch URL in place of a release pin. Do not @@ -252,10 +256,12 @@ Styling: ## Copy a complete bundle + ```sh -npx --package=@j3w1/ui@3.1.0 j3w1-ui copy dialog --out ./vendor/j3w1/dialog -npx --package=@j3w1/ui@3.1.0 j3w1-ui kit --components text-field,button,dialog --out ./vendor/j3w1/task +npx --package=@j3w1/ui@4.0.0 j3w1-ui copy dialog --out ./vendor/j3w1/dialog +npx --package=@j3w1/ui@4.0.0 j3w1-ui kit --components text-field,button,dialog --out ./vendor/j3w1/task ``` + - Installed from a tarball: run the installed `j3w1-ui` binary instead of npx. - The CLI checks all source bytes before it writes. It rejects unknown components diff --git a/packages/ui/dist/chunks/advanced-DCpe8Ndv.js b/packages/ui/dist/chunks/advanced-CqBF0dSb.js similarity index 97% rename from packages/ui/dist/chunks/advanced-DCpe8Ndv.js rename to packages/ui/dist/chunks/advanced-CqBF0dSb.js index 3390a044c..4a5c45981 100644 --- a/packages/ui/dist/chunks/advanced-DCpe8Ndv.js +++ b/packages/ui/dist/chunks/advanced-CqBF0dSb.js @@ -1,4 +1,4 @@ -import { d as rove, f as visible, i as all, l as nativeInput, o as enabled, s as identify } from "./choice-Db_w_BOQ.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-B7mo5Eq3.js"; import { t as IDREFS } from "./markup-DeQ4bEMR.js"; //#region packages/ui/src/behaviors/advanced.js function tree(root, { on }) { @@ -64,7 +64,12 @@ function tree(root, { on }) { "End" ].includes(event.key)) { event.preventDefault(); - const next = event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : Math.max(0, Math.min(options.length - 1, index + (event.key === "ArrowDown" ? 1 : -1))); + const next = keyIndex({ + key: event.key, + index, + length: options.length, + wrap: false + }); rove(options, next); } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight")) { event.preventDefault(); diff --git a/packages/ui/dist/copy/admin-form/runtime/chunks/choice-Db_w_BOQ.js b/packages/ui/dist/chunks/choice-B7mo5Eq3.js similarity index 98% rename from packages/ui/dist/copy/admin-form/runtime/chunks/choice-Db_w_BOQ.js rename to packages/ui/dist/chunks/choice-B7mo5Eq3.js index aebc478b6..849c80b8b 100644 --- a/packages/ui/dist/copy/admin-form/runtime/chunks/choice-Db_w_BOQ.js +++ b/packages/ui/dist/chunks/choice-B7mo5Eq3.js @@ -31,6 +31,12 @@ function identify(root, node, suffix) { 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]; @@ -929,4 +935,4 @@ function enhanceControls(root) { }; } //#endregion -export { announce as a, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; +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-d6BkKTYf.js b/packages/ui/dist/chunks/compositions-D57dCsBz.js similarity index 94% rename from packages/ui/dist/copy/i3-window-frame/runtime/chunks/compositions-d6BkKTYf.js rename to packages/ui/dist/chunks/compositions-D57dCsBz.js index 7d70275f2..f1da4562e 100644 --- a/packages/ui/dist/copy/i3-window-frame/runtime/chunks/compositions-d6BkKTYf.js +++ b/packages/ui/dist/chunks/compositions-D57dCsBz.js @@ -1,5 +1,5 @@ -import { i as all, o as enabled } from "./choice-Db_w_BOQ.js"; -import { i as tabs } from "./navigation-Dt8ap-9J.js"; +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 function fileBrowser(root, { on }) { const query = root.querySelector("[data-file-query]"), rows = all(root, "tr[data-file-id]"), status = root.querySelector("[data-file-status]"); diff --git a/packages/ui/dist/copy/chart/runtime/chunks/display-dj9YaBfn.js b/packages/ui/dist/chunks/display-Jm9bAsnb.js similarity index 98% rename from packages/ui/dist/copy/chart/runtime/chunks/display-dj9YaBfn.js rename to packages/ui/dist/chunks/display-Jm9bAsnb.js index 80833d5da..5bc817830 100644 --- a/packages/ui/dist/copy/chart/runtime/chunks/display-dj9YaBfn.js +++ b/packages/ui/dist/chunks/display-Jm9bAsnb.js @@ -1,4 +1,4 @@ -import { c as make, i as all, o as enabled } from "./choice-Db_w_BOQ.js"; +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]"); diff --git a/packages/ui/dist/copy/alert/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/chunks/element-Dovcr9Ky.js similarity index 99% rename from packages/ui/dist/copy/alert/runtime/chunks/element-C1XeXVYC.js rename to packages/ui/dist/chunks/element-Dovcr9Ky.js index a943f150d..aa7a67cb4 100644 --- a/packages/ui/dist/copy/alert/runtime/chunks/element-C1XeXVYC.js +++ b/packages/ui/dist/chunks/element-Dovcr9Ky.js @@ -1,4 +1,4 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.js"; +import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; //#region packages/ui/src/internal/element.js var HTMLElementBase = globalThis.HTMLElement ?? class {}; var nextInstance = 0; diff --git a/packages/ui/dist/chunks/form-builder-C6Rhfsz6.js b/packages/ui/dist/chunks/form-builder-C4avSOze.js similarity index 92% rename from packages/ui/dist/chunks/form-builder-C6Rhfsz6.js rename to packages/ui/dist/chunks/form-builder-C4avSOze.js index 2daa2e07f..c7ad23898 100644 --- a/packages/ui/dist/chunks/form-builder-C6Rhfsz6.js +++ b/packages/ui/dist/chunks/form-builder-C4avSOze.js @@ -1,4 +1,4 @@ -import { t as J3w1Element } from "./element-C1XeXVYC.js"; +import { t as J3w1Element } from "./element-Dovcr9Ky.js"; import { t as mountBuilder } from "./form-builder-C5Kx5G9b.js"; //#region packages/ui/src/behaviors/form-builder.js function formBuilder(root, { signal }) { @@ -22,7 +22,7 @@ function formBuilder(root, { signal }) { var J3w1FormBuilder = class extends J3w1Element { static componentId = "form-builder"; static version = "4.0.0"; - static implementationId = "sha256-uXS+kL7KbvfhlApDhEsvMY+pFsX9bHFlaTF/qUH94mE="; + static implementationId = "sha256-KhHbbANV3xzXIk57mZCL5Uw2aiN4jVv4u4xeVhDxSwU="; static connect = formBuilder; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/copy/settings-panel/runtime/chunks/forms-BT3z7lNC.js b/packages/ui/dist/chunks/forms-CE_hP1hg.js similarity index 98% rename from packages/ui/dist/copy/settings-panel/runtime/chunks/forms-BT3z7lNC.js rename to packages/ui/dist/chunks/forms-CE_hP1hg.js index 65f1f0e71..6ad3b48f5 100644 --- a/packages/ui/dist/copy/settings-panel/runtime/chunks/forms-BT3z7lNC.js +++ b/packages/ui/dist/chunks/forms-CE_hP1hg.js @@ -1,4 +1,4 @@ -import { c as make, i as all, o as enabled } from "./choice-Db_w_BOQ.js"; +import { i as all, l as make, o as enabled } from "./choice-B7mo5Eq3.js"; //#region 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"); diff --git a/packages/ui/dist/copy/badge/runtime/chunks/native-CAzZmDKR.js b/packages/ui/dist/chunks/native-BjBt1sUh.js similarity index 98% rename from packages/ui/dist/copy/badge/runtime/chunks/native-CAzZmDKR.js rename to packages/ui/dist/chunks/native-BjBt1sUh.js index 558c774e5..032f76c74 100644 --- a/packages/ui/dist/copy/badge/runtime/chunks/native-CAzZmDKR.js +++ b/packages/ui/dist/chunks/native-BjBt1sUh.js @@ -1,4 +1,4 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.js"; +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 {}; diff --git a/packages/ui/dist/copy/compact-dashboard/runtime/chunks/navigation-Dt8ap-9J.js b/packages/ui/dist/chunks/navigation-BfNzDYZB.js similarity index 96% rename from packages/ui/dist/copy/compact-dashboard/runtime/chunks/navigation-Dt8ap-9J.js rename to packages/ui/dist/chunks/navigation-BfNzDYZB.js index 81201c8d5..db2779553 100644 --- a/packages/ui/dist/copy/compact-dashboard/runtime/chunks/navigation-Dt8ap-9J.js +++ b/packages/ui/dist/chunks/navigation-BfNzDYZB.js @@ -1,4 +1,4 @@ -import { a as announce, d as rove, f as visible, i as all, l as nativeInput, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.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-B7mo5Eq3.js"; //#region packages/ui/src/behaviors/navigation.js function tabs(root, { on }, listOverride) { const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); @@ -81,7 +81,13 @@ function toolbar(root, { on }) { "End" ].includes(event.key)) return; event.preventDefault(); - rove(items, event.key === next ? index + 1 : event.key === prev ? index - 1 : event.key === "Home" ? 0 : items.length - 1); + 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]"); @@ -321,7 +327,11 @@ function menu(root, { on }) { "End" ].includes(event.key)) { event.preventDefault(); - rove(options, event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : index + (event.key === "ArrowDown" ? 1 : -1)); + 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(); diff --git a/packages/ui/dist/copy/chip/runtime/chunks/overlays-C6nlCHqg.js b/packages/ui/dist/chunks/overlays-Bw8SSDKz.js similarity index 98% rename from packages/ui/dist/copy/chip/runtime/chunks/overlays-C6nlCHqg.js rename to packages/ui/dist/chunks/overlays-Bw8SSDKz.js index 9df8503ec..3eeb8ff0d 100644 --- a/packages/ui/dist/copy/chip/runtime/chunks/overlays-C6nlCHqg.js +++ b/packages/ui/dist/chunks/overlays-Bw8SSDKz.js @@ -1,4 +1,4 @@ -import { i as all, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.js"; +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"); diff --git a/packages/ui/dist/copy/data-table/runtime/chunks/tables-B25ydUHs.js b/packages/ui/dist/chunks/tables-Cjr1EIJz.js similarity index 96% rename from packages/ui/dist/copy/data-table/runtime/chunks/tables-B25ydUHs.js rename to packages/ui/dist/chunks/tables-Cjr1EIJz.js index 172bab830..f82aaf25e 100644 --- a/packages/ui/dist/copy/data-table/runtime/chunks/tables-B25ydUHs.js +++ b/packages/ui/dist/chunks/tables-Cjr1EIJz.js @@ -1,4 +1,4 @@ -import { d as rove, i as all, o as enabled, s as identify } from "./choice-Db_w_BOQ.js"; +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]; @@ -106,7 +106,12 @@ function table(root, { on }) { "End" ].includes(event.key)) return; event.preventDefault(); - const nextIndex = event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : Math.max(0, Math.min(options.length - 1, index + (event.key === "ArrowDown" ? 1 : -1))); + const nextIndex = keyIndex({ + key: event.key, + index, + length: options.length, + wrap: false + }); const next = rove(options, nextIndex); if (event.shiftKey && selectAll) { anchor ??= row; diff --git a/packages/ui/dist/components/admin-form.js b/packages/ui/dist/components/admin-form.js index bb59750d7..f786258d5 100644 --- a/packages/ui/dist/components/admin-form.js +++ b/packages/ui/dist/components/admin-form.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { t as formComposition } from "../chunks/forms-BT3z7lNC.js"; +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 var J3w1AdminForm = class extends J3w1Element { static componentId = "admin-form"; static version = "4.0.0"; - static implementationId = "sha256-IZWHSSA/uP7yDRqpiKJQsQ05FssMem3lg++QYnGPtDM="; + static implementationId = "sha256-86V5kk3lZt3iA5GdiMBYc8P2mc4pO3KTo02FmkKh71k="; static connect = formComposition; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/alert.js b/packages/ui/dist/components/alert.js index 24171f944..6c6db1b50 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-C1XeXVYC.js"; -import { t as feedback } from "../chunks/overlays-C6nlCHqg.js"; +import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; +import { t as feedback } from "../chunks/overlays-Bw8SSDKz.js"; //#region .cache/ui-build/entries/components/alert.js var J3w1Alert = class extends J3w1Element { static componentId = "alert"; static version = "4.0.0"; - static implementationId = "sha256-D/UE6iF8Es5ira9X/X3Hlo5OO/Lzy3n/9s9vlkV7zJU="; + static implementationId = "sha256-6Wo+BnYA6udYTk6XDw6PR9MtJYx0FznliTgiGt+lVxo="; static connect = feedback; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/avatar.js b/packages/ui/dist/components/avatar.js index e173006c6..39f8bb7e4 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-C1XeXVYC.js"; -import { t as avatar } from "../chunks/display-dj9YaBfn.js"; +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 var J3w1Avatar = class extends J3w1Element { static componentId = "avatar"; static version = "4.0.0"; - static implementationId = "sha256-oKaTLRzIK5qK9lvYH/WxVObpYJISyDSenNJcmBSIbAE="; + static implementationId = "sha256-y5w6c1MQTafVvxzhJ5TzYxwGvju264CUxS2D23RvGCQ="; static connect = avatar; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/badge.js b/packages/ui/dist/components/badge.js index 75cd2918a..640dfde53 100644 --- a/packages/ui/dist/components/badge.js +++ b/packages/ui/dist/components/badge.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Badge = class extends J3w1Element { static componentId = "badge"; static version = "4.0.0"; - static implementationId = "sha256-7r4xdzZloUX+vqRo4Hc0GjD4Kj3pwVOKBfHyGYFV4fU="; + static implementationId = "sha256-4j+faVdrUDtcCc6a5/1Y+y9U30DXfpq/Frm/Z0bO1i8="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/breadcrumbs.js b/packages/ui/dist/components/breadcrumbs.js index 8c0afe607..5ce93d88b 100644 --- a/packages/ui/dist/components/breadcrumbs.js +++ b/packages/ui/dist/components/breadcrumbs.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as disclosure } from "../chunks/navigation-Dt8ap-9J.js"; +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 var J3w1Breadcrumbs = class extends J3w1Element { static componentId = "breadcrumbs"; static version = "4.0.0"; - static implementationId = "sha256-87YN9cPa7cDF4Ft74THtpIUQxKKqJQXA7fCZzmQ5DwA="; + static implementationId = "sha256-9uiBLPIbEVI200s39xDO7x0K09v+wPg5xcoMI5B5TbY="; static connect = disclosure; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/button-group.js b/packages/ui/dist/components/button-group.js index aaa99816c..e5443b0f9 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-C1XeXVYC.js"; -import { t as actions } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1ButtonGroup = class extends J3w1Element { static componentId = "button-group"; static version = "4.0.0"; - static implementationId = "sha256-4nMwz9kpZ4odBRA12jsDZ86Fx+dDkBCJD7OkQHdIGDY="; + static implementationId = "sha256-QC6YHzPpUytpyeDknjyX9Ke/akglG1NzBtJnCYjqgaA="; static connect = actions; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...[ diff --git a/packages/ui/dist/components/button.js b/packages/ui/dist/components/button.js index 13b2ecc87..3dfd4d373 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-C1XeXVYC.js"; -import { t as actions } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Button = class extends J3w1Element { static componentId = "button"; static version = "4.0.0"; - static implementationId = "sha256-KJsije7hrwEBTy2GsHhegHPN50aD1js7EUW9wwGysM4="; + static implementationId = "sha256-5XqIG0jRl2EIptqWgZIiuSKdNf0pHpMOZB14A1W3DqU="; static connect = actions; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...[ diff --git a/packages/ui/dist/components/card.js b/packages/ui/dist/components/card.js index a5ee729a4..9981d665b 100644 --- a/packages/ui/dist/components/card.js +++ b/packages/ui/dist/components/card.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Card = class extends J3w1Element { static componentId = "card"; static version = "4.0.0"; - static implementationId = "sha256-vQnfoIzeMEvjY3vf6ySomBbeDdh5YPzSMoXDvmtgOro="; + static implementationId = "sha256-1zEhR7grQaSCkJEXxbq66aFLUPYuFPcwf/JnBD3tNdQ="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/chart.js b/packages/ui/dist/components/chart.js index 2f3f33b51..70d90b671 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-C1XeXVYC.js"; -import { n as chart } from "../chunks/display-dj9YaBfn.js"; +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 var J3w1Chart = class extends J3w1Element { static componentId = "chart"; static version = "4.0.0"; - static implementationId = "sha256-HoAvhRRdFv6zYSIR6McpxJvYeGHHbg4t1zBpi2x1EXo="; + static implementationId = "sha256-48dT14XNNF9ZyV4PB4oLs8zT/lNQqNt9rXZCl9gUYVc="; static connect = chart; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/checkbox.js b/packages/ui/dist/components/checkbox.js index 508ce70fe..8d7e19060 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Checkbox = class extends J3w1Element { static componentId = "checkbox"; static version = "4.0.0"; - static implementationId = "sha256-s8QNllrpQfjPHm0Utgbm9jpMpGxi8Z+bEb83jPZVomQ="; + static implementationId = "sha256-Izbz5fVyhrSfF5rLvCHcElWnQgwhYuvOSm5StKMlqUg="; static connect = fields; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/chip.js b/packages/ui/dist/components/chip.js index 4f4800574..749a8cf86 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-C1XeXVYC.js"; -import { t as feedback } from "../chunks/overlays-C6nlCHqg.js"; +import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; +import { t as feedback } from "../chunks/overlays-Bw8SSDKz.js"; //#region .cache/ui-build/entries/components/chip.js var J3w1Chip = class extends J3w1Element { static componentId = "chip"; static version = "4.0.0"; - static implementationId = "sha256-WS0ZeKkxMPrlmT3er+h8PDDvz5rjH0e3bLmPLD+4egE="; + static implementationId = "sha256-AQdMwG6TMuURDhU/UWs7oHW2L2skw4ISgrH4cwOomvk="; static connect = feedback; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/code-editor.js b/packages/ui/dist/components/code-editor.js index 5d700d661..9a989eb60 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-C1XeXVYC.js"; -import { r as developerView } from "../chunks/display-dj9YaBfn.js"; +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 var J3w1CodeEditor = class extends J3w1Element { static componentId = "code-editor"; static version = "4.0.0"; - static implementationId = "sha256-SfbKlWOepDm9juxt9BZYRBuYIPkdwFye18Fx+JebtX8="; + static implementationId = "sha256-BBPVGsJGf2n0c4gfyDdfHQH3KYYqmiAAqqC2h3DlIcc="; static connect = developerView; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/combobox.js b/packages/ui/dist/components/combobox.js index 1f90d0d0a..098363263 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-C1XeXVYC.js"; -import { t as combobox } from "../chunks/navigation-Dt8ap-9J.js"; +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 var J3w1Combobox = class extends J3w1Element { static componentId = "combobox"; static version = "4.0.0"; - static implementationId = "sha256-XA3Nl+ZVgrypCgx4FjdKKQnMCNyoA+F8ID8i2Tjo8lY="; + static implementationId = "sha256-vBw1BDsNiy6oYSbmjgh7x2T+43b2GYa+XmHte/upgpQ="; static connect = combobox; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/command-palette.js b/packages/ui/dist/components/command-palette.js index 9f69c3926..196ad7f12 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-C1XeXVYC.js"; -import { t as commandPalette } from "../chunks/advanced-DCpe8Ndv.js"; +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 var J3w1CommandPalette = class extends J3w1Element { static componentId = "command-palette"; static version = "4.0.0"; - static implementationId = "sha256-z/FYgCRAmaHrY3I9P3qJz8fOSSDfrjxFjAqwEVhzk50="; + static implementationId = "sha256-jnhxb+w/Xgrb5Os9Dxr1YHn/ex7fLJlGLSWZSpbrAuU="; static connect = commandPalette; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/compact-dashboard.js b/packages/ui/dist/components/compact-dashboard.js index dd2296be0..b29237379 100644 --- a/packages/ui/dist/components/compact-dashboard.js +++ b/packages/ui/dist/components/compact-dashboard.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { t as dashboard } from "../chunks/compositions-d6BkKTYf.js"; +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 var J3w1CompactDashboard = class extends J3w1Element { static componentId = "compact-dashboard"; static version = "4.0.0"; - static implementationId = "sha256-HehbhZc0CAfJPPd19KsqWamAD2EgvREZQU0pBPncnJI="; + static implementationId = "sha256-Shp675PVGMGOiXxiKpeWEQHQugGKEIbNO/jz8KwP4m0="; static connect = dashboard; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/data-table.js b/packages/ui/dist/components/data-table.js index 79b133ce4..2825525ad 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-C1XeXVYC.js"; -import { n as table } from "../chunks/tables-B25ydUHs.js"; +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 var J3w1DataTable = class extends J3w1Element { static componentId = "data-table"; static version = "4.0.0"; - static implementationId = "sha256-QMe+oF071lb63bTNZ9n1ib/8bWgy27tciSjWJEfBgrk="; + static implementationId = "sha256-Qlh9cF0ylT3FE8z6iBYaA9/noI1T5dVrNgulqEfZGt8="; static connect = table; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/date-picker.js b/packages/ui/dist/components/date-picker.js index b75f98455..df35db9b0 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1DatePicker = class extends J3w1Element { static componentId = "date-picker"; static version = "4.0.0"; - static implementationId = "sha256-c14aNjkp318olUOl5+cdRlcdDahvWoTp8lk0sI48z1Y="; + static implementationId = "sha256-rz3at5sJTA4TkXHNaqQnM5BrVBt02my29UyKewvFuRY="; static connect = fields; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/description-list.js b/packages/ui/dist/components/description-list.js index c091b91c8..f7a7090ba 100644 --- a/packages/ui/dist/components/description-list.js +++ b/packages/ui/dist/components/description-list.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1DescriptionList = class extends J3w1Element { static componentId = "description-list"; static version = "4.0.0"; - static implementationId = "sha256-GysXOSSmdZO80ECnRDrzDhjMNfpRODjO9r753vB1Mg0="; + static implementationId = "sha256-O3lqE1mNupuyqMqz1k1EzRDHMDjwD6aUReeED7JUclg="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/diagnostics.js b/packages/ui/dist/components/diagnostics.js index 58236865c..f9e49175b 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-C1XeXVYC.js"; -import { r as developerView } from "../chunks/display-dj9YaBfn.js"; +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 var J3w1Diagnostics = class extends J3w1Element { static componentId = "diagnostics"; static version = "4.0.0"; - static implementationId = "sha256-jU3NVgcwD6UPMMah1cBNr8kgYNhC44JLUupKYIjR8ug="; + static implementationId = "sha256-lcf+xRikFjf+LQY6YZN+giWDauQWjFZbMz3xBLI3JG8="; static connect = developerView; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/dialog.js b/packages/ui/dist/components/dialog.js index 1b3c4a379..831fed823 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-C1XeXVYC.js"; -import { n as modal } from "../chunks/overlays-C6nlCHqg.js"; +import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; +import { n as modal } from "../chunks/overlays-Bw8SSDKz.js"; //#region .cache/ui-build/entries/components/dialog.js var J3w1Dialog = class extends J3w1Element { static componentId = "dialog"; static version = "4.0.0"; - static implementationId = "sha256-klBSVv/73RVF8H8z45KqQcsbWhHl+/t4VEl+jC/2v9Q="; + static implementationId = "sha256-mRRuIsoBG3ZepORoxkayVAw92Or7CJEuj6eD9YVaZyw="; static connect = modal; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/diff-view.js b/packages/ui/dist/components/diff-view.js index 633e44138..47f8bf1a3 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-C1XeXVYC.js"; -import { r as developerView } from "../chunks/display-dj9YaBfn.js"; +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 var J3w1DiffView = class extends J3w1Element { static componentId = "diff-view"; static version = "4.0.0"; - static implementationId = "sha256-lEC5NAzVDADHe5s6uWIGnx5icpXJwmRoT/VTUI4h2l8="; + static implementationId = "sha256-7zzFpU0Y2cQR1wO8DWE4bqkofCnJMaERCXRLdai7u0A="; static connect = developerView; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/disclosure.js b/packages/ui/dist/components/disclosure.js index 8760d6a4d..56e4f17fd 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-C1XeXVYC.js"; -import { n as disclosure } from "../chunks/navigation-Dt8ap-9J.js"; +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 var J3w1Disclosure = class extends J3w1Element { static componentId = "disclosure"; static version = "4.0.0"; - static implementationId = "sha256-ROxGJvPyGtUqhWzL3a8qhGmOOsm3PD+fneX9Gb764gg="; + static implementationId = "sha256-h35ty1HDvIv+l1TZ2KWtUtdJetenP1x1+OVPFVOsByg="; static connect = disclosure; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/drawer.js b/packages/ui/dist/components/drawer.js index 3090b4b92..84e74f5d6 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-C1XeXVYC.js"; -import { n as modal } from "../chunks/overlays-C6nlCHqg.js"; +import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; +import { n as modal } from "../chunks/overlays-Bw8SSDKz.js"; //#region .cache/ui-build/entries/components/drawer.js var J3w1Drawer = class extends J3w1Element { static componentId = "drawer"; static version = "4.0.0"; - static implementationId = "sha256-8/bHeKdg2GkEVkeV2YqDCVbqEPZb6trQ7qLrf3vhnWQ="; + static implementationId = "sha256-k/ZCI1iewFGM/3Yu72DZfB6MpyHU8aF26giyLMSce+U="; static connect = modal; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/editor-search.js b/packages/ui/dist/components/editor-search.js index f5bf25205..fc6e2a1a7 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-C1XeXVYC.js"; -import { i as editorSearch } from "../chunks/display-dj9YaBfn.js"; +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 var J3w1EditorSearch = class extends J3w1Element { static componentId = "editor-search"; static version = "4.0.0"; - static implementationId = "sha256-9KkGT11jVqC1mIIjjeR24BOy0FxKESmTA8B47/6yZHg="; + static implementationId = "sha256-SqX6iBMRHKvfYM9+QKkc2K/hjCGRNMeVrj+B25L3SoU="; static connect = editorSearch; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/empty-state.js b/packages/ui/dist/components/empty-state.js index b735fb73b..a2ad90398 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-C1XeXVYC.js"; -import { t as feedback } from "../chunks/overlays-C6nlCHqg.js"; +import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; +import { t as feedback } from "../chunks/overlays-Bw8SSDKz.js"; //#region .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-rbfG9GfAXF+BMPfgYh9VU3TSU0CXpzgo8GhNdA2DHw0="; + static implementationId = "sha256-TjsU1nEvRoXqvqnqWsM2EsMF7pDu5QD94wKIbCronI4="; static connect = feedback; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/error-state.js b/packages/ui/dist/components/error-state.js index 42d38f9c3..8adf9072e 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-C1XeXVYC.js"; -import { t as feedback } from "../chunks/overlays-C6nlCHqg.js"; +import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; +import { t as feedback } from "../chunks/overlays-Bw8SSDKz.js"; //#region .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-hj5jc9C6nDjhax7f/nHkk1z0tkHTuXGp1LJlDuYyDwU="; + static implementationId = "sha256-NFXjO9uEbTYqbXbZVfFiY8Ge2N54qnmAPnp046iwL4U="; static connect = feedback; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/field.js b/packages/ui/dist/components/field.js index 70f9d02d4..432885b11 100644 --- a/packages/ui/dist/components/field.js +++ b/packages/ui/dist/components/field.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Field = class extends J3w1Element { static componentId = "field"; static version = "4.0.0"; - static implementationId = "sha256-CViK07vFgOOS2jQ7u/riONTbtMAUdHVY73iqaGIV1tw="; + static implementationId = "sha256-GDPT/9zMxdyqVusrML6KYJd3mC9Kts0/5zp2/Xi2cYA="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/fieldset.js b/packages/ui/dist/components/fieldset.js index 4ed189f3a..062960dc4 100644 --- a/packages/ui/dist/components/fieldset.js +++ b/packages/ui/dist/components/fieldset.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Fieldset = class extends J3w1Element { static componentId = "fieldset"; static version = "4.0.0"; - static implementationId = "sha256-T4bhKoYz9jjaxP51Plfd+oswKiEpk1JGLzi29ItD4mQ="; + static implementationId = "sha256-GMEsNCLKXzxBWy1NzvLrpSNVUG/llwSmGqxbUbScbHQ="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/file-browser.js b/packages/ui/dist/components/file-browser.js index 17d4a5a03..2c355a89a 100644 --- a/packages/ui/dist/components/file-browser.js +++ b/packages/ui/dist/components/file-browser.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as fileBrowser } from "../chunks/compositions-d6BkKTYf.js"; +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 var J3w1FileBrowser = class extends J3w1Element { static componentId = "file-browser"; static version = "4.0.0"; - static implementationId = "sha256-aX7ynrR8fIvhjh+E38lBwgWP8mffpXVi5toiJ1sIa9c="; + static implementationId = "sha256-XNnX1ARH1szUReH6kSeTR1njKOACxLiUhBCmo9iNz8s="; static connect = fileBrowser; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/file-input.js b/packages/ui/dist/components/file-input.js index 228c9b229..e90ea78d1 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-C1XeXVYC.js"; -import { i as fileInput } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1FileInput = class extends J3w1Element { static componentId = "file-input"; static version = "4.0.0"; - static implementationId = "sha256-m0+3EjPTC3Wr2r8xF2V2Q+38R4z12VAJn9DB7iS0JPc="; + static implementationId = "sha256-DYtJ1M3W9zNvFy3MIif27+5jsw2JssfZ5mpXTXwGBCo="; static connect = fileInput; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/filterable-table.js b/packages/ui/dist/components/filterable-table.js index fdc624ffe..5eb0b2d55 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-C1XeXVYC.js"; -import { n as table } from "../chunks/tables-B25ydUHs.js"; +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 var J3w1FilterableTable = class extends J3w1Element { static componentId = "filterable-table"; static version = "4.0.0"; - static implementationId = "sha256-X8YqHg+uk9WRKBEGt72ID1ciBCXv0ORCorTI2IiT8v8="; + static implementationId = "sha256-SJvvFZ+/THkuQJCx1F2i0vCQ2C54dLton+9ipWE3sS8="; static connect = table; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/form-builder.js b/packages/ui/dist/components/form-builder.js index a3969b6cb..18f75c157 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-C6Rhfsz6.js"; +export { t as J3w1FormBuilder } from "../chunks/form-builder-C4avSOze.js"; diff --git a/packages/ui/dist/components/i3-window-frame.js b/packages/ui/dist/components/i3-window-frame.js index f7f1bfad9..b22fc628b 100644 --- a/packages/ui/dist/components/i3-window-frame.js +++ b/packages/ui/dist/components/i3-window-frame.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { r as windowFrame } from "../chunks/compositions-d6BkKTYf.js"; +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 var J3w1I3WindowFrame = class extends J3w1Element { static componentId = "i3-window-frame"; static version = "4.0.0"; - static implementationId = "sha256-Y4Ce7n8VcttdP/24Otj7l0Ls+ShSo3ACSeSkMKfZg4o="; + static implementationId = "sha256-aoVPpcLCR1nIgTxPmR2un0VYei4XlfuvYsAk1YW7+mU="; static connect = windowFrame; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/icon-button.js b/packages/ui/dist/components/icon-button.js index 7a65f2c9a..1b617c987 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-C1XeXVYC.js"; -import { t as actions } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1IconButton = class extends J3w1Element { static componentId = "icon-button"; static version = "4.0.0"; - static implementationId = "sha256-yIIam+ZjRGwxBMpAmgZARlOdFeFJZkhR1zP8PoO2q8g="; + static implementationId = "sha256-6B32745m5D4H8EEVZL8U0DDC44RJN37XJIm7LWa43Gg="; static connect = actions; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...[ diff --git a/packages/ui/dist/components/kbd.js b/packages/ui/dist/components/kbd.js index 9b1b92534..0556ef474 100644 --- a/packages/ui/dist/components/kbd.js +++ b/packages/ui/dist/components/kbd.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Kbd = class extends J3w1Element { static componentId = "kbd"; static version = "4.0.0"; - static implementationId = "sha256-M5H4/+6leZF7LAC7Shi1RDl/6HP+GYN6gzvNdgAGu0o="; + static implementationId = "sha256-/6a09jGbevstnOqzIMGZWFLfMuQtcqnGZ7oWyH64Xdg="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/link.js b/packages/ui/dist/components/link.js index de2420838..2356d4084 100644 --- a/packages/ui/dist/components/link.js +++ b/packages/ui/dist/components/link.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Link = class extends J3w1Element { static componentId = "link"; static version = "4.0.0"; - static implementationId = "sha256-G30Bj9xANI38mlDOkDVPEfBPa0wZWo9ZLpoAHPXMAGE="; + static implementationId = "sha256-rEWDiPkjpyMkw7piXIpFnMc4x8xrVQVhLrBLQWgZXRM="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/list.js b/packages/ui/dist/components/list.js index 3e5713699..247cffcc3 100644 --- a/packages/ui/dist/components/list.js +++ b/packages/ui/dist/components/list.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1List = class extends J3w1Element { static componentId = "list"; static version = "4.0.0"; - static implementationId = "sha256-bxsrs/DyJ6xpQGoZP+g3PJhsF5XpL6aWGvL7lM0TCNY="; + static implementationId = "sha256-14u9zr26qx+pniqBnH8sp+D6R9pyXRKm+KsUR/WnsOU="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/loading-indicator.js b/packages/ui/dist/components/loading-indicator.js index db1fc292b..85ead853a 100644 --- a/packages/ui/dist/components/loading-indicator.js +++ b/packages/ui/dist/components/loading-indicator.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1LoadingIndicator = class extends J3w1Element { static componentId = "loading-indicator"; static version = "4.0.0"; - static implementationId = "sha256-oylPiWm24mRL7UT6FnHzCqajisyWBH6qEks6sQ4t3Uc="; + static implementationId = "sha256-IeUo78vKcH/jhCptrFf5Js2XH0mNmrbHQA3dBow7Sb8="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/menu.js b/packages/ui/dist/components/menu.js index 3f1e4b50c..b35ceb43e 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-C1XeXVYC.js"; -import { r as menu } from "../chunks/navigation-Dt8ap-9J.js"; +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 var J3w1Menu = class extends J3w1Element { static componentId = "menu"; static version = "4.0.0"; - static implementationId = "sha256-jIlJcU1Nx7Q5MB7Fqfcn4f9vr0IW1gmGwNdP5Rk72Aw="; + static implementationId = "sha256-oS0Ubl9rLRKcmk22aO7KDARBpUoA/Y7sR2AvyqabH+U="; static connect = menu; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/multiselect.js b/packages/ui/dist/components/multiselect.js index 20a588ed0..cb58ac304 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-C1XeXVYC.js"; -import { n as multiselect } from "../chunks/advanced-DCpe8Ndv.js"; +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 var J3w1Multiselect = class extends J3w1Element { static componentId = "multiselect"; static version = "4.0.0"; - static implementationId = "sha256-OPa5V1nQSQlq4kVkfylH8e9/Aw6ID9xFd3Wd2jg9JT4="; + static implementationId = "sha256-M7eRaWl+u1uQgXFKvnBd0GCc8U7xIWfp5yT7U9eMjTg="; static connect = multiselect; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/number-field.js b/packages/ui/dist/components/number-field.js index af0b10715..41733ea16 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1NumberField = class extends J3w1Element { static componentId = "number-field"; static version = "4.0.0"; - static implementationId = "sha256-gb44C85yifc6xKGrJuKPEX7vvpX08h4rRm5NPWN3woo="; + static implementationId = "sha256-XSucS362OAqtU9RKAYp52Tc3M6K6uMWKmB6UdK8+/o0="; static connect = fields; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/pagination.js b/packages/ui/dist/components/pagination.js index ef3f9cb03..140293f27 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-C1XeXVYC.js"; -import { t as pagination } from "../chunks/tables-B25ydUHs.js"; +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 var J3w1Pagination = class extends J3w1Element { static componentId = "pagination"; static version = "4.0.0"; - static implementationId = "sha256-euvVvLa2uqHPWf4lao8liCwhVeUZHrDFF8Z30hRttNg="; + static implementationId = "sha256-HgWIYJ3ex0Ayw+BLic3BdN3dNV9ChkM7wiwgp/qkkAE="; static connect = pagination; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/popover.js b/packages/ui/dist/components/popover.js index bbc79107c..4ca710f90 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-C1XeXVYC.js"; -import { r as popover } from "../chunks/overlays-C6nlCHqg.js"; +import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; +import { r as popover } from "../chunks/overlays-Bw8SSDKz.js"; //#region .cache/ui-build/entries/components/popover.js var J3w1Popover = class extends J3w1Element { static componentId = "popover"; static version = "4.0.0"; - static implementationId = "sha256-R3mF1UXSn1CBWM10egGi9EjTZGc775igXYWKiLNBZSY="; + static implementationId = "sha256-8KG7XOC5HTOmJW+CysUIXfhkV3COWEwpPzmG6HXdN80="; static connect = popover; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/progress.js b/packages/ui/dist/components/progress.js index 2328cc005..c4664d716 100644 --- a/packages/ui/dist/components/progress.js +++ b/packages/ui/dist/components/progress.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Progress = class extends J3w1Element { static componentId = "progress"; static version = "4.0.0"; - static implementationId = "sha256-pb/hnKbLN1fkkVEzliJMaxoY12bTHrD8nlVbfWNTXGE="; + static implementationId = "sha256-ayNpjS/tJF/VzILGmci24aDE3GR3edKDd1sGAVN7HtQ="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/radio-group.js b/packages/ui/dist/components/radio-group.js index e82d3422f..9c5100135 100644 --- a/packages/ui/dist/components/radio-group.js +++ b/packages/ui/dist/components/radio-group.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1RadioGroup = class extends J3w1Element { static componentId = "radio-group"; static version = "4.0.0"; - static implementationId = "sha256-zaWExle/kKyvESOFtr11ZVTV64fMoCjROxiCHKlvwyY="; + static implementationId = "sha256-qoOHybVksZNlma+H614aGdgiZ/u0EegTSeDcIojBXA0="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/range.js b/packages/ui/dist/components/range.js index 8c18e09bc..b560b2a51 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Range = class extends J3w1Element { static componentId = "range"; static version = "4.0.0"; - static implementationId = "sha256-775qtEkdJpV+XXDTSY5Jta+nPBg9zq9OpoCwXoM1X30="; + static implementationId = "sha256-zCJuNTps0+QV29mUu6dGnyhnpifuS7WnpWWjLJtkpdo="; static connect = fields; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/repeater.js b/packages/ui/dist/components/repeater.js index 1660aee7c..0874370f2 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-C1XeXVYC.js"; -import { r as repeater } from "../chunks/advanced-DCpe8Ndv.js"; +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 var J3w1Repeater = class extends J3w1Element { static componentId = "repeater"; static version = "4.0.0"; - static implementationId = "sha256-Tx+pvPHZeC66CE52/uMEXatMD8QBTtQd+OahbHnBVuY="; + static implementationId = "sha256-G3uVYtEsLo70OmMPhofMD2YylFEq1kezRvUEMrNnRII="; static connect = repeater; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...[ diff --git a/packages/ui/dist/components/search-field.js b/packages/ui/dist/components/search-field.js index 4d97313b6..666ca6dde 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1SearchField = class extends J3w1Element { static componentId = "search-field"; static version = "4.0.0"; - static implementationId = "sha256-1DXqGUME/dceUQ+jjPOv/UDtTubfoV13HCjmaDde06w="; + static implementationId = "sha256-nopARV2ViNiuyBqGv6KjxLJ3uaaVqRJ3K7Mgtg/mS7Q="; static connect = fields; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/segmented-control.js b/packages/ui/dist/components/segmented-control.js index e72128f6a..6ffc9b94e 100644 --- a/packages/ui/dist/components/segmented-control.js +++ b/packages/ui/dist/components/segmented-control.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1SegmentedControl = class extends J3w1Element { static componentId = "segmented-control"; static version = "4.0.0"; - static implementationId = "sha256-9PLNL13EHbz4Q4W5X5YLzVqofRhbsR0BeD0TPmji/8Q="; + static implementationId = "sha256-ULY50CCb++GAub0Bdb1hOwDWjDszJVNB0Fwnbmwbg1c="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/select.js b/packages/ui/dist/components/select.js index f15a0462d..a59b0acab 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Select = class extends J3w1Element { static componentId = "select"; static version = "4.0.0"; - static implementationId = "sha256-x5f4XAk757Fq5+Tl0cEgt1x3VCTPpITjazQZUo+WpvQ="; + static implementationId = "sha256-/4CAqDSF84DTC0pEcQUtcmmtAaVge6ifWVX3elTZzLM="; static connect = fields; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/settings-panel.js b/packages/ui/dist/components/settings-panel.js index 0d8bf3d6a..4d48521a3 100644 --- a/packages/ui/dist/components/settings-panel.js +++ b/packages/ui/dist/components/settings-panel.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { t as formComposition } from "../chunks/forms-BT3z7lNC.js"; +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 var J3w1SettingsPanel = class extends J3w1Element { static componentId = "settings-panel"; static version = "4.0.0"; - static implementationId = "sha256-EIIJELO3DpCDTENzI+0vWiDG0OCBjrf8QBh5vGHkR/M="; + static implementationId = "sha256-Or1edewP4Rk9HC/kFygK+IUyEoPDHJFEyWO9Acv3Ge4="; static connect = formComposition; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/sidebar-nav.js b/packages/ui/dist/components/sidebar-nav.js index 17b99366b..03f391cbd 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-C1XeXVYC.js"; -import { n as disclosure } from "../chunks/navigation-Dt8ap-9J.js"; +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 var J3w1SidebarNav = class extends J3w1Element { static componentId = "sidebar-nav"; static version = "4.0.0"; - static implementationId = "sha256-7P+xFrwVfLOcV9jD54m5q0GPgMxEknJwkB/ex41V9/E="; + static implementationId = "sha256-rKjBWaKv0/VZBCTIvYNnUx/X/HyPypn7MJrL9+nt6cM="; static connect = disclosure; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/skeleton.js b/packages/ui/dist/components/skeleton.js index c6e8e7fc4..16c0393a3 100644 --- a/packages/ui/dist/components/skeleton.js +++ b/packages/ui/dist/components/skeleton.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Skeleton = class extends J3w1Element { static componentId = "skeleton"; static version = "4.0.0"; - static implementationId = "sha256-fM5rtzoVG8RbNxxxkZnyxAlMU2Y7X34uknqD80CcjkA="; + static implementationId = "sha256-ZyHv2dS6YAfZGShU1uHi9YjORc4siAkmG4ledp4rX5I="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/skip-link.js b/packages/ui/dist/components/skip-link.js index 31537fda3..65021bd9d 100644 --- a/packages/ui/dist/components/skip-link.js +++ b/packages/ui/dist/components/skip-link.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1SkipLink = class extends J3w1Element { static componentId = "skip-link"; static version = "4.0.0"; - static implementationId = "sha256-KdblE6x/JhgGz9zwqnBxtLslwBM2YaG4D+gQYhv8+U8="; + static implementationId = "sha256-S77cz706XKgfI8OMLIyAhZab0PRCJkMplNQrcZjKP3c="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/switch.js b/packages/ui/dist/components/switch.js index 8dd46651f..87c027482 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-C1XeXVYC.js"; -import { a as switchControl } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Switch = class extends J3w1Element { static componentId = "switch"; static version = "4.0.0"; - static implementationId = "sha256-Wsym3Y7lkfx+vDtiTBtZS2h3anSfvc8bYabeqBAc4ms="; + static implementationId = "sha256-FqTv7TNhvOBWq10QKBC1FBB+4Wxd4wo2qtt4bCUEvbA="; static connect = switchControl; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/table.js b/packages/ui/dist/components/table.js index 747e23ad7..a79632ad4 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-C1XeXVYC.js"; -import { n as table } from "../chunks/tables-B25ydUHs.js"; +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 var J3w1Table = class extends J3w1Element { static componentId = "table"; static version = "4.0.0"; - static implementationId = "sha256-1o7THlBOZhryugncv5/v3bAs3dEZx7OD0QGD47Fx2q4="; + static implementationId = "sha256-dYinCl3vod1TSMh+SSPtibWEFlVRwhAF7TZ09eviokw="; static connect = table; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/tabs.js b/packages/ui/dist/components/tabs.js index dfdc18518..448e73b8b 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-C1XeXVYC.js"; -import { i as tabs } from "../chunks/navigation-Dt8ap-9J.js"; +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 var J3w1Tabs = class extends J3w1Element { static componentId = "tabs"; static version = "4.0.0"; - static implementationId = "sha256-yl6ifi/c/BHYGqaMMbePuD6uCP50aeMMOiJFXfy/C6s="; + static implementationId = "sha256-vWyT4Mr1GxnXVkpNXHK/nd/+0BmdRogsb7+eE6EnQ7A="; static connect = tabs; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/terminal.js b/packages/ui/dist/components/terminal.js index b6b36123c..d9c12358a 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-C1XeXVYC.js"; -import { r as developerView } from "../chunks/display-dj9YaBfn.js"; +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 var J3w1Terminal = class extends J3w1Element { static componentId = "terminal"; static version = "4.0.0"; - static implementationId = "sha256-YtjoIQGA3MHvquAi/l7AGweWpTNBe/ruD7iYJIEkkoc="; + static implementationId = "sha256-vnYvMfEFdH6UbGXHQ5OrfeJTspczt8hiaTWYnXnhlJc="; static connect = developerView; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/text-field.js b/packages/ui/dist/components/text-field.js index 469ab73da..5f6946538 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1TextField = class extends J3w1Element { static componentId = "text-field"; static version = "4.0.0"; - static implementationId = "sha256-zLqXpOHelLAc+ttryZKIkoe3xzw0YRD1AHJXXSXMwdg="; + static implementationId = "sha256-k06i0LBPa/oPe2VNmxbJkBzisp1zcAENq3MeVnKZzAo="; static connect = fields; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/textarea.js b/packages/ui/dist/components/textarea.js index 35ed045a1..850762b41 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Textarea = class extends J3w1Element { static componentId = "textarea"; static version = "4.0.0"; - static implementationId = "sha256-hrpvVFypogHx9xxUI1Lemq3AlNYBkdbjqujfPFl8BM0="; + static implementationId = "sha256-BoVEmVsZUWTLPVMKc4WLoQfNpjGc4Wy8j7o7zHck1uQ="; static connect = fields; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/time-picker.js b/packages/ui/dist/components/time-picker.js index 384dca63b..182becce4 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1TimePicker = class extends J3w1Element { static componentId = "time-picker"; static version = "4.0.0"; - static implementationId = "sha256-NixIqVSP1+pZBmD/nUflx8v6ZEWVt0qAVhGMMZv7eWQ="; + static implementationId = "sha256-IYFVpO+yyMztyk5IQgkfuuyrieY/xyLgcisHM1D02DA="; static connect = fields; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/timeline.js b/packages/ui/dist/components/timeline.js index 49eeb39d4..b5e0249ea 100644 --- a/packages/ui/dist/components/timeline.js +++ b/packages/ui/dist/components/timeline.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Timeline = class extends J3w1Element { static componentId = "timeline"; static version = "4.0.0"; - static implementationId = "sha256-CHqFmIx9nQ6y8hgR0WE3+faD/i7oj5KwbMMOpibojI4="; + static implementationId = "sha256-AeDLITSMVmcqyJwXO1iz+6eWe9/9kWYL6lepUxS5ZtU="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/toast.js b/packages/ui/dist/components/toast.js index bfce21732..b400752aa 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-C1XeXVYC.js"; -import { t as feedback } from "../chunks/overlays-C6nlCHqg.js"; +import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; +import { t as feedback } from "../chunks/overlays-Bw8SSDKz.js"; //#region .cache/ui-build/entries/components/toast.js var J3w1Toast = class extends J3w1Element { static componentId = "toast"; static version = "4.0.0"; - static implementationId = "sha256-rhHX0XsrYevsAon0WzlROHjbfJksZhr/XraWeBmZhxA="; + static implementationId = "sha256-BqW1X3i3Z1X0gaHK/29B1mrUpyhmHpV2a30eW/aK+y4="; static connect = feedback; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/toolbar.js b/packages/ui/dist/components/toolbar.js index c2b5f4a84..195494e1d 100644 --- a/packages/ui/dist/components/toolbar.js +++ b/packages/ui/dist/components/toolbar.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { a as toolbar } from "../chunks/navigation-Dt8ap-9J.js"; +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 var J3w1Toolbar = class extends J3w1Element { static componentId = "toolbar"; static version = "4.0.0"; - static implementationId = "sha256-7FoTDU41k2QPRk6gXO/G9yZKsFEuxE/63FSt+FSMAlQ="; + static implementationId = "sha256-VCE2y9mKILLuKe6e6CYb+KzHmhM/oKWGD3XWHaHGRw0="; static connect = toolbar; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/tooltip.js b/packages/ui/dist/components/tooltip.js index a796e5788..e641fa5b8 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-C1XeXVYC.js"; -import { i as tooltip } from "../chunks/overlays-C6nlCHqg.js"; +import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; +import { i as tooltip } from "../chunks/overlays-Bw8SSDKz.js"; //#region .cache/ui-build/entries/components/tooltip.js var J3w1Tooltip = class extends J3w1Element { static componentId = "tooltip"; static version = "4.0.0"; - static implementationId = "sha256-nhRIjLsKxdM5/M6c+0RvOzlv1sK6VJDshft6xhMUbtE="; + static implementationId = "sha256-GLt9uL8KQ+UknDKUAP+CEU7bTChO5TO3WPwmpJzH62M="; static connect = tooltip; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/components/tree.js b/packages/ui/dist/components/tree.js index 8a8288b08..e0f6bd8da 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-C1XeXVYC.js"; -import { i as tree } from "../chunks/advanced-DCpe8Ndv.js"; +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 var J3w1Tree = class extends J3w1Element { static componentId = "tree"; static version = "4.0.0"; - static implementationId = "sha256-MaBLx3mLOk+RW8kMweDInlVoWjSFctZly5Jz9BMRFRI="; + static implementationId = "sha256-8E6bGMMWEmhgjIAfuDs1+pxcabRicShQao3beIvcNBY="; static connect = tree; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/components/wizard.js b/packages/ui/dist/components/wizard.js index 4d9bbaefc..852097735 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-C1XeXVYC.js"; -import { n as wizard } from "../chunks/forms-BT3z7lNC.js"; +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 var J3w1Wizard = class extends J3w1Element { static componentId = "wizard"; static version = "4.0.0"; - static implementationId = "sha256-io0DYHj45iX5Dvck9xDTbxK9av2V6Z42KQERETAWGb4="; + static implementationId = "sha256-RPzZPFnWZYndDTCn4JxgWR8s+kGEDCPgKxzzaesMZdk="; static connect = wizard; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/consumption.md b/packages/ui/dist/consumption.md index fb7d37943..22370406e 100644 --- a/packages/ui/dist/consumption.md +++ b/packages/ui/dist/consumption.md @@ -23,9 +23,11 @@ complete maintained markup on the component's page. Keep the exact package version and your package-manager lockfile in source control. + ```sh -npm install --save-exact @j3w1/ui@3.1.0 +npm install --save-exact @j3w1/ui@4.0.0 ``` + That command needs npm publication, which is an owner release action. Before publication: @@ -34,9 +36,11 @@ publication: 2. Check it against its published digest. 3. Install the local file: + ```sh -npm install --save-exact ./j3w1-ui-3.1.0.tgz +npm install --save-exact ./j3w1-ui-4.0.0.tgz ``` + The repository builds this same artifact with `npm run ui:build` and `npm run ui:pack`. Never use a branch URL in place of a release pin. Do not @@ -250,10 +254,12 @@ Styling: ## Copy a complete bundle + ```sh -npx --package=@j3w1/ui@3.1.0 j3w1-ui copy dialog --out ./vendor/j3w1/dialog -npx --package=@j3w1/ui@3.1.0 j3w1-ui kit --components text-field,button,dialog --out ./vendor/j3w1/task +npx --package=@j3w1/ui@4.0.0 j3w1-ui copy dialog --out ./vendor/j3w1/dialog +npx --package=@j3w1/ui@4.0.0 j3w1-ui kit --components text-field,button,dialog --out ./vendor/j3w1/task ``` + - Installed from a tarball: run the installed `j3w1-ui` binary instead of npx. - The CLI checks all source bytes before it writes. It rejects unknown components diff --git a/packages/ui/dist/contracts/admin-form.json b/packages/ui/dist/contracts/admin-form.json index 84cac0e3d..3c3531097 100644 --- a/packages/ui/dist/contracts/admin-form.json +++ b/packages/ui/dist/contracts/admin-form.json @@ -909,6 +909,6 @@ "copy": { "directory": "copy/admin-form/", "manifest": "copy/admin-form/manifest.json", - "digest": "sha256-nYS8jMsuxKEj8F3dOHKvnVCccydqs1Pp3Z6SsTCUoOU=" + "digest": "sha256-SY9yLDIEoubx7vOjX86E6Af/lWOXakcF5RF345H06o0=" } } diff --git a/packages/ui/dist/contracts/alert.json b/packages/ui/dist/contracts/alert.json index 5c2fa2f3f..e8ee20f91 100644 --- a/packages/ui/dist/contracts/alert.json +++ b/packages/ui/dist/contracts/alert.json @@ -445,6 +445,6 @@ "copy": { "directory": "copy/alert/", "manifest": "copy/alert/manifest.json", - "digest": "sha256-2ZbWfxl+0O3OjPAuMynLSs9Kp25QuUMiwXSpMKBlxQ0=" + "digest": "sha256-GdtuucxCeKVz8/V2jsQmrExTynqtoj18Ngk2eibPo1A=" } } diff --git a/packages/ui/dist/contracts/avatar.json b/packages/ui/dist/contracts/avatar.json index f1304f356..b42209aff 100644 --- a/packages/ui/dist/contracts/avatar.json +++ b/packages/ui/dist/contracts/avatar.json @@ -274,6 +274,6 @@ "copy": { "directory": "copy/avatar/", "manifest": "copy/avatar/manifest.json", - "digest": "sha256-c6GiHt1iB6I4HICzh/PnoN9D4wm4omp6h7bp2vBfftg=" + "digest": "sha256-d3157WFbkfMSnAyhscjitsbHKfZ5RIkgA5UPkxlBRyw=" } } diff --git a/packages/ui/dist/contracts/badge.json b/packages/ui/dist/contracts/badge.json index 004d71f97..aeb00073d 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-dYqinOxtXZZbvC2MgSv3k1KR+2WgDw7MIWYvM1syecw=" + "digest": "sha256-2ZbcqLs0w7N2cnu6znQmM45vwV2jYqlVYeROhMVGDXY=" } } diff --git a/packages/ui/dist/contracts/breadcrumbs.json b/packages/ui/dist/contracts/breadcrumbs.json index 3a582e963..9408323bc 100644 --- a/packages/ui/dist/contracts/breadcrumbs.json +++ b/packages/ui/dist/contracts/breadcrumbs.json @@ -340,6 +340,6 @@ "copy": { "directory": "copy/breadcrumbs/", "manifest": "copy/breadcrumbs/manifest.json", - "digest": "sha256-EalDQFcoOagLdF+WFVS1L0RqDU9zG7P6zi6BdvHcFFM=" + "digest": "sha256-sxScJ5LWeXb+RcxzzKt3BInF6XNPWZanItclgpTAtnQ=" } } diff --git a/packages/ui/dist/contracts/button-group.json b/packages/ui/dist/contracts/button-group.json index 227505894..9eb9d73aa 100644 --- a/packages/ui/dist/contracts/button-group.json +++ b/packages/ui/dist/contracts/button-group.json @@ -323,6 +323,6 @@ "copy": { "directory": "copy/button-group/", "manifest": "copy/button-group/manifest.json", - "digest": "sha256-vwsYAxmno4/3Uq0+30v3izOHgMpzwUEntDgsiFb/uAE=" + "digest": "sha256-jdstAsXBIYH7Fn/eAXxFfPkA1FXs81QYJ3o5InKuAbE=" } } diff --git a/packages/ui/dist/contracts/button.json b/packages/ui/dist/contracts/button.json index fb68cc281..5ab32103d 100644 --- a/packages/ui/dist/contracts/button.json +++ b/packages/ui/dist/contracts/button.json @@ -510,6 +510,6 @@ "copy": { "directory": "copy/button/", "manifest": "copy/button/manifest.json", - "digest": "sha256-c6TgjUcOcYCt67r5dMnrTmZpgv9LuAg3v1JdKvlJv+I=" + "digest": "sha256-9aPod8autncWE6MMIq3cg0M3HLELyCDUbauos9Lmay8=" } } diff --git a/packages/ui/dist/contracts/card.json b/packages/ui/dist/contracts/card.json index 5d67877f7..498b423d8 100644 --- a/packages/ui/dist/contracts/card.json +++ b/packages/ui/dist/contracts/card.json @@ -362,6 +362,6 @@ "copy": { "directory": "copy/card/", "manifest": "copy/card/manifest.json", - "digest": "sha256-i+pJofI3U2yKMpy/iUtg9GQYpMJuhdXqk8eQsj/fFsk=" + "digest": "sha256-surQ2SRSiqDj/nzNCiD1yEFyfhPCm61p0Yjf7gl8rnE=" } } diff --git a/packages/ui/dist/contracts/chart.json b/packages/ui/dist/contracts/chart.json index 3e76b0c29..0b86b5810 100644 --- a/packages/ui/dist/contracts/chart.json +++ b/packages/ui/dist/contracts/chart.json @@ -336,6 +336,6 @@ "copy": { "directory": "copy/chart/", "manifest": "copy/chart/manifest.json", - "digest": "sha256-lm2ZxifbDt5iYTAwiLkbvEREqGAmkeGkqLeoqfgfbLw=" + "digest": "sha256-F/2fv5nZscYggNH2x3Z0v/7Jg7onkrxtjw3NNZ95mf8=" } } diff --git a/packages/ui/dist/contracts/checkbox.json b/packages/ui/dist/contracts/checkbox.json index 22c821986..1b9e80e03 100644 --- a/packages/ui/dist/contracts/checkbox.json +++ b/packages/ui/dist/contracts/checkbox.json @@ -491,6 +491,6 @@ "copy": { "directory": "copy/checkbox/", "manifest": "copy/checkbox/manifest.json", - "digest": "sha256-kFFpTffP1dDIr9wzNmLVN7foHnf/nRwRbekip3C4oYY=" + "digest": "sha256-objP3WhT1Jq2OhCFDVjtysUtDf8cG7rSSGnEFk6oHkA=" } } diff --git a/packages/ui/dist/contracts/chip.json b/packages/ui/dist/contracts/chip.json index e01495c21..9d590e0eb 100644 --- a/packages/ui/dist/contracts/chip.json +++ b/packages/ui/dist/contracts/chip.json @@ -386,6 +386,6 @@ "copy": { "directory": "copy/chip/", "manifest": "copy/chip/manifest.json", - "digest": "sha256-yT0JmPG1bG7dWQAeyCEaG9vmhKJg43cR+dngTQc3ToY=" + "digest": "sha256-QGjrjIpek7P7Yi72gBE9aw5WBUsqe4QAZRMfkbJ6DVo=" } } diff --git a/packages/ui/dist/contracts/code-editor.json b/packages/ui/dist/contracts/code-editor.json index 6ed98eb06..e0a2c4b76 100644 --- a/packages/ui/dist/contracts/code-editor.json +++ b/packages/ui/dist/contracts/code-editor.json @@ -531,6 +531,6 @@ "copy": { "directory": "copy/code-editor/", "manifest": "copy/code-editor/manifest.json", - "digest": "sha256-ilcy8XyaIxDvpFx8RrzkFJhHJ6uot99rm2kBpXxBYBI=" + "digest": "sha256-/A+RNxZGcOIo0DFchNAZJ6m84/3M7PzfW3bRO9VFry4=" } } diff --git a/packages/ui/dist/contracts/combobox.json b/packages/ui/dist/contracts/combobox.json index 29d23c77a..445bfef25 100644 --- a/packages/ui/dist/contracts/combobox.json +++ b/packages/ui/dist/contracts/combobox.json @@ -548,6 +548,6 @@ "copy": { "directory": "copy/combobox/", "manifest": "copy/combobox/manifest.json", - "digest": "sha256-rdA+FV9dwxEdykFLa7tzZnjl+60iBGTXLBwm5cfXOnE=" + "digest": "sha256-LC5lxRaEjCGeCQs8KzUb7Kib9EekddKOWGaaXDBODQs=" } } diff --git a/packages/ui/dist/contracts/command-palette.json b/packages/ui/dist/contracts/command-palette.json index 970446129..9b37457cc 100644 --- a/packages/ui/dist/contracts/command-palette.json +++ b/packages/ui/dist/contracts/command-palette.json @@ -407,6 +407,6 @@ "copy": { "directory": "copy/command-palette/", "manifest": "copy/command-palette/manifest.json", - "digest": "sha256-RxOWXeniso+hvwGsCJGdxMEfsQnCjBbPcgMkNi70XEY=" + "digest": "sha256-uA8GN+OL2y7mOBmNlsfhjC5/h7doA6mKnA5NaP2Y4XU=" } } diff --git a/packages/ui/dist/contracts/compact-dashboard.json b/packages/ui/dist/contracts/compact-dashboard.json index 82dd23a38..77dd49f49 100644 --- a/packages/ui/dist/contracts/compact-dashboard.json +++ b/packages/ui/dist/contracts/compact-dashboard.json @@ -479,6 +479,6 @@ "copy": { "directory": "copy/compact-dashboard/", "manifest": "copy/compact-dashboard/manifest.json", - "digest": "sha256-6VcljZV/ScZZHBdlliiCRDKmNJun1WvkMSswT57Yue4=" + "digest": "sha256-HhNyj8t8nMAPYgRrOBgscLpqzSmOmckytD+vDcBJ3rU=" } } diff --git a/packages/ui/dist/contracts/data-table.json b/packages/ui/dist/contracts/data-table.json index de5c63d9b..86563c95b 100644 --- a/packages/ui/dist/contracts/data-table.json +++ b/packages/ui/dist/contracts/data-table.json @@ -607,6 +607,6 @@ "copy": { "directory": "copy/data-table/", "manifest": "copy/data-table/manifest.json", - "digest": "sha256-2ou/6/GgNuGgAaCssLJwSinsCUqepjlg+x2p8l6YANI=" + "digest": "sha256-OCyt7FSrvzT/nqyGad7t90WQqktfbHMhmLRKVC7ayI8=" } } diff --git a/packages/ui/dist/contracts/date-picker.json b/packages/ui/dist/contracts/date-picker.json index 70f622404..5d7f787da 100644 --- a/packages/ui/dist/contracts/date-picker.json +++ b/packages/ui/dist/contracts/date-picker.json @@ -583,6 +583,6 @@ "copy": { "directory": "copy/date-picker/", "manifest": "copy/date-picker/manifest.json", - "digest": "sha256-48K6bsVp7ch78EFmIyDgXpAaLzUWaLgA1nfjOo2NwZo=" + "digest": "sha256-HTadscpISlfLGMTeD2aqKFA3XTQ0944fT4Nta8m/a5Q=" } } diff --git a/packages/ui/dist/contracts/description-list.json b/packages/ui/dist/contracts/description-list.json index dc9e3d4ce..796ba7de5 100644 --- a/packages/ui/dist/contracts/description-list.json +++ b/packages/ui/dist/contracts/description-list.json @@ -281,6 +281,6 @@ "copy": { "directory": "copy/description-list/", "manifest": "copy/description-list/manifest.json", - "digest": "sha256-X4Ucl253TcuE6dHaVe7snooGjXH6qNADSDI8KIVB11A=" + "digest": "sha256-t+51h630XT9WJSqr9Ew+KF7288yZS+EGHbNlUvzKauc=" } } diff --git a/packages/ui/dist/contracts/diagnostics.json b/packages/ui/dist/contracts/diagnostics.json index ba09ee29a..16796a63a 100644 --- a/packages/ui/dist/contracts/diagnostics.json +++ b/packages/ui/dist/contracts/diagnostics.json @@ -568,6 +568,6 @@ "copy": { "directory": "copy/diagnostics/", "manifest": "copy/diagnostics/manifest.json", - "digest": "sha256-UpdG5YWwniZZMmaHLoJEtfjfHyOOvfgh9kwW7yzjGME=" + "digest": "sha256-tL7GzLYckJ9GfhEdUi2jnGJqqdrX3eIBHflY5RDP6gs=" } } diff --git a/packages/ui/dist/contracts/dialog.json b/packages/ui/dist/contracts/dialog.json index ed7478b23..7a64e6804 100644 --- a/packages/ui/dist/contracts/dialog.json +++ b/packages/ui/dist/contracts/dialog.json @@ -695,6 +695,6 @@ "copy": { "directory": "copy/dialog/", "manifest": "copy/dialog/manifest.json", - "digest": "sha256-ffV0ZOGvzK4N5REfOqb5SopYFtk70wS5so3vIH5qUHc=" + "digest": "sha256-ojK2lUJ8amSjYbXkYaErv1Tz8TPOx9vQe0FohxK9PvA=" } } diff --git a/packages/ui/dist/contracts/diff-view.json b/packages/ui/dist/contracts/diff-view.json index 38d0866a3..e185b96ea 100644 --- a/packages/ui/dist/contracts/diff-view.json +++ b/packages/ui/dist/contracts/diff-view.json @@ -516,6 +516,6 @@ "copy": { "directory": "copy/diff-view/", "manifest": "copy/diff-view/manifest.json", - "digest": "sha256-kxUgBrJ5pugX+Rn/YdpdeR3lTLsYCBlHWGv/+4xyeGY=" + "digest": "sha256-5CyVIpdcAcf9a6jxhdb1P7rhVAf7Q2Ge062mNu8e6kM=" } } diff --git a/packages/ui/dist/contracts/disclosure.json b/packages/ui/dist/contracts/disclosure.json index ff5eaf816..b1664b42b 100644 --- a/packages/ui/dist/contracts/disclosure.json +++ b/packages/ui/dist/contracts/disclosure.json @@ -335,6 +335,6 @@ "copy": { "directory": "copy/disclosure/", "manifest": "copy/disclosure/manifest.json", - "digest": "sha256-srtw0ECNjqeIbiyT88LWtptOK+3TJpxgjEzBwafyhBE=" + "digest": "sha256-IhTnTf9y8wxbgmzrMuAtQT43sT0qEhunebh3YsPvSnk=" } } diff --git a/packages/ui/dist/contracts/drawer.json b/packages/ui/dist/contracts/drawer.json index 5fff7e534..9c015266d 100644 --- a/packages/ui/dist/contracts/drawer.json +++ b/packages/ui/dist/contracts/drawer.json @@ -696,6 +696,6 @@ "copy": { "directory": "copy/drawer/", "manifest": "copy/drawer/manifest.json", - "digest": "sha256-4F6UZloyQg8I7wVtudpN0GlasZZCpflUeQnezTwqvss=" + "digest": "sha256-3OnnmMpVSx6TFSQGJa2Sy+MQ9nWHNTdwDhFx50SWiCA=" } } diff --git a/packages/ui/dist/contracts/editor-search.json b/packages/ui/dist/contracts/editor-search.json index 053b7ef79..769c7cceb 100644 --- a/packages/ui/dist/contracts/editor-search.json +++ b/packages/ui/dist/contracts/editor-search.json @@ -363,6 +363,6 @@ "copy": { "directory": "copy/editor-search/", "manifest": "copy/editor-search/manifest.json", - "digest": "sha256-tzETVZ5wEm/wqmqM6Gu3ONUNlEVtbZUiPneNH2sbPZ8=" + "digest": "sha256-h937qBCyN7f/4/4NbTvjeZNcmsKJzaShOXGOQ6xHnrc=" } } diff --git a/packages/ui/dist/contracts/empty-state.json b/packages/ui/dist/contracts/empty-state.json index 6e9a3d5ad..0b2418951 100644 --- a/packages/ui/dist/contracts/empty-state.json +++ b/packages/ui/dist/contracts/empty-state.json @@ -429,6 +429,6 @@ "copy": { "directory": "copy/empty-state/", "manifest": "copy/empty-state/manifest.json", - "digest": "sha256-75nIi6f/Ht0GN4W2P39d86rZv1OvN/aduq/2EcG1HB4=" + "digest": "sha256-A4qwhMTw4YwVgEdLkoA8+YjIxeHsdoa4rDwk9HrftLE=" } } diff --git a/packages/ui/dist/contracts/error-state.json b/packages/ui/dist/contracts/error-state.json index 1d1df2d73..eebd42a90 100644 --- a/packages/ui/dist/contracts/error-state.json +++ b/packages/ui/dist/contracts/error-state.json @@ -353,6 +353,6 @@ "copy": { "directory": "copy/error-state/", "manifest": "copy/error-state/manifest.json", - "digest": "sha256-gv+zrrKBwqknOREXPEz57rKP+7GJco38FRkXeXQqAbU=" + "digest": "sha256-xFn0ldAM/ke5tayuHtg+fqk9nJrMEeaqJCXK8Wpdr+4=" } } diff --git a/packages/ui/dist/contracts/field.json b/packages/ui/dist/contracts/field.json index 57757f7a0..04bb5d463 100644 --- a/packages/ui/dist/contracts/field.json +++ b/packages/ui/dist/contracts/field.json @@ -374,6 +374,6 @@ "copy": { "directory": "copy/field/", "manifest": "copy/field/manifest.json", - "digest": "sha256-w3/ZZLfNarfyG9UY8KNfqo/QA/4ufORLVSWeIwS/iYY=" + "digest": "sha256-2KbVkBRdn8QGAt3fcHfn5hSJFIPpIvcothSRK0bQYx4=" } } diff --git a/packages/ui/dist/contracts/fieldset.json b/packages/ui/dist/contracts/fieldset.json index 4c842e176..e95be058e 100644 --- a/packages/ui/dist/contracts/fieldset.json +++ b/packages/ui/dist/contracts/fieldset.json @@ -366,6 +366,6 @@ "copy": { "directory": "copy/fieldset/", "manifest": "copy/fieldset/manifest.json", - "digest": "sha256-uljFodRq8xH/+kpic5mcTdwYRi6D8uRATY8/65tRHSA=" + "digest": "sha256-Icof6ix6nIGawAfa4gGLYuk+5HuPjVTjIy7CMKv3Gus=" } } diff --git a/packages/ui/dist/contracts/file-browser.json b/packages/ui/dist/contracts/file-browser.json index 5ffed937e..804e0a981 100644 --- a/packages/ui/dist/contracts/file-browser.json +++ b/packages/ui/dist/contracts/file-browser.json @@ -459,6 +459,6 @@ "copy": { "directory": "copy/file-browser/", "manifest": "copy/file-browser/manifest.json", - "digest": "sha256-dumD1CMdclQzMmPsrLn3Denb28aFPOcd34uk/ZtbEgI=" + "digest": "sha256-p+FD1Fb+C3/mulwIU8cKodFTh7cYo4/fbDxZVVWtLlM=" } } diff --git a/packages/ui/dist/contracts/file-input.json b/packages/ui/dist/contracts/file-input.json index 6c612ba34..938a03348 100644 --- a/packages/ui/dist/contracts/file-input.json +++ b/packages/ui/dist/contracts/file-input.json @@ -522,6 +522,6 @@ "copy": { "directory": "copy/file-input/", "manifest": "copy/file-input/manifest.json", - "digest": "sha256-PCFjtc+DwT+gaXF4ED4ra/J3ypLKXVDF9kT/4IXn4No=" + "digest": "sha256-bH56aJVEFuoALa30Gr50CeAhnI4prQtCX+Tlg7ISm6g=" } } diff --git a/packages/ui/dist/contracts/filterable-table.json b/packages/ui/dist/contracts/filterable-table.json index c0179624f..91e02b85c 100644 --- a/packages/ui/dist/contracts/filterable-table.json +++ b/packages/ui/dist/contracts/filterable-table.json @@ -756,6 +756,6 @@ "copy": { "directory": "copy/filterable-table/", "manifest": "copy/filterable-table/manifest.json", - "digest": "sha256-6e9ro37teOmSFrYcAJ7t+PP1FQ9FEb9GhcBjA3Ah5iw=" + "digest": "sha256-vCP76v9Lq2Cjbf3J7rPkteGIiIcCkiscExcfBEdOpqw=" } } diff --git a/packages/ui/dist/contracts/form-builder.json b/packages/ui/dist/contracts/form-builder.json index 2215d7496..f4436568b 100644 --- a/packages/ui/dist/contracts/form-builder.json +++ b/packages/ui/dist/contracts/form-builder.json @@ -878,6 +878,6 @@ "copy": { "directory": "copy/form-builder/", "manifest": "copy/form-builder/manifest.json", - "digest": "sha256-/AJpK7InIcUrx5C6r4HWc3McmNfuSvcN0bFFLRwFx7s=" + "digest": "sha256-FLvmL17oFKsay5ANEQsyqUMotNS7tqHqJqbAXCGyPhw=" } } diff --git a/packages/ui/dist/contracts/i3-window-frame.json b/packages/ui/dist/contracts/i3-window-frame.json index 2dd58c36a..7a9cd244d 100644 --- a/packages/ui/dist/contracts/i3-window-frame.json +++ b/packages/ui/dist/contracts/i3-window-frame.json @@ -962,6 +962,6 @@ "copy": { "directory": "copy/i3-window-frame/", "manifest": "copy/i3-window-frame/manifest.json", - "digest": "sha256-U0UgHnHKVp5XKkj1fNN5b+MOeYjoFSjDI5MDm6KE5Qw=" + "digest": "sha256-r+5f/+sKy8zad7v6pIzYWu+aS7a5X79zFso6utxNgvw=" } } diff --git a/packages/ui/dist/contracts/icon-button.json b/packages/ui/dist/contracts/icon-button.json index 3be2a5fb9..1f44b8b6b 100644 --- a/packages/ui/dist/contracts/icon-button.json +++ b/packages/ui/dist/contracts/icon-button.json @@ -365,6 +365,6 @@ "copy": { "directory": "copy/icon-button/", "manifest": "copy/icon-button/manifest.json", - "digest": "sha256-ySWwdGJTFvqUPfIPiE//EF2SBXqYn8iDa05Ljnz5WmE=" + "digest": "sha256-oKil4+MHybcN978zie4LFpqLGOsbcddS9ILW1oS8BUg=" } } diff --git a/packages/ui/dist/contracts/kbd.json b/packages/ui/dist/contracts/kbd.json index 70e32d764..dc13e3d11 100644 --- a/packages/ui/dist/contracts/kbd.json +++ b/packages/ui/dist/contracts/kbd.json @@ -254,6 +254,6 @@ "copy": { "directory": "copy/kbd/", "manifest": "copy/kbd/manifest.json", - "digest": "sha256-N3o7jonx7ZxjgaydH4c9BuaHiyHBNtfdwvsGJReVWvc=" + "digest": "sha256-0oroIGs5QHHIsEFAS8mzBCOPGSulP+DHSkFwKqbOqfE=" } } diff --git a/packages/ui/dist/contracts/link.json b/packages/ui/dist/contracts/link.json index 94c828f42..b09d549ab 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-9RCBHV2eK/OPYH+iLaWZUBLLRL/3/Db67A/AA/gLtVA=" + "digest": "sha256-3HLwWPQ4f3n5kWRcOa538HFBnmCshfVhVu3YDi6njKI=" } } diff --git a/packages/ui/dist/contracts/list.json b/packages/ui/dist/contracts/list.json index 9a843cc0a..226878206 100644 --- a/packages/ui/dist/contracts/list.json +++ b/packages/ui/dist/contracts/list.json @@ -407,6 +407,6 @@ "copy": { "directory": "copy/list/", "manifest": "copy/list/manifest.json", - "digest": "sha256-SbBbbXQ5+Bc1H2Pt8GwTLH1s6pniel+amh1L4cKgwss=" + "digest": "sha256-bhWcTAujbBE3PS/Y2T+CsTQki57VdAggFJLePzTl+xw=" } } diff --git a/packages/ui/dist/contracts/loading-indicator.json b/packages/ui/dist/contracts/loading-indicator.json index 076c8bb80..88a4cb3a0 100644 --- a/packages/ui/dist/contracts/loading-indicator.json +++ b/packages/ui/dist/contracts/loading-indicator.json @@ -286,6 +286,6 @@ "copy": { "directory": "copy/loading-indicator/", "manifest": "copy/loading-indicator/manifest.json", - "digest": "sha256-E5QH4rXH0Q8cEQtr0bOGShuzZQlv5Y0cZ76Um3cCKCg=" + "digest": "sha256-+AYJYt3+YOXzkhh2cHyzuvahnmCB9rfq9SOV4G+Rb1U=" } } diff --git a/packages/ui/dist/contracts/menu.json b/packages/ui/dist/contracts/menu.json index 49237e3f2..56a4ac460 100644 --- a/packages/ui/dist/contracts/menu.json +++ b/packages/ui/dist/contracts/menu.json @@ -534,6 +534,6 @@ "copy": { "directory": "copy/menu/", "manifest": "copy/menu/manifest.json", - "digest": "sha256-Ud+V3UiG+NGVSscSNIvn3E4AuJOFFvDO/8r2oe1R9sw=" + "digest": "sha256-MVQ5cZlXdmFAA34VqlXLFuybCnCpay7xluf8sdFC9Rc=" } } diff --git a/packages/ui/dist/contracts/multiselect.json b/packages/ui/dist/contracts/multiselect.json index cde64e1ee..a3026010d 100644 --- a/packages/ui/dist/contracts/multiselect.json +++ b/packages/ui/dist/contracts/multiselect.json @@ -490,6 +490,6 @@ "copy": { "directory": "copy/multiselect/", "manifest": "copy/multiselect/manifest.json", - "digest": "sha256-vXlR0srvz+KDPAaPbWuMQCTQmQGqocNNjF2ccKGVUeA=" + "digest": "sha256-nKMzjOfdVCU41TBMPw0LQ1xs2gpD6VKkxbgNrjoXu74=" } } diff --git a/packages/ui/dist/contracts/number-field.json b/packages/ui/dist/contracts/number-field.json index b0f340db2..b11a3daaf 100644 --- a/packages/ui/dist/contracts/number-field.json +++ b/packages/ui/dist/contracts/number-field.json @@ -608,6 +608,6 @@ "copy": { "directory": "copy/number-field/", "manifest": "copy/number-field/manifest.json", - "digest": "sha256-p6h3APhk2/kyaXbWKAEHdHQKn9zMYnarGK9hRLu/MKg=" + "digest": "sha256-hCbMC7IlXDmxCwg/QFY9q54+XiopRwcxLcGXi5qcsB0=" } } diff --git a/packages/ui/dist/contracts/pagination.json b/packages/ui/dist/contracts/pagination.json index 204737ab4..2f2f46340 100644 --- a/packages/ui/dist/contracts/pagination.json +++ b/packages/ui/dist/contracts/pagination.json @@ -378,6 +378,6 @@ "copy": { "directory": "copy/pagination/", "manifest": "copy/pagination/manifest.json", - "digest": "sha256-VnFhaAlOvHjn6UY3qGk2yBXuPfa3PI1CYjoFCi9AAJo=" + "digest": "sha256-nx5efHd3Yq/LgORnwJ2ml5WZ9s91EpMEcsuClG7EU4U=" } } diff --git a/packages/ui/dist/contracts/popover.json b/packages/ui/dist/contracts/popover.json index 48b7a8e12..a1eb82f22 100644 --- a/packages/ui/dist/contracts/popover.json +++ b/packages/ui/dist/contracts/popover.json @@ -336,6 +336,6 @@ "copy": { "directory": "copy/popover/", "manifest": "copy/popover/manifest.json", - "digest": "sha256-Phnn5besyYINT3a2SO+Oyfo34q3wPJpuLaWvH2pQWAU=" + "digest": "sha256-77eZwFgpetX/GOZnOtSMNU/CDHsi/KG+ixW0IpkmiwM=" } } diff --git a/packages/ui/dist/contracts/progress.json b/packages/ui/dist/contracts/progress.json index 137a90489..9cc35e857 100644 --- a/packages/ui/dist/contracts/progress.json +++ b/packages/ui/dist/contracts/progress.json @@ -298,6 +298,6 @@ "copy": { "directory": "copy/progress/", "manifest": "copy/progress/manifest.json", - "digest": "sha256-r+zhlEfXkdl5bcryLN+l4mssjPuUGlyjB4vslOUMdck=" + "digest": "sha256-v1IrrUgpbjJYfPnq8pHamsdybSUnPAa8pRh6S8p+PSQ=" } } diff --git a/packages/ui/dist/contracts/radio-group.json b/packages/ui/dist/contracts/radio-group.json index aada0527b..94d9c5429 100644 --- a/packages/ui/dist/contracts/radio-group.json +++ b/packages/ui/dist/contracts/radio-group.json @@ -396,6 +396,6 @@ "copy": { "directory": "copy/radio-group/", "manifest": "copy/radio-group/manifest.json", - "digest": "sha256-UpYcgVSqDnhnjaAHOl5w3cY9WJP0x1sLlAONVAGlg78=" + "digest": "sha256-zUkTL5FcsZlvLHOTIx4RNU5lTVvTPGr/1IQX35UzkKk=" } } diff --git a/packages/ui/dist/contracts/range.json b/packages/ui/dist/contracts/range.json index b02799426..084bfa95c 100644 --- a/packages/ui/dist/contracts/range.json +++ b/packages/ui/dist/contracts/range.json @@ -556,6 +556,6 @@ "copy": { "directory": "copy/range/", "manifest": "copy/range/manifest.json", - "digest": "sha256-9Fj1tjDQyex5Ybg8lOvcWuVuHic/EnjnNXfR/YPoO7c=" + "digest": "sha256-2zOSEiGiOqY7xfv7/vuey0GKbJG9CJIjDHjsLU36960=" } } diff --git a/packages/ui/dist/contracts/repeater.json b/packages/ui/dist/contracts/repeater.json index 297b83251..9fd46acf9 100644 --- a/packages/ui/dist/contracts/repeater.json +++ b/packages/ui/dist/contracts/repeater.json @@ -361,6 +361,6 @@ "copy": { "directory": "copy/repeater/", "manifest": "copy/repeater/manifest.json", - "digest": "sha256-Ek/0mqQpQIztzCidbtl1wboLnvHJjvWQ7BM/s4lZ5FM=" + "digest": "sha256-JQ4FuJwvAez8YhIdTjgxq2ItTIEaKdSzvz38cbU6ChU=" } } diff --git a/packages/ui/dist/contracts/search-field.json b/packages/ui/dist/contracts/search-field.json index c6bfdb188..821fb15c1 100644 --- a/packages/ui/dist/contracts/search-field.json +++ b/packages/ui/dist/contracts/search-field.json @@ -484,6 +484,6 @@ "copy": { "directory": "copy/search-field/", "manifest": "copy/search-field/manifest.json", - "digest": "sha256-pnh7Ao4SBHM7H6SMJlWsYLXgxVp7AdEhbo+/35vi72k=" + "digest": "sha256-X2C6mB7tjK5+K1tt523eqZrLi+n8t21TOjfncY+ulSY=" } } diff --git a/packages/ui/dist/contracts/segmented-control.json b/packages/ui/dist/contracts/segmented-control.json index 846069fec..82744736b 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-H33N4ElTkCkBMh2MbBR3SPIPib1+HsrpF2WqEwYwOow=" + "digest": "sha256-mtPWQuT+66s2vpxWJcVaB8keW/TMjasZjnnCJjIMXd4=" } } diff --git a/packages/ui/dist/contracts/select.json b/packages/ui/dist/contracts/select.json index 32d990c70..ad84ca632 100644 --- a/packages/ui/dist/contracts/select.json +++ b/packages/ui/dist/contracts/select.json @@ -607,6 +607,6 @@ "copy": { "directory": "copy/select/", "manifest": "copy/select/manifest.json", - "digest": "sha256-Auv8G7CtLAflBo0zzaMsITFuEZmyeNhvlcRInd1XK04=" + "digest": "sha256-Cc9jhJojKlMJ2nG8AUgH++eJJUFMvpQKfAMi2EHRrx0=" } } diff --git a/packages/ui/dist/contracts/settings-panel.json b/packages/ui/dist/contracts/settings-panel.json index 763a61ad2..f33bcf270 100644 --- a/packages/ui/dist/contracts/settings-panel.json +++ b/packages/ui/dist/contracts/settings-panel.json @@ -817,6 +817,6 @@ "copy": { "directory": "copy/settings-panel/", "manifest": "copy/settings-panel/manifest.json", - "digest": "sha256-vLsgXoGOv6Ek2Vt1iEvKgMZAwnYyn2CTBoyAh/wxfJw=" + "digest": "sha256-glxwnegkAvZYJi0GCvPvJPi4IlV8Tczl7pF2VYy/KYc=" } } diff --git a/packages/ui/dist/contracts/sidebar-nav.json b/packages/ui/dist/contracts/sidebar-nav.json index cc2371086..831acf2c6 100644 --- a/packages/ui/dist/contracts/sidebar-nav.json +++ b/packages/ui/dist/contracts/sidebar-nav.json @@ -426,6 +426,6 @@ "copy": { "directory": "copy/sidebar-nav/", "manifest": "copy/sidebar-nav/manifest.json", - "digest": "sha256-vJwnwnVoCLZuwhSZpsPKP7dmOI/CkQQTmVryV7sm25s=" + "digest": "sha256-XWT+KUPg4g4OKKRN7TMBUwPrk7ejk8fiyzBpuM5WPPQ=" } } diff --git a/packages/ui/dist/contracts/skeleton.json b/packages/ui/dist/contracts/skeleton.json index c44cd0130..242075624 100644 --- a/packages/ui/dist/contracts/skeleton.json +++ b/packages/ui/dist/contracts/skeleton.json @@ -282,6 +282,6 @@ "copy": { "directory": "copy/skeleton/", "manifest": "copy/skeleton/manifest.json", - "digest": "sha256-4LwxROheBPrSRHAZZzi9L4TDIlPOW7pk4CjtpDmBKQw=" + "digest": "sha256-Tse4D2OoORQr9mD6VjfJczC882UFnIjNvurneAO/X9U=" } } diff --git a/packages/ui/dist/contracts/skip-link.json b/packages/ui/dist/contracts/skip-link.json index b6fac58ca..d4dd45a4b 100644 --- a/packages/ui/dist/contracts/skip-link.json +++ b/packages/ui/dist/contracts/skip-link.json @@ -289,6 +289,6 @@ "copy": { "directory": "copy/skip-link/", "manifest": "copy/skip-link/manifest.json", - "digest": "sha256-/jHANaZlfExigzc9YSvrmpKwOgJsNkh3BLB4kOMIj5c=" + "digest": "sha256-qToWGFnF2ZHAppCVsK6F37uSNCkaiJa0o9dRC980408=" } } diff --git a/packages/ui/dist/contracts/switch.json b/packages/ui/dist/contracts/switch.json index 8b4b16a5e..0dceb2234 100644 --- a/packages/ui/dist/contracts/switch.json +++ b/packages/ui/dist/contracts/switch.json @@ -395,6 +395,6 @@ "copy": { "directory": "copy/switch/", "manifest": "copy/switch/manifest.json", - "digest": "sha256-YSfVQXXYORkF8TYDuvw8UDQFQ0C2BvhbCcgmyhHx5aE=" + "digest": "sha256-9xj2uziqsoVvDxHlrWeYtax1DhDv15vtgrzyE6M7E80=" } } diff --git a/packages/ui/dist/contracts/table.json b/packages/ui/dist/contracts/table.json index 9f7a6d812..602391570 100644 --- a/packages/ui/dist/contracts/table.json +++ b/packages/ui/dist/contracts/table.json @@ -429,6 +429,6 @@ "copy": { "directory": "copy/table/", "manifest": "copy/table/manifest.json", - "digest": "sha256-uE41ppP3fPQSO1RWxPnhd8Zoqlh9cVyfgTKwwVT5Ajs=" + "digest": "sha256-gr4sDXDH6C1w5B4FlFNPxU1RkmMpBWG+Mx3Ge9fNES0=" } } diff --git a/packages/ui/dist/contracts/tabs.json b/packages/ui/dist/contracts/tabs.json index f150ca10d..622e97934 100644 --- a/packages/ui/dist/contracts/tabs.json +++ b/packages/ui/dist/contracts/tabs.json @@ -398,6 +398,6 @@ "copy": { "directory": "copy/tabs/", "manifest": "copy/tabs/manifest.json", - "digest": "sha256-PM9hfuUIQtvrIekuc8ckBWWQXjPFXTSvcBTd9ovfoQY=" + "digest": "sha256-GdzO1hAPIfEsd0BOsp3t5RLbqZfJkGnn1ZCXXToYFZU=" } } diff --git a/packages/ui/dist/contracts/terminal.json b/packages/ui/dist/contracts/terminal.json index 67217d06f..557972073 100644 --- a/packages/ui/dist/contracts/terminal.json +++ b/packages/ui/dist/contracts/terminal.json @@ -536,6 +536,6 @@ "copy": { "directory": "copy/terminal/", "manifest": "copy/terminal/manifest.json", - "digest": "sha256-Um+BronLZKEFOHCEpSta1jnlVHpAUaE+SY2iEDpTXgA=" + "digest": "sha256-rbo4awKBVvGKzyDFUb4nwHQFmHGbdDfMwwXzGUdAREA=" } } diff --git a/packages/ui/dist/contracts/text-field.json b/packages/ui/dist/contracts/text-field.json index 3a6aa6cba..8e49ce56c 100644 --- a/packages/ui/dist/contracts/text-field.json +++ b/packages/ui/dist/contracts/text-field.json @@ -536,6 +536,6 @@ "copy": { "directory": "copy/text-field/", "manifest": "copy/text-field/manifest.json", - "digest": "sha256-T+FFVaCn+rM3sQkUSAo7Rt0qWttJ1BhryEiHTCNVafE=" + "digest": "sha256-ZFtcAd9B/pkPWzu13gZXvk2xrA55t5jubwRPDjbraks=" } } diff --git a/packages/ui/dist/contracts/textarea.json b/packages/ui/dist/contracts/textarea.json index 90c4402d2..80db73cd7 100644 --- a/packages/ui/dist/contracts/textarea.json +++ b/packages/ui/dist/contracts/textarea.json @@ -493,6 +493,6 @@ "copy": { "directory": "copy/textarea/", "manifest": "copy/textarea/manifest.json", - "digest": "sha256-TWjfrH63Bc/kflpuBQDJbS27RePsfSb9IsUWdkGRiwA=" + "digest": "sha256-MJE8N929g+k7J0CHLayqvw21/OU44JIZ2678hr+A5YQ=" } } diff --git a/packages/ui/dist/contracts/time-picker.json b/packages/ui/dist/contracts/time-picker.json index 1f2def6ca..646c7a4ea 100644 --- a/packages/ui/dist/contracts/time-picker.json +++ b/packages/ui/dist/contracts/time-picker.json @@ -567,6 +567,6 @@ "copy": { "directory": "copy/time-picker/", "manifest": "copy/time-picker/manifest.json", - "digest": "sha256-6dQepccMEMurDmXDGAXKgSfV2lWmb9ekpIZ/3hodceI=" + "digest": "sha256-TsyWY0+4rJxb2osbgC2wSnuTVY1vEQYHcpQelUBOPuc=" } } diff --git a/packages/ui/dist/contracts/timeline.json b/packages/ui/dist/contracts/timeline.json index 0694bf216..e1ebd38bd 100644 --- a/packages/ui/dist/contracts/timeline.json +++ b/packages/ui/dist/contracts/timeline.json @@ -282,6 +282,6 @@ "copy": { "directory": "copy/timeline/", "manifest": "copy/timeline/manifest.json", - "digest": "sha256-0Or3Y8Tm/QMqmLp4lpUHlYERYtvsxQV0B7ZW9XTw6fg=" + "digest": "sha256-I6GYvjBcp+vO3kJk8Fst/bUcq2ZqzEyTlSdwUfdhyu4=" } } diff --git a/packages/ui/dist/contracts/toast.json b/packages/ui/dist/contracts/toast.json index 0207e655b..a75475e48 100644 --- a/packages/ui/dist/contracts/toast.json +++ b/packages/ui/dist/contracts/toast.json @@ -524,6 +524,6 @@ "copy": { "directory": "copy/toast/", "manifest": "copy/toast/manifest.json", - "digest": "sha256-5G6eFKtb0RzEvUaf7y/U2BUwja0sO/DtWmx8/bruQU8=" + "digest": "sha256-cO1fkE2cxytYMT7X5VXymS8J2mqSvNmVpdw8u5n58ZU=" } } diff --git a/packages/ui/dist/contracts/toolbar.json b/packages/ui/dist/contracts/toolbar.json index e867e48c9..1f24891d4 100644 --- a/packages/ui/dist/contracts/toolbar.json +++ b/packages/ui/dist/contracts/toolbar.json @@ -533,6 +533,6 @@ "copy": { "directory": "copy/toolbar/", "manifest": "copy/toolbar/manifest.json", - "digest": "sha256-8hlyqGGelr15H1t7evcG0FBb95rGUZnTNnn/7YboC68=" + "digest": "sha256-zrNVk9H7z4L1LcjXysnS9k61jvrlzeBWR1qX2vhQ10E=" } } diff --git a/packages/ui/dist/contracts/tooltip.json b/packages/ui/dist/contracts/tooltip.json index e6845887a..182c78b8d 100644 --- a/packages/ui/dist/contracts/tooltip.json +++ b/packages/ui/dist/contracts/tooltip.json @@ -357,6 +357,6 @@ "copy": { "directory": "copy/tooltip/", "manifest": "copy/tooltip/manifest.json", - "digest": "sha256-LkcqlVgeLQw44bCRmlXlSU+9P8cA2jVRRTLSgZlvDps=" + "digest": "sha256-Me0HsoZyvQ2n2VjoDO5Lw49BbBBX6TZjPCZ1QmE/0bM=" } } diff --git a/packages/ui/dist/contracts/tree.json b/packages/ui/dist/contracts/tree.json index 1943dc577..08a3f57ee 100644 --- a/packages/ui/dist/contracts/tree.json +++ b/packages/ui/dist/contracts/tree.json @@ -339,6 +339,6 @@ "copy": { "directory": "copy/tree/", "manifest": "copy/tree/manifest.json", - "digest": "sha256-b/wUhzdct+NttP79qt24e+b3XsS9ej8bN1kxxKgJ7m8=" + "digest": "sha256-t6nwj1LYRLPcxFNduvbbCOjxgKAl4ixOUmYtB+vqH9A=" } } diff --git a/packages/ui/dist/contracts/wizard.json b/packages/ui/dist/contracts/wizard.json index 045711804..5b3b82e82 100644 --- a/packages/ui/dist/contracts/wizard.json +++ b/packages/ui/dist/contracts/wizard.json @@ -631,6 +631,6 @@ "copy": { "directory": "copy/wizard/", "manifest": "copy/wizard/manifest.json", - "digest": "sha256-m2daflOEDFk6WotvcUWzd9v4LCJpXkBoOyA2h+etXNI=" + "digest": "sha256-UhjeLs5rph69L+MfnhqE+VaHTj1lp+R96NBkf02w9pY=" } } diff --git a/packages/ui/dist/copy/admin-form/manifest.json b/packages/ui/dist/copy/admin-form/manifest.json index ca39230b9..c193389a4 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "register/text-field.js", "components/text-field.js", - "chunks/native-CAzZmDKR.js", + "chunks/native-BjBt1sUh.js", "register/textarea.js", "components/textarea.js", "register/select.js", "components/select.js", "components/admin-form.js", - "chunks/forms-BT3z7lNC.js" + "chunks/forms-CE_hP1hg.js" ], "files": { - "runtime/register/admin-form.js": "sha256-wbxQ6jG47yRORiZBcV1vZy21o7vLJ0wZWSBjlQ08r5o=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/register/text-field.js": "sha256-DD+ctMlKClOK6B/glshiJwIjKilewzY171GvKtVGf1A=", - "runtime/components/text-field.js": "sha256-6f5tLWwF57IFY+uH5zM0afiU3g09PW3M4772zC7zD4Q=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "runtime/register/textarea.js": "sha256-H+BMjmdgnMxVEA9KvLSSKoOlHTAH91Qy7+pjUiTlgEE=", - "runtime/components/textarea.js": "sha256-qJqDEskuaVeBUFjefVF+KSbJV3s6vpaKCtd4aQ4QtoY=", - "runtime/register/select.js": "sha256-zXXuJRnrp9EVnk1A8VpgUzF/JPShcAImY9zRc6nQasQ=", - "runtime/components/select.js": "sha256-yyq0jsJOysQGTPpFoA1C1aRWSIukrk+M4Ro2ZwCyWbw=", - "runtime/components/admin-form.js": "sha256-aN07ea+gUj6aAxwJjeILpqJFPUQJ27g3LAIjpHmljNg=", - "runtime/chunks/forms-BT3z7lNC.js": "sha256-Txmae07dWLj1H/FL869U0Kv84TQxzpdFeOg0g8zGK6I=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Of5oLJY6n5Yfqu44/xCAuuJEYRoCg4Kr+YZbVggbwZE=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/chunks/choice-Db_w_BOQ.js b/packages/ui/dist/copy/admin-form/runtime/chunks/choice-B7mo5Eq3.js similarity index 98% rename from packages/ui/dist/chunks/choice-Db_w_BOQ.js rename to packages/ui/dist/copy/admin-form/runtime/chunks/choice-B7mo5Eq3.js index aebc478b6..849c80b8b 100644 --- a/packages/ui/dist/chunks/choice-Db_w_BOQ.js +++ b/packages/ui/dist/copy/admin-form/runtime/chunks/choice-B7mo5Eq3.js @@ -31,6 +31,12 @@ function identify(root, node, suffix) { 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]; @@ -929,4 +935,4 @@ function enhanceControls(root) { }; } //#endregion -export { announce as a, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; +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-C1XeXVYC.js b/packages/ui/dist/copy/admin-form/runtime/chunks/element-Dovcr9Ky.js similarity index 99% rename from packages/ui/dist/chunks/element-C1XeXVYC.js rename to packages/ui/dist/copy/admin-form/runtime/chunks/element-Dovcr9Ky.js index a943f150d..aa7a67cb4 100644 --- a/packages/ui/dist/chunks/element-C1XeXVYC.js +++ b/packages/ui/dist/copy/admin-form/runtime/chunks/element-Dovcr9Ky.js @@ -1,4 +1,4 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.js"; +import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; //#region packages/ui/src/internal/element.js var HTMLElementBase = globalThis.HTMLElement ?? class {}; var nextInstance = 0; diff --git a/packages/ui/dist/chunks/forms-BT3z7lNC.js b/packages/ui/dist/copy/admin-form/runtime/chunks/forms-CE_hP1hg.js similarity index 98% rename from packages/ui/dist/chunks/forms-BT3z7lNC.js rename to packages/ui/dist/copy/admin-form/runtime/chunks/forms-CE_hP1hg.js index 65f1f0e71..6ad3b48f5 100644 --- a/packages/ui/dist/chunks/forms-BT3z7lNC.js +++ b/packages/ui/dist/copy/admin-form/runtime/chunks/forms-CE_hP1hg.js @@ -1,4 +1,4 @@ -import { c as make, i as all, o as enabled } from "./choice-Db_w_BOQ.js"; +import { i as all, l as make, o as enabled } from "./choice-B7mo5Eq3.js"; //#region 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"); diff --git a/packages/ui/dist/copy/button-group/runtime/chunks/native-CAzZmDKR.js b/packages/ui/dist/copy/admin-form/runtime/chunks/native-BjBt1sUh.js similarity index 98% rename from packages/ui/dist/copy/button-group/runtime/chunks/native-CAzZmDKR.js rename to packages/ui/dist/copy/admin-form/runtime/chunks/native-BjBt1sUh.js index 558c774e5..032f76c74 100644 --- a/packages/ui/dist/copy/button-group/runtime/chunks/native-CAzZmDKR.js +++ b/packages/ui/dist/copy/admin-form/runtime/chunks/native-BjBt1sUh.js @@ -1,4 +1,4 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.js"; +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 {}; 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 bb59750d7..f786258d5 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,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { t as formComposition } from "../chunks/forms-BT3z7lNC.js"; +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 var J3w1AdminForm = class extends J3w1Element { static componentId = "admin-form"; static version = "4.0.0"; - static implementationId = "sha256-IZWHSSA/uP7yDRqpiKJQsQ05FssMem3lg++QYnGPtDM="; + static implementationId = "sha256-86V5kk3lZt3iA5GdiMBYc8P2mc4pO3KTo02FmkKh71k="; static connect = formComposition; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; 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 f15a0462d..a59b0acab 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Select = class extends J3w1Element { static componentId = "select"; static version = "4.0.0"; - static implementationId = "sha256-x5f4XAk757Fq5+Tl0cEgt1x3VCTPpITjazQZUo+WpvQ="; + static implementationId = "sha256-/4CAqDSF84DTC0pEcQUtcmmtAaVge6ifWVX3elTZzLM="; static connect = fields; static upgradeProperties = [ "disabled", 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 469ab73da..5f6946538 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1TextField = class extends J3w1Element { static componentId = "text-field"; static version = "4.0.0"; - static implementationId = "sha256-zLqXpOHelLAc+ttryZKIkoe3xzw0YRD1AHJXXSXMwdg="; + static implementationId = "sha256-k06i0LBPa/oPe2VNmxbJkBzisp1zcAENq3MeVnKZzAo="; static connect = fields; static upgradeProperties = [ "disabled", 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 35ed045a1..850762b41 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Textarea = class extends J3w1Element { static componentId = "textarea"; static version = "4.0.0"; - static implementationId = "sha256-hrpvVFypogHx9xxUI1Lemq3AlNYBkdbjqujfPFl8BM0="; + static implementationId = "sha256-BoVEmVsZUWTLPVMKc4WLoQfNpjGc4Wy8j7o7zHck1uQ="; static connect = fields; static upgradeProperties = [ "disabled", 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 611bd32a3..a6ac994bb 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import "./text-field.js"; import "./textarea.js"; import "./select.js"; 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 b97661d55..6fcd3d855 100644 --- a/packages/ui/dist/copy/admin-form/runtime/register/select.js +++ b/packages/ui/dist/copy/admin-form/runtime/register/select.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Select } from "../components/select.js"; //#region .cache/ui-build/entries/register/select.js var element = registerElement("j3w1-select", J3w1Select); 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 e3bf71d74..01007e107 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1TextField } from "../components/text-field.js"; //#region .cache/ui-build/entries/register/text-field.js var element = registerElement("j3w1-text-field", J3w1TextField); 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 ea76ce485..2e9a5db69 100644 --- a/packages/ui/dist/copy/admin-form/runtime/register/textarea.js +++ b/packages/ui/dist/copy/admin-form/runtime/register/textarea.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Textarea } from "../components/textarea.js"; //#region .cache/ui-build/entries/register/textarea.js var element = registerElement("j3w1-textarea", J3w1Textarea); diff --git a/packages/ui/dist/copy/alert/manifest.json b/packages/ui/dist/copy/alert/manifest.json index b8ba01ebd..05dcfb4fa 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/alert.js", - "chunks/overlays-C6nlCHqg.js" + "chunks/overlays-Bw8SSDKz.js" ], "files": { - "runtime/register/alert.js": "sha256-da/DH6uAJcK9QeCEbqBELiYsVrWkN9elrGzFJKH78ZI=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/alert.js": "sha256-afRZEs1g1g0l5Fh9oTXjl7R4w6ChNBFZ+N8x/BeJexg=", - "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", + "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-viVrXu+dUgCAMDq7iuljYYljZLxreTt4cQ+40NUQ3Js=", + "runtime/chunks/overlays-Bw8SSDKz.js": "sha256-YrX9CL2A48QwI7COQQ5anYJLPOxpKrIeyz+jtfp+T+I=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-cEV4WAKxLNKgYY5pU9nDVSG4toj5mM7vGZwyE+6Ui8o=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/alert/runtime/chunks/choice-Db_w_BOQ.js b/packages/ui/dist/copy/alert/runtime/chunks/choice-B7mo5Eq3.js similarity index 98% rename from packages/ui/dist/copy/alert/runtime/chunks/choice-Db_w_BOQ.js rename to packages/ui/dist/copy/alert/runtime/chunks/choice-B7mo5Eq3.js index aebc478b6..849c80b8b 100644 --- a/packages/ui/dist/copy/alert/runtime/chunks/choice-Db_w_BOQ.js +++ b/packages/ui/dist/copy/alert/runtime/chunks/choice-B7mo5Eq3.js @@ -31,6 +31,12 @@ function identify(root, node, suffix) { 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]; @@ -929,4 +935,4 @@ function enhanceControls(root) { }; } //#endregion -export { announce as a, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; +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-C1XeXVYC.js b/packages/ui/dist/copy/alert/runtime/chunks/element-Dovcr9Ky.js similarity index 99% rename from packages/ui/dist/copy/avatar/runtime/chunks/element-C1XeXVYC.js rename to packages/ui/dist/copy/alert/runtime/chunks/element-Dovcr9Ky.js index a943f150d..aa7a67cb4 100644 --- a/packages/ui/dist/copy/avatar/runtime/chunks/element-C1XeXVYC.js +++ b/packages/ui/dist/copy/alert/runtime/chunks/element-Dovcr9Ky.js @@ -1,4 +1,4 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.js"; +import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; //#region packages/ui/src/internal/element.js var HTMLElementBase = globalThis.HTMLElement ?? class {}; var nextInstance = 0; diff --git a/packages/ui/dist/copy/alert/runtime/chunks/overlays-C6nlCHqg.js b/packages/ui/dist/copy/alert/runtime/chunks/overlays-Bw8SSDKz.js similarity index 98% rename from packages/ui/dist/copy/alert/runtime/chunks/overlays-C6nlCHqg.js rename to packages/ui/dist/copy/alert/runtime/chunks/overlays-Bw8SSDKz.js index 9df8503ec..3eeb8ff0d 100644 --- a/packages/ui/dist/copy/alert/runtime/chunks/overlays-C6nlCHqg.js +++ b/packages/ui/dist/copy/alert/runtime/chunks/overlays-Bw8SSDKz.js @@ -1,4 +1,4 @@ -import { i as all, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.js"; +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"); diff --git a/packages/ui/dist/copy/alert/runtime/components/alert.js b/packages/ui/dist/copy/alert/runtime/components/alert.js index 24171f944..6c6db1b50 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-C1XeXVYC.js"; -import { t as feedback } from "../chunks/overlays-C6nlCHqg.js"; +import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; +import { t as feedback } from "../chunks/overlays-Bw8SSDKz.js"; //#region .cache/ui-build/entries/components/alert.js var J3w1Alert = class extends J3w1Element { static componentId = "alert"; static version = "4.0.0"; - static implementationId = "sha256-D/UE6iF8Es5ira9X/X3Hlo5OO/Lzy3n/9s9vlkV7zJU="; + static implementationId = "sha256-6Wo+BnYA6udYTk6XDw6PR9MtJYx0FznliTgiGt+lVxo="; static connect = feedback; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/copy/alert/runtime/register/alert.js b/packages/ui/dist/copy/alert/runtime/register/alert.js index c0a9872de..4398942dd 100644 --- a/packages/ui/dist/copy/alert/runtime/register/alert.js +++ b/packages/ui/dist/copy/alert/runtime/register/alert.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Alert } from "../components/alert.js"; //#region .cache/ui-build/entries/register/alert.js var element = registerElement("j3w1-alert", J3w1Alert); diff --git a/packages/ui/dist/copy/avatar/manifest.json b/packages/ui/dist/copy/avatar/manifest.json index 20d0a101a..cc6222be3 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/avatar.js", - "chunks/display-dj9YaBfn.js" + "chunks/display-Jm9bAsnb.js" ], "files": { - "runtime/register/avatar.js": "sha256-5DYNLWi7ycaPY4mr7DXYNOCVEbo97Pnr3INC7MFexbM=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/avatar.js": "sha256-ewC6RhKRQwH+7jEF62lU5q8KPwKXfyEg/JWISD2N/FE=", - "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-XYCR7yVoWMnpJrQG4A+pL3xESyHR6OKMuwJfZGgDpKA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/avatar/runtime/chunks/choice-Db_w_BOQ.js b/packages/ui/dist/copy/avatar/runtime/chunks/choice-B7mo5Eq3.js similarity index 98% rename from packages/ui/dist/copy/avatar/runtime/chunks/choice-Db_w_BOQ.js rename to packages/ui/dist/copy/avatar/runtime/chunks/choice-B7mo5Eq3.js index aebc478b6..849c80b8b 100644 --- a/packages/ui/dist/copy/avatar/runtime/chunks/choice-Db_w_BOQ.js +++ b/packages/ui/dist/copy/avatar/runtime/chunks/choice-B7mo5Eq3.js @@ -31,6 +31,12 @@ function identify(root, node, suffix) { 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]; @@ -929,4 +935,4 @@ function enhanceControls(root) { }; } //#endregion -export { announce as a, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; +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-dj9YaBfn.js b/packages/ui/dist/copy/avatar/runtime/chunks/display-Jm9bAsnb.js similarity index 98% rename from packages/ui/dist/copy/code-editor/runtime/chunks/display-dj9YaBfn.js rename to packages/ui/dist/copy/avatar/runtime/chunks/display-Jm9bAsnb.js index 80833d5da..5bc817830 100644 --- a/packages/ui/dist/copy/code-editor/runtime/chunks/display-dj9YaBfn.js +++ b/packages/ui/dist/copy/avatar/runtime/chunks/display-Jm9bAsnb.js @@ -1,4 +1,4 @@ -import { c as make, i as all, o as enabled } from "./choice-Db_w_BOQ.js"; +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]"); diff --git a/packages/ui/dist/copy/admin-form/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/avatar/runtime/chunks/element-Dovcr9Ky.js similarity index 99% rename from packages/ui/dist/copy/admin-form/runtime/chunks/element-C1XeXVYC.js rename to packages/ui/dist/copy/avatar/runtime/chunks/element-Dovcr9Ky.js index a943f150d..aa7a67cb4 100644 --- a/packages/ui/dist/copy/admin-form/runtime/chunks/element-C1XeXVYC.js +++ b/packages/ui/dist/copy/avatar/runtime/chunks/element-Dovcr9Ky.js @@ -1,4 +1,4 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.js"; +import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; //#region packages/ui/src/internal/element.js var HTMLElementBase = globalThis.HTMLElement ?? class {}; var nextInstance = 0; diff --git a/packages/ui/dist/copy/avatar/runtime/components/avatar.js b/packages/ui/dist/copy/avatar/runtime/components/avatar.js index e173006c6..39f8bb7e4 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-C1XeXVYC.js"; -import { t as avatar } from "../chunks/display-dj9YaBfn.js"; +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 var J3w1Avatar = class extends J3w1Element { static componentId = "avatar"; static version = "4.0.0"; - static implementationId = "sha256-oKaTLRzIK5qK9lvYH/WxVObpYJISyDSenNJcmBSIbAE="; + static implementationId = "sha256-y5w6c1MQTafVvxzhJ5TzYxwGvju264CUxS2D23RvGCQ="; static connect = avatar; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/copy/avatar/runtime/register/avatar.js b/packages/ui/dist/copy/avatar/runtime/register/avatar.js index b2c66d2ae..9367113f3 100644 --- a/packages/ui/dist/copy/avatar/runtime/register/avatar.js +++ b/packages/ui/dist/copy/avatar/runtime/register/avatar.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Avatar } from "../components/avatar.js"; //#region .cache/ui-build/entries/register/avatar.js var element = registerElement("j3w1-avatar", J3w1Avatar); diff --git a/packages/ui/dist/copy/badge/manifest.json b/packages/ui/dist/copy/badge/manifest.json index caf8d9313..c2bc5a593 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/badge.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/badge.js": "sha256-v2MgL8efVFZ4zJl9rvTmIYZxswZz69oeyrHTaYTAojs=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/badge.js": "sha256-l72iC8CAJp/xCXpSX/oJ3xsz8VT4N6UAcVhVSKeC/zs=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-K2TPkFZfKUt35HniL/ub9icdMukZ7wCx0S5+D1FOv8Y=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/badge/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/badge/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/badge/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/badge/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/badge/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/badge/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/badge/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/badge/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/badge/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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/native-CAzZmDKR.js b/packages/ui/dist/copy/badge/runtime/chunks/native-BjBt1sUh.js similarity index 98% rename from packages/ui/dist/chunks/native-CAzZmDKR.js rename to packages/ui/dist/copy/badge/runtime/chunks/native-BjBt1sUh.js index 558c774e5..032f76c74 100644 --- a/packages/ui/dist/chunks/native-CAzZmDKR.js +++ b/packages/ui/dist/copy/badge/runtime/chunks/native-BjBt1sUh.js @@ -1,4 +1,4 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.js"; +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 {}; diff --git a/packages/ui/dist/copy/badge/runtime/components/badge.js b/packages/ui/dist/copy/badge/runtime/components/badge.js index 75cd2918a..640dfde53 100644 --- a/packages/ui/dist/copy/badge/runtime/components/badge.js +++ b/packages/ui/dist/copy/badge/runtime/components/badge.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Badge = class extends J3w1Element { static componentId = "badge"; static version = "4.0.0"; - static implementationId = "sha256-7r4xdzZloUX+vqRo4Hc0GjD4Kj3pwVOKBfHyGYFV4fU="; + static implementationId = "sha256-4j+faVdrUDtcCc6a5/1Y+y9U30DXfpq/Frm/Z0bO1i8="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/copy/badge/runtime/register/badge.js b/packages/ui/dist/copy/badge/runtime/register/badge.js index 9e0027214..2fe7fff68 100644 --- a/packages/ui/dist/copy/badge/runtime/register/badge.js +++ b/packages/ui/dist/copy/badge/runtime/register/badge.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Badge } from "../components/badge.js"; //#region .cache/ui-build/entries/register/badge.js var element = registerElement("j3w1-badge", J3w1Badge); diff --git a/packages/ui/dist/copy/breadcrumbs/manifest.json b/packages/ui/dist/copy/breadcrumbs/manifest.json index a0c181c65..4adf99a77 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/breadcrumbs.js", - "chunks/navigation-Dt8ap-9J.js" + "chunks/navigation-BfNzDYZB.js" ], "files": { - "runtime/register/breadcrumbs.js": "sha256-Q0duBAI2kOEbn33M/8S8M3ciNcrLKYFaLDl2PvMF4MY=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/breadcrumbs.js": "sha256-GtJDiM9iN77t0CIkD7Feiu8A1MQ5DeirIUfSVxO6o7Q=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-pJjvksTD6NTZ2QRx/SBxS4j7xy1rVLprovo5OnTOafs=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/breadcrumbs/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/breadcrumbs/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/breadcrumbs/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/breadcrumbs/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/breadcrumbs/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/breadcrumbs/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/breadcrumbs/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/breadcrumbs/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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-Dt8ap-9J.js b/packages/ui/dist/copy/breadcrumbs/runtime/chunks/navigation-BfNzDYZB.js similarity index 96% rename from packages/ui/dist/chunks/navigation-Dt8ap-9J.js rename to packages/ui/dist/copy/breadcrumbs/runtime/chunks/navigation-BfNzDYZB.js index 81201c8d5..db2779553 100644 --- a/packages/ui/dist/chunks/navigation-Dt8ap-9J.js +++ b/packages/ui/dist/copy/breadcrumbs/runtime/chunks/navigation-BfNzDYZB.js @@ -1,4 +1,4 @@ -import { a as announce, d as rove, f as visible, i as all, l as nativeInput, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.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-B7mo5Eq3.js"; //#region packages/ui/src/behaviors/navigation.js function tabs(root, { on }, listOverride) { const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); @@ -81,7 +81,13 @@ function toolbar(root, { on }) { "End" ].includes(event.key)) return; event.preventDefault(); - rove(items, event.key === next ? index + 1 : event.key === prev ? index - 1 : event.key === "Home" ? 0 : items.length - 1); + 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]"); @@ -321,7 +327,11 @@ function menu(root, { on }) { "End" ].includes(event.key)) { event.preventDefault(); - rove(options, event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : index + (event.key === "ArrowDown" ? 1 : -1)); + 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(); diff --git a/packages/ui/dist/copy/breadcrumbs/runtime/components/breadcrumbs.js b/packages/ui/dist/copy/breadcrumbs/runtime/components/breadcrumbs.js index 8c0afe607..5ce93d88b 100644 --- a/packages/ui/dist/copy/breadcrumbs/runtime/components/breadcrumbs.js +++ b/packages/ui/dist/copy/breadcrumbs/runtime/components/breadcrumbs.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as disclosure } from "../chunks/navigation-Dt8ap-9J.js"; +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 var J3w1Breadcrumbs = class extends J3w1Element { static componentId = "breadcrumbs"; static version = "4.0.0"; - static implementationId = "sha256-87YN9cPa7cDF4Ft74THtpIUQxKKqJQXA7fCZzmQ5DwA="; + static implementationId = "sha256-9uiBLPIbEVI200s39xDO7x0K09v+wPg5xcoMI5B5TbY="; static connect = disclosure; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/copy/breadcrumbs/runtime/register/breadcrumbs.js b/packages/ui/dist/copy/breadcrumbs/runtime/register/breadcrumbs.js index 087fe5e6b..1b41f187d 100644 --- a/packages/ui/dist/copy/breadcrumbs/runtime/register/breadcrumbs.js +++ b/packages/ui/dist/copy/breadcrumbs/runtime/register/breadcrumbs.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Breadcrumbs } from "../components/breadcrumbs.js"; //#region .cache/ui-build/entries/register/breadcrumbs.js var element = registerElement("j3w1-breadcrumbs", J3w1Breadcrumbs); diff --git a/packages/ui/dist/copy/button-group/manifest.json b/packages/ui/dist/copy/button-group/manifest.json index f85380925..477cf8cbb 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/button-group.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/button-group.js": "sha256-iOfzUy8ZfhYmriDjbhxJtVBL2w+EPgppfO8UNoOm6QM=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/button-group.js": "sha256-9kyXdp1HjHBA1/8MAvS/4B8TzQnyUUIVFbxkMteeCH4=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-f5VJ2bwUNXUnsb5AcdxUYbcOC7PeghM/cnXvDSuGuMs=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/button-group/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/button-group/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/button-group/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/button-group/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/button-group/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/button-group/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/button-group/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/button-group/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/button-group/runtime/chunks/native-BjBt1sUh.js similarity index 98% rename from packages/ui/dist/copy/admin-form/runtime/chunks/native-CAzZmDKR.js rename to packages/ui/dist/copy/button-group/runtime/chunks/native-BjBt1sUh.js index 558c774e5..032f76c74 100644 --- a/packages/ui/dist/copy/admin-form/runtime/chunks/native-CAzZmDKR.js +++ b/packages/ui/dist/copy/button-group/runtime/chunks/native-BjBt1sUh.js @@ -1,4 +1,4 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.js"; +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 {}; 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 aaa99816c..e5443b0f9 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-C1XeXVYC.js"; -import { t as actions } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1ButtonGroup = class extends J3w1Element { static componentId = "button-group"; static version = "4.0.0"; - static implementationId = "sha256-4nMwz9kpZ4odBRA12jsDZ86Fx+dDkBCJD7OkQHdIGDY="; + static implementationId = "sha256-QC6YHzPpUytpyeDknjyX9Ke/akglG1NzBtJnCYjqgaA="; static connect = actions; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...[ 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 81edee7d1..86bb9c765 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1ButtonGroup } from "../components/button-group.js"; //#region .cache/ui-build/entries/register/button-group.js var element = registerElement("j3w1-button-group", J3w1ButtonGroup); diff --git a/packages/ui/dist/copy/button/manifest.json b/packages/ui/dist/copy/button/manifest.json index c3b593350..6509677e1 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/button.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/button.js": "sha256-nrgSUK+JnRhipV1b5VKANBtP+ap6ANYd4xnpZYpHYM0=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/button.js": "sha256-uMPPvidQWPs9e0OGW6Q+cI2izylinOUSgrBAM94vxAA=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-79ycU5ojNv1Z2yHzJ6KXDmshFL1we3mQNOoIwfMXnyg=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/button/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/button/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/button/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/button/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/button/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/button/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/button/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/button/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/button/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/button/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/button/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/button.js b/packages/ui/dist/copy/button/runtime/components/button.js index 13b2ecc87..3dfd4d373 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-C1XeXVYC.js"; -import { t as actions } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Button = class extends J3w1Element { static componentId = "button"; static version = "4.0.0"; - static implementationId = "sha256-KJsije7hrwEBTy2GsHhegHPN50aD1js7EUW9wwGysM4="; + static implementationId = "sha256-5XqIG0jRl2EIptqWgZIiuSKdNf0pHpMOZB14A1W3DqU="; static connect = actions; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...[ diff --git a/packages/ui/dist/copy/button/runtime/register/button.js b/packages/ui/dist/copy/button/runtime/register/button.js index 8d63fb5fe..b01aa4dae 100644 --- a/packages/ui/dist/copy/button/runtime/register/button.js +++ b/packages/ui/dist/copy/button/runtime/register/button.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Button } from "../components/button.js"; //#region .cache/ui-build/entries/register/button.js var element = registerElement("j3w1-button", J3w1Button); diff --git a/packages/ui/dist/copy/card/manifest.json b/packages/ui/dist/copy/card/manifest.json index e606058b0..ec4dc3464 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/card.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/card.js": "sha256-zbAWuZuKNPZkVbl9pW5S2Mzg9/mlHJ7BeQEgQAUhrlA=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/card.js": "sha256-REUcny20Az6YiLn0F6l0ZkmNrj18xAqRj9bWUmvkhLo=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-pfXQBPkrp6iF0OlQiLQh9DMUwtsCinOaL1HLAjlChII=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/card/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/card/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/card/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/card/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/card/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/card/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/card/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/card/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/card/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/card/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/card/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/card.js b/packages/ui/dist/copy/card/runtime/components/card.js index a5ee729a4..9981d665b 100644 --- a/packages/ui/dist/copy/card/runtime/components/card.js +++ b/packages/ui/dist/copy/card/runtime/components/card.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Card = class extends J3w1Element { static componentId = "card"; static version = "4.0.0"; - static implementationId = "sha256-vQnfoIzeMEvjY3vf6ySomBbeDdh5YPzSMoXDvmtgOro="; + static implementationId = "sha256-1zEhR7grQaSCkJEXxbq66aFLUPYuFPcwf/JnBD3tNdQ="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/copy/card/runtime/register/card.js b/packages/ui/dist/copy/card/runtime/register/card.js index 31cc0f59d..2a9535cee 100644 --- a/packages/ui/dist/copy/card/runtime/register/card.js +++ b/packages/ui/dist/copy/card/runtime/register/card.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Card } from "../components/card.js"; //#region .cache/ui-build/entries/register/card.js var element = registerElement("j3w1-card", J3w1Card); diff --git a/packages/ui/dist/copy/chart/manifest.json b/packages/ui/dist/copy/chart/manifest.json index 72e49bb9b..3ce508443 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/chart.js", - "chunks/display-dj9YaBfn.js" + "chunks/display-Jm9bAsnb.js" ], "files": { - "runtime/register/chart.js": "sha256-5iBwKSjcyRylARXTeL2emhbuI2FCMQ757IBdPqFnU0U=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/chart.js": "sha256-J4rkX+ylh8URHbl2DxJ2FtbkHBtan2UOpNGVJIh1LjQ=", - "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-/W9/IEOepx6zAHtGcRJs1x0lwfMFkVEiYDCV4y4byXw=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/chart/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/chart/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/chart/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/avatar/runtime/chunks/display-dj9YaBfn.js b/packages/ui/dist/copy/chart/runtime/chunks/display-Jm9bAsnb.js similarity index 98% rename from packages/ui/dist/copy/avatar/runtime/chunks/display-dj9YaBfn.js rename to packages/ui/dist/copy/chart/runtime/chunks/display-Jm9bAsnb.js index 80833d5da..5bc817830 100644 --- a/packages/ui/dist/copy/avatar/runtime/chunks/display-dj9YaBfn.js +++ b/packages/ui/dist/copy/chart/runtime/chunks/display-Jm9bAsnb.js @@ -1,4 +1,4 @@ -import { c as make, i as all, o as enabled } from "./choice-Db_w_BOQ.js"; +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]"); diff --git a/packages/ui/dist/copy/chart/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/chart/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/chart/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/chart/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/chart/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 2f3f33b51..70d90b671 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-C1XeXVYC.js"; -import { n as chart } from "../chunks/display-dj9YaBfn.js"; +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 var J3w1Chart = class extends J3w1Element { static componentId = "chart"; static version = "4.0.0"; - static implementationId = "sha256-HoAvhRRdFv6zYSIR6McpxJvYeGHHbg4t1zBpi2x1EXo="; + static implementationId = "sha256-48dT14XNNF9ZyV4PB4oLs8zT/lNQqNt9rXZCl9gUYVc="; static connect = chart; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/copy/chart/runtime/register/chart.js b/packages/ui/dist/copy/chart/runtime/register/chart.js index 17feb810e..8efbe0a3f 100644 --- a/packages/ui/dist/copy/chart/runtime/register/chart.js +++ b/packages/ui/dist/copy/chart/runtime/register/chart.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Chart } from "../components/chart.js"; //#region .cache/ui-build/entries/register/chart.js var element = registerElement("j3w1-chart", J3w1Chart); diff --git a/packages/ui/dist/copy/checkbox/manifest.json b/packages/ui/dist/copy/checkbox/manifest.json index d32a6ce7d..5111a88a3 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/checkbox.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/checkbox.js": "sha256-Bcfx68O9tVUsOU2UXt39Iw36ZluRIGYHI88jMpSDEjk=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/checkbox.js": "sha256-dKDUoVoQi9btazDX3FlRb0fnVzLkYEN+W08CewNGTnI=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-PpwiBtqgcGIHn1KgKDXvrsX0DeTZ4PfyQsMnUpwCUrI=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/checkbox/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/checkbox/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/checkbox/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/checkbox/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/checkbox/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/checkbox/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/checkbox/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/checkbox/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/checkbox/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/checkbox/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/checkbox/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/checkbox.js b/packages/ui/dist/copy/checkbox/runtime/components/checkbox.js index 508ce70fe..8d7e19060 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Checkbox = class extends J3w1Element { static componentId = "checkbox"; static version = "4.0.0"; - static implementationId = "sha256-s8QNllrpQfjPHm0Utgbm9jpMpGxi8Z+bEb83jPZVomQ="; + static implementationId = "sha256-Izbz5fVyhrSfF5rLvCHcElWnQgwhYuvOSm5StKMlqUg="; static connect = fields; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/copy/checkbox/runtime/register/checkbox.js b/packages/ui/dist/copy/checkbox/runtime/register/checkbox.js index 0e3541551..70632e2d0 100644 --- a/packages/ui/dist/copy/checkbox/runtime/register/checkbox.js +++ b/packages/ui/dist/copy/checkbox/runtime/register/checkbox.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Checkbox } from "../components/checkbox.js"; //#region .cache/ui-build/entries/register/checkbox.js var element = registerElement("j3w1-checkbox", J3w1Checkbox); diff --git a/packages/ui/dist/copy/chip/manifest.json b/packages/ui/dist/copy/chip/manifest.json index 2ca77473a..bda82590f 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/chip.js", - "chunks/overlays-C6nlCHqg.js" + "chunks/overlays-Bw8SSDKz.js" ], "files": { - "runtime/register/chip.js": "sha256-nhg2cNNdf2EtWAVdLGFMWDTHx5f02Oe0Zf06cTV+sY8=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/chip.js": "sha256-u34FDCir8vK2ro61A5etBvzomb22WIhnIx7vL6Xcf3k=", - "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", + "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-zqlDj7D8NyN4xQ/pnlXuOTnA8NlRXPBwW6qG+JcjoDY=", + "runtime/chunks/overlays-Bw8SSDKz.js": "sha256-YrX9CL2A48QwI7COQQ5anYJLPOxpKrIeyz+jtfp+T+I=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-nKS3XC8eLjQCMMZHRRKSiHiaNGZgYD6CXzVULJoDU3g=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/chip/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/chip/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/chip/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/chip/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/chip/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/chip/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/chip/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/chip/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/chip/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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/dialog/runtime/chunks/overlays-C6nlCHqg.js b/packages/ui/dist/copy/chip/runtime/chunks/overlays-Bw8SSDKz.js similarity index 98% rename from packages/ui/dist/copy/dialog/runtime/chunks/overlays-C6nlCHqg.js rename to packages/ui/dist/copy/chip/runtime/chunks/overlays-Bw8SSDKz.js index 9df8503ec..3eeb8ff0d 100644 --- a/packages/ui/dist/copy/dialog/runtime/chunks/overlays-C6nlCHqg.js +++ b/packages/ui/dist/copy/chip/runtime/chunks/overlays-Bw8SSDKz.js @@ -1,4 +1,4 @@ -import { i as all, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.js"; +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"); diff --git a/packages/ui/dist/copy/chip/runtime/components/chip.js b/packages/ui/dist/copy/chip/runtime/components/chip.js index 4f4800574..749a8cf86 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-C1XeXVYC.js"; -import { t as feedback } from "../chunks/overlays-C6nlCHqg.js"; +import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; +import { t as feedback } from "../chunks/overlays-Bw8SSDKz.js"; //#region .cache/ui-build/entries/components/chip.js var J3w1Chip = class extends J3w1Element { static componentId = "chip"; static version = "4.0.0"; - static implementationId = "sha256-WS0ZeKkxMPrlmT3er+h8PDDvz5rjH0e3bLmPLD+4egE="; + static implementationId = "sha256-AQdMwG6TMuURDhU/UWs7oHW2L2skw4ISgrH4cwOomvk="; static connect = feedback; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/copy/chip/runtime/register/chip.js b/packages/ui/dist/copy/chip/runtime/register/chip.js index 399954b1a..d6b89d151 100644 --- a/packages/ui/dist/copy/chip/runtime/register/chip.js +++ b/packages/ui/dist/copy/chip/runtime/register/chip.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Chip } from "../components/chip.js"; //#region .cache/ui-build/entries/register/chip.js var element = registerElement("j3w1-chip", J3w1Chip); diff --git a/packages/ui/dist/copy/code-editor/manifest.json b/packages/ui/dist/copy/code-editor/manifest.json index 86ba2212d..4ea3684e8 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/code-editor.js", - "chunks/display-dj9YaBfn.js" + "chunks/display-Jm9bAsnb.js" ], "files": { - "runtime/register/code-editor.js": "sha256-agRsxgm8tBPEgLi7nGnYfqB/KOMRnbad/Eph3+YfYnE=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/code-editor.js": "sha256-F0O1Zc5wQaq5NGzIEEBzGXHEfj0hUaCR23D2hnUukLY=", - "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-X9h2Mxr0yLKLoKffZDsC55HBiRmSX+SuRQkjkcxerOo=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/code-editor/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/code-editor/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/code-editor/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/chunks/display-dj9YaBfn.js b/packages/ui/dist/copy/code-editor/runtime/chunks/display-Jm9bAsnb.js similarity index 98% rename from packages/ui/dist/chunks/display-dj9YaBfn.js rename to packages/ui/dist/copy/code-editor/runtime/chunks/display-Jm9bAsnb.js index 80833d5da..5bc817830 100644 --- a/packages/ui/dist/chunks/display-dj9YaBfn.js +++ b/packages/ui/dist/copy/code-editor/runtime/chunks/display-Jm9bAsnb.js @@ -1,4 +1,4 @@ -import { c as make, i as all, o as enabled } from "./choice-Db_w_BOQ.js"; +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]"); diff --git a/packages/ui/dist/copy/code-editor/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/code-editor/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/code-editor/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/code-editor/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/code-editor/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 5d700d661..9a989eb60 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-C1XeXVYC.js"; -import { r as developerView } from "../chunks/display-dj9YaBfn.js"; +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 var J3w1CodeEditor = class extends J3w1Element { static componentId = "code-editor"; static version = "4.0.0"; - static implementationId = "sha256-SfbKlWOepDm9juxt9BZYRBuYIPkdwFye18Fx+JebtX8="; + static implementationId = "sha256-BBPVGsJGf2n0c4gfyDdfHQH3KYYqmiAAqqC2h3DlIcc="; static connect = developerView; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; 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 ebfebc300..91f3f8d5f 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1CodeEditor } from "../components/code-editor.js"; //#region .cache/ui-build/entries/register/code-editor.js var element = registerElement("j3w1-code-editor", J3w1CodeEditor); diff --git a/packages/ui/dist/copy/combobox/manifest.json b/packages/ui/dist/copy/combobox/manifest.json index 7da01c962..e0b4d3f38 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/combobox.js", - "chunks/navigation-Dt8ap-9J.js" + "chunks/navigation-BfNzDYZB.js" ], "files": { - "runtime/register/combobox.js": "sha256-wSm80gvqOsgkhwOnsCIjr2a4w8W7WCRQqBXn2frDhak=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/combobox.js": "sha256-5b1Sa2zwhRyysK9sVyLiBCGsYfJyYnfGDsb6r3sA9MA=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-f4pI9RLIKYsRggzuVcLA2zYdXHZXY3+DbGFjvBCtbSg=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/combobox/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/combobox/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/combobox/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/combobox/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/combobox/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/combobox/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/combobox/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/combobox/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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-Dt8ap-9J.js b/packages/ui/dist/copy/combobox/runtime/chunks/navigation-BfNzDYZB.js similarity index 96% rename from packages/ui/dist/copy/breadcrumbs/runtime/chunks/navigation-Dt8ap-9J.js rename to packages/ui/dist/copy/combobox/runtime/chunks/navigation-BfNzDYZB.js index 81201c8d5..db2779553 100644 --- a/packages/ui/dist/copy/breadcrumbs/runtime/chunks/navigation-Dt8ap-9J.js +++ b/packages/ui/dist/copy/combobox/runtime/chunks/navigation-BfNzDYZB.js @@ -1,4 +1,4 @@ -import { a as announce, d as rove, f as visible, i as all, l as nativeInput, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.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-B7mo5Eq3.js"; //#region packages/ui/src/behaviors/navigation.js function tabs(root, { on }, listOverride) { const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); @@ -81,7 +81,13 @@ function toolbar(root, { on }) { "End" ].includes(event.key)) return; event.preventDefault(); - rove(items, event.key === next ? index + 1 : event.key === prev ? index - 1 : event.key === "Home" ? 0 : items.length - 1); + 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]"); @@ -321,7 +327,11 @@ function menu(root, { on }) { "End" ].includes(event.key)) { event.preventDefault(); - rove(options, event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : index + (event.key === "ArrowDown" ? 1 : -1)); + 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(); diff --git a/packages/ui/dist/copy/combobox/runtime/components/combobox.js b/packages/ui/dist/copy/combobox/runtime/components/combobox.js index 1f90d0d0a..098363263 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-C1XeXVYC.js"; -import { t as combobox } from "../chunks/navigation-Dt8ap-9J.js"; +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 var J3w1Combobox = class extends J3w1Element { static componentId = "combobox"; static version = "4.0.0"; - static implementationId = "sha256-XA3Nl+ZVgrypCgx4FjdKKQnMCNyoA+F8ID8i2Tjo8lY="; + static implementationId = "sha256-vBw1BDsNiy6oYSbmjgh7x2T+43b2GYa+XmHte/upgpQ="; static connect = combobox; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/copy/combobox/runtime/register/combobox.js b/packages/ui/dist/copy/combobox/runtime/register/combobox.js index 7469ac395..0441f87e8 100644 --- a/packages/ui/dist/copy/combobox/runtime/register/combobox.js +++ b/packages/ui/dist/copy/combobox/runtime/register/combobox.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Combobox } from "../components/combobox.js"; //#region .cache/ui-build/entries/register/combobox.js var element = registerElement("j3w1-combobox", J3w1Combobox); diff --git a/packages/ui/dist/copy/command-palette/manifest.json b/packages/ui/dist/copy/command-palette/manifest.json index 3fd9e71e4..212030ab4 100644 --- a/packages/ui/dist/copy/command-palette/manifest.json +++ b/packages/ui/dist/copy/command-palette/manifest.json @@ -5,18 +5,18 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/command-palette.md", "dependencies": [ "register/command-palette.js", - "chunks/element-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/command-palette.js", - "chunks/advanced-DCpe8Ndv.js", + "chunks/advanced-CqBF0dSb.js", "chunks/markup-DeQ4bEMR.js" ], "files": { - "runtime/register/command-palette.js": "sha256-lGGoaVMCbjDzpQkjNlUs9K1jnmKtBfQi/K3dG35cCd0=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/command-palette.js": "sha256-KMSKyY2a0yyVe6zxGdWjBFFsgbL/DjNUvU8lnxB6USQ=", - "runtime/chunks/advanced-DCpe8Ndv.js": "sha256-nr1LFdLYsGeTM4vDyldvuJygRm0F04sYonxatySPu1g=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-sXrks2txpylBLDX4L9vKPIvAj11p73qrX0apfh7EgTg=", diff --git a/packages/ui/dist/copy/command-palette/runtime/chunks/advanced-DCpe8Ndv.js b/packages/ui/dist/copy/command-palette/runtime/chunks/advanced-CqBF0dSb.js similarity index 97% rename from packages/ui/dist/copy/command-palette/runtime/chunks/advanced-DCpe8Ndv.js rename to packages/ui/dist/copy/command-palette/runtime/chunks/advanced-CqBF0dSb.js index 3390a044c..4a5c45981 100644 --- a/packages/ui/dist/copy/command-palette/runtime/chunks/advanced-DCpe8Ndv.js +++ b/packages/ui/dist/copy/command-palette/runtime/chunks/advanced-CqBF0dSb.js @@ -1,4 +1,4 @@ -import { d as rove, f as visible, i as all, l as nativeInput, o as enabled, s as identify } from "./choice-Db_w_BOQ.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-B7mo5Eq3.js"; import { t as IDREFS } from "./markup-DeQ4bEMR.js"; //#region packages/ui/src/behaviors/advanced.js function tree(root, { on }) { @@ -64,7 +64,12 @@ function tree(root, { on }) { "End" ].includes(event.key)) { event.preventDefault(); - const next = event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : Math.max(0, Math.min(options.length - 1, index + (event.key === "ArrowDown" ? 1 : -1))); + const next = keyIndex({ + key: event.key, + index, + length: options.length, + wrap: false + }); rove(options, next); } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight")) { event.preventDefault(); 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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/command-palette/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/command-palette/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/command-palette/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/command-palette/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/command-palette/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/command-palette/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/command-palette/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/command-palette/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/command-palette/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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/command-palette/runtime/components/command-palette.js b/packages/ui/dist/copy/command-palette/runtime/components/command-palette.js index 9f69c3926..196ad7f12 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-C1XeXVYC.js"; -import { t as commandPalette } from "../chunks/advanced-DCpe8Ndv.js"; +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 var J3w1CommandPalette = class extends J3w1Element { static componentId = "command-palette"; static version = "4.0.0"; - static implementationId = "sha256-z/FYgCRAmaHrY3I9P3qJz8fOSSDfrjxFjAqwEVhzk50="; + static implementationId = "sha256-jnhxb+w/Xgrb5Os9Dxr1YHn/ex7fLJlGLSWZSpbrAuU="; static connect = commandPalette; static upgradeProperties = [ "disabled", 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 21d0307af..8c4d129ed 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1CommandPalette } from "../components/command-palette.js"; //#region .cache/ui-build/entries/register/command-palette.js var element = registerElement("j3w1-command-palette", J3w1CommandPalette); diff --git a/packages/ui/dist/copy/compact-dashboard/manifest.json b/packages/ui/dist/copy/compact-dashboard/manifest.json index 135342a39..43616095c 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "register/chart.js", "components/chart.js", - "chunks/display-dj9YaBfn.js", + "chunks/display-Jm9bAsnb.js", "components/compact-dashboard.js", - "chunks/compositions-d6BkKTYf.js", - "chunks/navigation-Dt8ap-9J.js" + "chunks/compositions-D57dCsBz.js", + "chunks/navigation-BfNzDYZB.js" ], "files": { - "runtime/register/compact-dashboard.js": "sha256-+hjjezkupB41oBwwJyLeQY5FNxI9eXWs5VsP2irSgxY=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/register/chart.js": "sha256-5iBwKSjcyRylARXTeL2emhbuI2FCMQ757IBdPqFnU0U=", - "runtime/components/chart.js": "sha256-J4rkX+ylh8URHbl2DxJ2FtbkHBtan2UOpNGVJIh1LjQ=", - "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", - "runtime/components/compact-dashboard.js": "sha256-AyJRimILR3ZhpG7LU6Jtut1sQj0LSEFhOC9MT+gVfbQ=", - "runtime/chunks/compositions-d6BkKTYf.js": "sha256-El5csGAVMeeZWmJ1ztdXW3O3t2AQPrf3YrEOMkGX17c=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-CK9kd2wDntxSLF6J4F4+3SFybCPdr/tSqL7xJpw3hFs=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/compact-dashboard/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/compact-dashboard/runtime/chunks/compositions-d6BkKTYf.js b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/compositions-D57dCsBz.js similarity index 94% rename from packages/ui/dist/copy/compact-dashboard/runtime/chunks/compositions-d6BkKTYf.js rename to packages/ui/dist/copy/compact-dashboard/runtime/chunks/compositions-D57dCsBz.js index 7d70275f2..f1da4562e 100644 --- a/packages/ui/dist/copy/compact-dashboard/runtime/chunks/compositions-d6BkKTYf.js +++ b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/compositions-D57dCsBz.js @@ -1,5 +1,5 @@ -import { i as all, o as enabled } from "./choice-Db_w_BOQ.js"; -import { i as tabs } from "./navigation-Dt8ap-9J.js"; +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 function fileBrowser(root, { on }) { const query = root.querySelector("[data-file-query]"), rows = all(root, "tr[data-file-id]"), status = root.querySelector("[data-file-status]"); 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 new file mode 100644 index 000000000..5bc817830 --- /dev/null +++ b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/display-Jm9bAsnb.js @@ -0,0 +1,212 @@ +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-dj9YaBfn.js b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/display-dj9YaBfn.js deleted file mode 100644 index 80833d5da..000000000 --- a/packages/ui/dist/copy/compact-dashboard/runtime/chunks/display-dj9YaBfn.js +++ /dev/null @@ -1,212 +0,0 @@ -import { c as make, i as all, o as enabled } from "./choice-Db_w_BOQ.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/element-C1XeXVYC.js b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/compact-dashboard/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/compact-dashboard/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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-Dt8ap-9J.js b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/navigation-BfNzDYZB.js similarity index 96% rename from packages/ui/dist/copy/combobox/runtime/chunks/navigation-Dt8ap-9J.js rename to packages/ui/dist/copy/compact-dashboard/runtime/chunks/navigation-BfNzDYZB.js index 81201c8d5..db2779553 100644 --- a/packages/ui/dist/copy/combobox/runtime/chunks/navigation-Dt8ap-9J.js +++ b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/navigation-BfNzDYZB.js @@ -1,4 +1,4 @@ -import { a as announce, d as rove, f as visible, i as all, l as nativeInput, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.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-B7mo5Eq3.js"; //#region packages/ui/src/behaviors/navigation.js function tabs(root, { on }, listOverride) { const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); @@ -81,7 +81,13 @@ function toolbar(root, { on }) { "End" ].includes(event.key)) return; event.preventDefault(); - rove(items, event.key === next ? index + 1 : event.key === prev ? index - 1 : event.key === "Home" ? 0 : items.length - 1); + 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]"); @@ -321,7 +327,11 @@ function menu(root, { on }) { "End" ].includes(event.key)) { event.preventDefault(); - rove(options, event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : index + (event.key === "ArrowDown" ? 1 : -1)); + 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(); 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 2f3f33b51..70d90b671 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-C1XeXVYC.js"; -import { n as chart } from "../chunks/display-dj9YaBfn.js"; +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 var J3w1Chart = class extends J3w1Element { static componentId = "chart"; static version = "4.0.0"; - static implementationId = "sha256-HoAvhRRdFv6zYSIR6McpxJvYeGHHbg4t1zBpi2x1EXo="; + static implementationId = "sha256-48dT14XNNF9ZyV4PB4oLs8zT/lNQqNt9rXZCl9gUYVc="; static connect = chart; static upgradeProperties = [ "disabled", 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 dd2296be0..b29237379 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,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { t as dashboard } from "../chunks/compositions-d6BkKTYf.js"; +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 var J3w1CompactDashboard = class extends J3w1Element { static componentId = "compact-dashboard"; static version = "4.0.0"; - static implementationId = "sha256-HehbhZc0CAfJPPd19KsqWamAD2EgvREZQU0pBPncnJI="; + static implementationId = "sha256-Shp675PVGMGOiXxiKpeWEQHQugGKEIbNO/jz8KwP4m0="; static connect = dashboard; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; 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 17feb810e..8efbe0a3f 100644 --- a/packages/ui/dist/copy/compact-dashboard/runtime/register/chart.js +++ b/packages/ui/dist/copy/compact-dashboard/runtime/register/chart.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Chart } from "../components/chart.js"; //#region .cache/ui-build/entries/register/chart.js var element = registerElement("j3w1-chart", J3w1Chart); 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 93010f858..6a2980828 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import "./chart.js"; import { J3w1CompactDashboard } from "../components/compact-dashboard.js"; //#region .cache/ui-build/entries/register/compact-dashboard.js diff --git a/packages/ui/dist/copy/data-table/manifest.json b/packages/ui/dist/copy/data-table/manifest.json index 98d99f255..1c2dbeaea 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "register/menu.js", "components/menu.js", - "chunks/navigation-Dt8ap-9J.js", + "chunks/navigation-BfNzDYZB.js", "components/data-table.js", - "chunks/tables-B25ydUHs.js" + "chunks/tables-Cjr1EIJz.js" ], "files": { - "runtime/register/data-table.js": "sha256-BtE8hPANffhtRYhX+PBKWwtZUJMtlvG/m3ctxaSCwTU=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/register/menu.js": "sha256-YX+9ydadaIbkPIBFhLWX4Jv3V9vIl4UY1qolxLGfZUg=", - "runtime/components/menu.js": "sha256-AMtJth+M+4jqb8imqdn9VcM3aKvtgCWkPySfsI7htH8=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "runtime/components/data-table.js": "sha256-jj60XwNxQlssKZTff5HB9Z6v14UDZdK8O80kLP082l4=", - "runtime/chunks/tables-B25ydUHs.js": "sha256-XqRdyfrSS93rVybWHq6a0WhrmZgaboHi5n8ymgwRbM8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-aygLfHiZmFXenQHQrHnjVcw8W0tp2SLdB7d/laGcKgA=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/data-table/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/data-table/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/data-table/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/data-table/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/data-table/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/data-table/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/data-table/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/data-table/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..db2779553 --- /dev/null +++ b/packages/ui/dist/copy/data-table/runtime/chunks/navigation-BfNzDYZB.js @@ -0,0 +1,377 @@ +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-Dt8ap-9J.js b/packages/ui/dist/copy/data-table/runtime/chunks/navigation-Dt8ap-9J.js deleted file mode 100644 index 81201c8d5..000000000 --- a/packages/ui/dist/copy/data-table/runtime/chunks/navigation-Dt8ap-9J.js +++ /dev/null @@ -1,367 +0,0 @@ -import { a as announce, d as rove, f as visible, i as all, l as nativeInput, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.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, event.key === next ? index + 1 : event.key === prev ? index - 1 : event.key === "Home" ? 0 : items.length - 1); - }); - 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, event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : index + (event.key === "ArrowDown" ? 1 : -1)); - } 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/filterable-table/runtime/chunks/tables-B25ydUHs.js b/packages/ui/dist/copy/data-table/runtime/chunks/tables-Cjr1EIJz.js similarity index 96% rename from packages/ui/dist/copy/filterable-table/runtime/chunks/tables-B25ydUHs.js rename to packages/ui/dist/copy/data-table/runtime/chunks/tables-Cjr1EIJz.js index 172bab830..f82aaf25e 100644 --- a/packages/ui/dist/copy/filterable-table/runtime/chunks/tables-B25ydUHs.js +++ b/packages/ui/dist/copy/data-table/runtime/chunks/tables-Cjr1EIJz.js @@ -1,4 +1,4 @@ -import { d as rove, i as all, o as enabled, s as identify } from "./choice-Db_w_BOQ.js"; +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]; @@ -106,7 +106,12 @@ function table(root, { on }) { "End" ].includes(event.key)) return; event.preventDefault(); - const nextIndex = event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : Math.max(0, Math.min(options.length - 1, index + (event.key === "ArrowDown" ? 1 : -1))); + const nextIndex = keyIndex({ + key: event.key, + index, + length: options.length, + wrap: false + }); const next = rove(options, nextIndex); if (event.shiftKey && selectAll) { anchor ??= row; 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 79b133ce4..2825525ad 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-C1XeXVYC.js"; -import { n as table } from "../chunks/tables-B25ydUHs.js"; +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 var J3w1DataTable = class extends J3w1Element { static componentId = "data-table"; static version = "4.0.0"; - static implementationId = "sha256-QMe+oF071lb63bTNZ9n1ib/8bWgy27tciSjWJEfBgrk="; + static implementationId = "sha256-Qlh9cF0ylT3FE8z6iBYaA9/noI1T5dVrNgulqEfZGt8="; static connect = table; static upgradeProperties = [ "disabled", 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 3f1e4b50c..b35ceb43e 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-C1XeXVYC.js"; -import { r as menu } from "../chunks/navigation-Dt8ap-9J.js"; +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 var J3w1Menu = class extends J3w1Element { static componentId = "menu"; static version = "4.0.0"; - static implementationId = "sha256-jIlJcU1Nx7Q5MB7Fqfcn4f9vr0IW1gmGwNdP5Rk72Aw="; + static implementationId = "sha256-oS0Ubl9rLRKcmk22aO7KDARBpUoA/Y7sR2AvyqabH+U="; static connect = menu; static upgradeProperties = [ "disabled", 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 9b565eed9..4d622c48b 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import "./menu.js"; import { J3w1DataTable } from "../components/data-table.js"; //#region .cache/ui-build/entries/register/data-table.js 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 734c05e98..655b77a5a 100644 --- a/packages/ui/dist/copy/data-table/runtime/register/menu.js +++ b/packages/ui/dist/copy/data-table/runtime/register/menu.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Menu } from "../components/menu.js"; //#region .cache/ui-build/entries/register/menu.js var element = registerElement("j3w1-menu", J3w1Menu); diff --git a/packages/ui/dist/copy/date-picker/manifest.json b/packages/ui/dist/copy/date-picker/manifest.json index 7bbe89754..4df25ddf4 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/date-picker.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/date-picker.js": "sha256-QyyWDOnYnSGxEdY+mxrtYtsLqoQAkhvTLJ5z7kjo3/w=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/date-picker.js": "sha256-rglCYTqoXYDZ63YUb01UqeMk0HRjOeYkVcqadAX0qmM=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-InOm4+AU0uQu6XZs3K+f13FA89Jf7iQO1GuL/2+s9YA=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/date-picker/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/date-picker/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/date-picker/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/date-picker/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/date-picker/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/date-picker/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/date-picker/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/date-picker/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/date-picker/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/date-picker/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/date-picker/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/date-picker.js b/packages/ui/dist/copy/date-picker/runtime/components/date-picker.js index b75f98455..df35db9b0 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1DatePicker = class extends J3w1Element { static componentId = "date-picker"; static version = "4.0.0"; - static implementationId = "sha256-c14aNjkp318olUOl5+cdRlcdDahvWoTp8lk0sI48z1Y="; + static implementationId = "sha256-rz3at5sJTA4TkXHNaqQnM5BrVBt02my29UyKewvFuRY="; static connect = fields; static upgradeProperties = [ "disabled", 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 24231b7fd..541cd14fa 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1DatePicker } from "../components/date-picker.js"; //#region .cache/ui-build/entries/register/date-picker.js var element = registerElement("j3w1-date-picker", J3w1DatePicker); diff --git a/packages/ui/dist/copy/description-list/manifest.json b/packages/ui/dist/copy/description-list/manifest.json index f447ddfb2..4a05a921d 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/description-list.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/description-list.js": "sha256-yhsiXjAR6wy2d0ePQtFlXsvPwWsBDWwuJiOZu/UqR1g=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/description-list.js": "sha256-qKd9CujEm+EgRSZfWHW9YXH9JY/d5wMBkkfqqP3z5so=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-MvWyrX2+45DLgWL1ZxTdk0IFVjl5WyfGYZdOYpIeoak=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/description-list/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/description-list/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/description-list/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/description-list/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/description-list/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/description-list/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/description-list/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/description-list/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/description-list/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/description-list/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/description-list/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/description-list.js b/packages/ui/dist/copy/description-list/runtime/components/description-list.js index c091b91c8..f7a7090ba 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,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1DescriptionList = class extends J3w1Element { static componentId = "description-list"; static version = "4.0.0"; - static implementationId = "sha256-GysXOSSmdZO80ECnRDrzDhjMNfpRODjO9r753vB1Mg0="; + static implementationId = "sha256-O3lqE1mNupuyqMqz1k1EzRDHMDjwD6aUReeED7JUclg="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; 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 b2341a425..37a62a7a6 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1DescriptionList } from "../components/description-list.js"; //#region .cache/ui-build/entries/register/description-list.js var element = registerElement("j3w1-description-list", J3w1DescriptionList); diff --git a/packages/ui/dist/copy/diagnostics/manifest.json b/packages/ui/dist/copy/diagnostics/manifest.json index 206999afe..08c3a7688 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/diagnostics.js", - "chunks/display-dj9YaBfn.js" + "chunks/display-Jm9bAsnb.js" ], "files": { - "runtime/register/diagnostics.js": "sha256-lSYtaMuTbe7wtLvNB4chvQ8SOVu0ILi3pFknhy/X/0E=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/diagnostics.js": "sha256-nC94tOw1MCiaCz5hbJRQf8qjWzQDz53K24KiwRwR8ws=", - "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-1uXLsplg978riCNhv/v5p+RvR0hW6fVdRnKgNUo+IYs=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/diagnostics/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/diagnostics/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/diagnostics/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place 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 new file mode 100644 index 000000000..5bc817830 --- /dev/null +++ b/packages/ui/dist/copy/diagnostics/runtime/chunks/display-Jm9bAsnb.js @@ -0,0 +1,212 @@ +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-dj9YaBfn.js b/packages/ui/dist/copy/diagnostics/runtime/chunks/display-dj9YaBfn.js deleted file mode 100644 index 80833d5da..000000000 --- a/packages/ui/dist/copy/diagnostics/runtime/chunks/display-dj9YaBfn.js +++ /dev/null @@ -1,212 +0,0 @@ -import { c as make, i as all, o as enabled } from "./choice-Db_w_BOQ.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/element-C1XeXVYC.js b/packages/ui/dist/copy/diagnostics/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/diagnostics/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/diagnostics/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/diagnostics/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 58236865c..f9e49175b 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-C1XeXVYC.js"; -import { r as developerView } from "../chunks/display-dj9YaBfn.js"; +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 var J3w1Diagnostics = class extends J3w1Element { static componentId = "diagnostics"; static version = "4.0.0"; - static implementationId = "sha256-jU3NVgcwD6UPMMah1cBNr8kgYNhC44JLUupKYIjR8ug="; + static implementationId = "sha256-lcf+xRikFjf+LQY6YZN+giWDauQWjFZbMz3xBLI3JG8="; static connect = developerView; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/copy/diagnostics/runtime/register/diagnostics.js b/packages/ui/dist/copy/diagnostics/runtime/register/diagnostics.js index e92c83ed2..2d9f84547 100644 --- a/packages/ui/dist/copy/diagnostics/runtime/register/diagnostics.js +++ b/packages/ui/dist/copy/diagnostics/runtime/register/diagnostics.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Diagnostics } from "../components/diagnostics.js"; //#region .cache/ui-build/entries/register/diagnostics.js var element = registerElement("j3w1-diagnostics", J3w1Diagnostics); diff --git a/packages/ui/dist/copy/dialog/manifest.json b/packages/ui/dist/copy/dialog/manifest.json index 3ba912853..bce4cbd52 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/dialog.js", - "chunks/overlays-C6nlCHqg.js" + "chunks/overlays-Bw8SSDKz.js" ], "files": { - "runtime/register/dialog.js": "sha256-Y6MRVCgkK5UEzcEdMHQSCUf6gMnxsPOJuhfEFWmJXOw=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/dialog.js": "sha256-e9pTCjxk1e95o6PW5WuKLJsHz87/SQRFeL9+DTQyk5I=", - "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", + "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-mYfz6BnuRAPGKxNiVulnuJ4IEMvqr5BPqrNrZCRR5H8=", + "runtime/chunks/overlays-Bw8SSDKz.js": "sha256-YrX9CL2A48QwI7COQQ5anYJLPOxpKrIeyz+jtfp+T+I=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-d4bh9HaP4YOtfgWmP42qVqw3nqSJ3DF629AWjqoZTn4=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/dialog/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/dialog/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/dialog/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/dialog/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/dialog/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/dialog/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/dialog/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/dialog/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/dialog/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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-C6nlCHqg.js b/packages/ui/dist/copy/dialog/runtime/chunks/overlays-Bw8SSDKz.js similarity index 98% rename from packages/ui/dist/chunks/overlays-C6nlCHqg.js rename to packages/ui/dist/copy/dialog/runtime/chunks/overlays-Bw8SSDKz.js index 9df8503ec..3eeb8ff0d 100644 --- a/packages/ui/dist/chunks/overlays-C6nlCHqg.js +++ b/packages/ui/dist/copy/dialog/runtime/chunks/overlays-Bw8SSDKz.js @@ -1,4 +1,4 @@ -import { i as all, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.js"; +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"); diff --git a/packages/ui/dist/copy/dialog/runtime/components/dialog.js b/packages/ui/dist/copy/dialog/runtime/components/dialog.js index 1b3c4a379..831fed823 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-C1XeXVYC.js"; -import { n as modal } from "../chunks/overlays-C6nlCHqg.js"; +import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; +import { n as modal } from "../chunks/overlays-Bw8SSDKz.js"; //#region .cache/ui-build/entries/components/dialog.js var J3w1Dialog = class extends J3w1Element { static componentId = "dialog"; static version = "4.0.0"; - static implementationId = "sha256-klBSVv/73RVF8H8z45KqQcsbWhHl+/t4VEl+jC/2v9Q="; + static implementationId = "sha256-mRRuIsoBG3ZepORoxkayVAw92Or7CJEuj6eD9YVaZyw="; static connect = modal; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/copy/dialog/runtime/register/dialog.js b/packages/ui/dist/copy/dialog/runtime/register/dialog.js index ee673cb86..bded0a66c 100644 --- a/packages/ui/dist/copy/dialog/runtime/register/dialog.js +++ b/packages/ui/dist/copy/dialog/runtime/register/dialog.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Dialog } from "../components/dialog.js"; //#region .cache/ui-build/entries/register/dialog.js var element = registerElement("j3w1-dialog", J3w1Dialog); diff --git a/packages/ui/dist/copy/diff-view/manifest.json b/packages/ui/dist/copy/diff-view/manifest.json index 8b99563fd..50358dba1 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/diff-view.js", - "chunks/display-dj9YaBfn.js" + "chunks/display-Jm9bAsnb.js" ], "files": { - "runtime/register/diff-view.js": "sha256-dfbslff/fV33ePOMN/mGU9l+7RqomLajKxKQdpmW+qQ=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/diff-view.js": "sha256-QfZm092MHlNhP9Vfs6IkWjXkbrGughYsBfHTOCL93cM=", - "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-mibFUolrx0OWHlYNpEFTvfkMI0c6h4CUv7SWJ4eQVns=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/diff-view/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/diff-view/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/diff-view/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place 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 new file mode 100644 index 000000000..5bc817830 --- /dev/null +++ b/packages/ui/dist/copy/diff-view/runtime/chunks/display-Jm9bAsnb.js @@ -0,0 +1,212 @@ +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-dj9YaBfn.js b/packages/ui/dist/copy/diff-view/runtime/chunks/display-dj9YaBfn.js deleted file mode 100644 index 80833d5da..000000000 --- a/packages/ui/dist/copy/diff-view/runtime/chunks/display-dj9YaBfn.js +++ /dev/null @@ -1,212 +0,0 @@ -import { c as make, i as all, o as enabled } from "./choice-Db_w_BOQ.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/element-C1XeXVYC.js b/packages/ui/dist/copy/diff-view/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/diff-view/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/diff-view/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/diff-view/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 633e44138..47f8bf1a3 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-C1XeXVYC.js"; -import { r as developerView } from "../chunks/display-dj9YaBfn.js"; +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 var J3w1DiffView = class extends J3w1Element { static componentId = "diff-view"; static version = "4.0.0"; - static implementationId = "sha256-lEC5NAzVDADHe5s6uWIGnx5icpXJwmRoT/VTUI4h2l8="; + static implementationId = "sha256-7zzFpU0Y2cQR1wO8DWE4bqkofCnJMaERCXRLdai7u0A="; static connect = developerView; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; 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 53e4b042d..92fc87c5c 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1DiffView } from "../components/diff-view.js"; //#region .cache/ui-build/entries/register/diff-view.js var element = registerElement("j3w1-diff-view", J3w1DiffView); diff --git a/packages/ui/dist/copy/disclosure/manifest.json b/packages/ui/dist/copy/disclosure/manifest.json index 73af296bf..eb65336e8 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/disclosure.js", - "chunks/navigation-Dt8ap-9J.js" + "chunks/navigation-BfNzDYZB.js" ], "files": { - "runtime/register/disclosure.js": "sha256-QAWXKSki5SRPPTshefR54Zy2gycHjHlG61aTWPL1Q4g=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/disclosure.js": "sha256-T++duSnTm8ippxMGxtM25ykxUO+HYIt0HK55RkVOrHQ=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-vVNjPU0AXLKLnxgRPgOVmN3dS6S3pxA6xLFfJFK8ex4=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/disclosure/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/disclosure/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/disclosure/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/disclosure/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/disclosure/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/disclosure/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/disclosure/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/disclosure/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..db2779553 --- /dev/null +++ b/packages/ui/dist/copy/disclosure/runtime/chunks/navigation-BfNzDYZB.js @@ -0,0 +1,377 @@ +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-Dt8ap-9J.js b/packages/ui/dist/copy/disclosure/runtime/chunks/navigation-Dt8ap-9J.js deleted file mode 100644 index 81201c8d5..000000000 --- a/packages/ui/dist/copy/disclosure/runtime/chunks/navigation-Dt8ap-9J.js +++ /dev/null @@ -1,367 +0,0 @@ -import { a as announce, d as rove, f as visible, i as all, l as nativeInput, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.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, event.key === next ? index + 1 : event.key === prev ? index - 1 : event.key === "Home" ? 0 : items.length - 1); - }); - 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, event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : index + (event.key === "ArrowDown" ? 1 : -1)); - } 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/components/disclosure.js b/packages/ui/dist/copy/disclosure/runtime/components/disclosure.js index 8760d6a4d..56e4f17fd 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-C1XeXVYC.js"; -import { n as disclosure } from "../chunks/navigation-Dt8ap-9J.js"; +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 var J3w1Disclosure = class extends J3w1Element { static componentId = "disclosure"; static version = "4.0.0"; - static implementationId = "sha256-ROxGJvPyGtUqhWzL3a8qhGmOOsm3PD+fneX9Gb764gg="; + static implementationId = "sha256-h35ty1HDvIv+l1TZ2KWtUtdJetenP1x1+OVPFVOsByg="; static connect = disclosure; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/copy/disclosure/runtime/register/disclosure.js b/packages/ui/dist/copy/disclosure/runtime/register/disclosure.js index 5eff2865e..76f4c204b 100644 --- a/packages/ui/dist/copy/disclosure/runtime/register/disclosure.js +++ b/packages/ui/dist/copy/disclosure/runtime/register/disclosure.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Disclosure } from "../components/disclosure.js"; //#region .cache/ui-build/entries/register/disclosure.js var element = registerElement("j3w1-disclosure", J3w1Disclosure); diff --git a/packages/ui/dist/copy/drawer/manifest.json b/packages/ui/dist/copy/drawer/manifest.json index e0561f3ec..51bda8368 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/drawer.js", - "chunks/overlays-C6nlCHqg.js" + "chunks/overlays-Bw8SSDKz.js" ], "files": { - "runtime/register/drawer.js": "sha256-6AFbTqS+kQAd15TJ9NzKLIyNKPdVVmxyZMeHJXtNEhU=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/drawer.js": "sha256-vwjZdEg2SybEwAsIBL+uJuAs6ArJnLfrtqdRiOtleqA=", - "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", + "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-jGdxQ8JnwAPl1aTJWnbXrRb0kPIs7kJZo5rIrmfBTF4=", + "runtime/chunks/overlays-Bw8SSDKz.js": "sha256-YrX9CL2A48QwI7COQQ5anYJLPOxpKrIeyz+jtfp+T+I=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-39DmGp3B3f8+C/QGAv6xbiVXT7QviSaVCnHk8XpC158=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/drawer/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/drawer/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/drawer/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/drawer/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/drawer/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/drawer/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/drawer/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/drawer/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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-Bw8SSDKz.js b/packages/ui/dist/copy/drawer/runtime/chunks/overlays-Bw8SSDKz.js new file mode 100644 index 000000000..3eeb8ff0d --- /dev/null +++ b/packages/ui/dist/copy/drawer/runtime/chunks/overlays-Bw8SSDKz.js @@ -0,0 +1,236 @@ +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, dismissed = false, hovering = false; + const stop = () => { + clearTimeout(timer); + }; + const hide = () => { + stop(); + popup.hidden = true; + }; + const show = () => { + stop(); + if (!dismissed) { + popup.hidden = false; + place(trigger, popup); + } + }; + on(trigger, "pointerenter", (event) => { + if (event.pointerType !== "touch") { + hovering = true; + dismissed = false; + timer = setTimeout(show, 300); + } + }); + on(root, "pointerleave", (event) => { + if (!root.contains(event.relatedTarget)) { + hovering = false; + dismissed = false; + if (root.ownerDocument.activeElement !== trigger) hide(); + } + }); + 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/chunks/overlays-C6nlCHqg.js b/packages/ui/dist/copy/drawer/runtime/chunks/overlays-C6nlCHqg.js deleted file mode 100644 index 9df8503ec..000000000 --- a/packages/ui/dist/copy/drawer/runtime/chunks/overlays-C6nlCHqg.js +++ /dev/null @@ -1,236 +0,0 @@ -import { i as all, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.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, dismissed = false, hovering = false; - const stop = () => { - clearTimeout(timer); - }; - const hide = () => { - stop(); - popup.hidden = true; - }; - const show = () => { - stop(); - if (!dismissed) { - popup.hidden = false; - place(trigger, popup); - } - }; - on(trigger, "pointerenter", (event) => { - if (event.pointerType !== "touch") { - hovering = true; - dismissed = false; - timer = setTimeout(show, 300); - } - }); - on(root, "pointerleave", (event) => { - if (!root.contains(event.relatedTarget)) { - hovering = false; - dismissed = false; - if (root.ownerDocument.activeElement !== trigger) hide(); - } - }); - 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 3090b4b92..84e74f5d6 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-C1XeXVYC.js"; -import { n as modal } from "../chunks/overlays-C6nlCHqg.js"; +import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; +import { n as modal } from "../chunks/overlays-Bw8SSDKz.js"; //#region .cache/ui-build/entries/components/drawer.js var J3w1Drawer = class extends J3w1Element { static componentId = "drawer"; static version = "4.0.0"; - static implementationId = "sha256-8/bHeKdg2GkEVkeV2YqDCVbqEPZb6trQ7qLrf3vhnWQ="; + static implementationId = "sha256-k/ZCI1iewFGM/3Yu72DZfB6MpyHU8aF26giyLMSce+U="; static connect = modal; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/copy/drawer/runtime/register/drawer.js b/packages/ui/dist/copy/drawer/runtime/register/drawer.js index d2101eb9d..3ea076673 100644 --- a/packages/ui/dist/copy/drawer/runtime/register/drawer.js +++ b/packages/ui/dist/copy/drawer/runtime/register/drawer.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Drawer } from "../components/drawer.js"; //#region .cache/ui-build/entries/register/drawer.js var element = registerElement("j3w1-drawer", J3w1Drawer); diff --git a/packages/ui/dist/copy/editor-search/manifest.json b/packages/ui/dist/copy/editor-search/manifest.json index d985021fd..ce8d1e04a 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/editor-search.js", - "chunks/display-dj9YaBfn.js" + "chunks/display-Jm9bAsnb.js" ], "files": { - "runtime/register/editor-search.js": "sha256-tMpvZf9OrWiyhDzn0EWZnEz8kSJ2SP8tALzQVYqwCws=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/editor-search.js": "sha256-tPLpeyxQ/8Gf/LImxqGBvRraQE6oFXtqIspmI84b8XA=", - "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-M0SrYSnjmhmwR0wfAiNg1VU3bXhEQkYknaGRLw0fWMM=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/editor-search/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/editor-search/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/editor-search/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place 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 new file mode 100644 index 000000000..5bc817830 --- /dev/null +++ b/packages/ui/dist/copy/editor-search/runtime/chunks/display-Jm9bAsnb.js @@ -0,0 +1,212 @@ +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-dj9YaBfn.js b/packages/ui/dist/copy/editor-search/runtime/chunks/display-dj9YaBfn.js deleted file mode 100644 index 80833d5da..000000000 --- a/packages/ui/dist/copy/editor-search/runtime/chunks/display-dj9YaBfn.js +++ /dev/null @@ -1,212 +0,0 @@ -import { c as make, i as all, o as enabled } from "./choice-Db_w_BOQ.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/element-C1XeXVYC.js b/packages/ui/dist/copy/editor-search/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/editor-search/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/editor-search/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/editor-search/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 f5bf25205..fc6e2a1a7 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-C1XeXVYC.js"; -import { i as editorSearch } from "../chunks/display-dj9YaBfn.js"; +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 var J3w1EditorSearch = class extends J3w1Element { static componentId = "editor-search"; static version = "4.0.0"; - static implementationId = "sha256-9KkGT11jVqC1mIIjjeR24BOy0FxKESmTA8B47/6yZHg="; + static implementationId = "sha256-SqX6iBMRHKvfYM9+QKkc2K/hjCGRNMeVrj+B25L3SoU="; static connect = editorSearch; static upgradeProperties = [ "disabled", 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 fa960075d..e0237ca4a 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1EditorSearch } from "../components/editor-search.js"; //#region .cache/ui-build/entries/register/editor-search.js var element = registerElement("j3w1-editor-search", J3w1EditorSearch); diff --git a/packages/ui/dist/copy/empty-state/manifest.json b/packages/ui/dist/copy/empty-state/manifest.json index 93927f1fc..d03ee8b86 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/empty-state.js", - "chunks/overlays-C6nlCHqg.js" + "chunks/overlays-Bw8SSDKz.js" ], "files": { - "runtime/register/empty-state.js": "sha256-U7bwZQNspzXEKbkM+QwrFwH9wCsXZ+UNK2RYEFi+FjI=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/empty-state.js": "sha256-bmsYB/w+TevvaR9K+tvrVuNDGxVPv2PYR4hbTkhw+dU=", - "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", + "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-OdxqAGZuSH7KdWGE58jWJBVQnd4azuJVXLqmIEKf/1k=", + "runtime/chunks/overlays-Bw8SSDKz.js": "sha256-YrX9CL2A48QwI7COQQ5anYJLPOxpKrIeyz+jtfp+T+I=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Mdd72ooxolJDcPYScpT7yUM7Uj1SV5nk9LuG9vP0EeA=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/empty-state/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/empty-state/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/empty-state/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/empty-state/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/empty-state/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/empty-state/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/empty-state/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/empty-state/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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-Bw8SSDKz.js b/packages/ui/dist/copy/empty-state/runtime/chunks/overlays-Bw8SSDKz.js new file mode 100644 index 000000000..3eeb8ff0d --- /dev/null +++ b/packages/ui/dist/copy/empty-state/runtime/chunks/overlays-Bw8SSDKz.js @@ -0,0 +1,236 @@ +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, dismissed = false, hovering = false; + const stop = () => { + clearTimeout(timer); + }; + const hide = () => { + stop(); + popup.hidden = true; + }; + const show = () => { + stop(); + if (!dismissed) { + popup.hidden = false; + place(trigger, popup); + } + }; + on(trigger, "pointerenter", (event) => { + if (event.pointerType !== "touch") { + hovering = true; + dismissed = false; + timer = setTimeout(show, 300); + } + }); + on(root, "pointerleave", (event) => { + if (!root.contains(event.relatedTarget)) { + hovering = false; + dismissed = false; + if (root.ownerDocument.activeElement !== trigger) hide(); + } + }); + 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/chunks/overlays-C6nlCHqg.js b/packages/ui/dist/copy/empty-state/runtime/chunks/overlays-C6nlCHqg.js deleted file mode 100644 index 9df8503ec..000000000 --- a/packages/ui/dist/copy/empty-state/runtime/chunks/overlays-C6nlCHqg.js +++ /dev/null @@ -1,236 +0,0 @@ -import { i as all, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.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, dismissed = false, hovering = false; - const stop = () => { - clearTimeout(timer); - }; - const hide = () => { - stop(); - popup.hidden = true; - }; - const show = () => { - stop(); - if (!dismissed) { - popup.hidden = false; - place(trigger, popup); - } - }; - on(trigger, "pointerenter", (event) => { - if (event.pointerType !== "touch") { - hovering = true; - dismissed = false; - timer = setTimeout(show, 300); - } - }); - on(root, "pointerleave", (event) => { - if (!root.contains(event.relatedTarget)) { - hovering = false; - dismissed = false; - if (root.ownerDocument.activeElement !== trigger) hide(); - } - }); - 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 b735fb73b..a2ad90398 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-C1XeXVYC.js"; -import { t as feedback } from "../chunks/overlays-C6nlCHqg.js"; +import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; +import { t as feedback } from "../chunks/overlays-Bw8SSDKz.js"; //#region .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-rbfG9GfAXF+BMPfgYh9VU3TSU0CXpzgo8GhNdA2DHw0="; + static implementationId = "sha256-TjsU1nEvRoXqvqnqWsM2EsMF7pDu5QD94wKIbCronI4="; static connect = feedback; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; 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 cc2e584c5..a4b9594da 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1EmptyState } from "../components/empty-state.js"; //#region .cache/ui-build/entries/register/empty-state.js var element = registerElement("j3w1-empty-state", J3w1EmptyState); diff --git a/packages/ui/dist/copy/error-state/manifest.json b/packages/ui/dist/copy/error-state/manifest.json index 6e0ab789d..8a05505e0 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/error-state.js", - "chunks/overlays-C6nlCHqg.js" + "chunks/overlays-Bw8SSDKz.js" ], "files": { - "runtime/register/error-state.js": "sha256-LIyigSg3KPB01jhmW1+pAsrMoPyf6KtZcmrTenvFCx8=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/error-state.js": "sha256-vgUhuSmkAd9uc2x8r5Oc5k2rjzWbEtFRnrR0smV/YqM=", - "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", + "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-SjO3330quFN81HjlZH31y/z5f1V4MNQewsgHCYnHvA8=", + "runtime/chunks/overlays-Bw8SSDKz.js": "sha256-YrX9CL2A48QwI7COQQ5anYJLPOxpKrIeyz+jtfp+T+I=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-CdLPhgSZDY0ucB4/nfZpfphuYXcfoqslUTPyuhz2tDw=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/error-state/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/error-state/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/error-state/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/error-state/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/error-state/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/error-state/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/error-state/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/error-state/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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-Bw8SSDKz.js b/packages/ui/dist/copy/error-state/runtime/chunks/overlays-Bw8SSDKz.js new file mode 100644 index 000000000..3eeb8ff0d --- /dev/null +++ b/packages/ui/dist/copy/error-state/runtime/chunks/overlays-Bw8SSDKz.js @@ -0,0 +1,236 @@ +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, dismissed = false, hovering = false; + const stop = () => { + clearTimeout(timer); + }; + const hide = () => { + stop(); + popup.hidden = true; + }; + const show = () => { + stop(); + if (!dismissed) { + popup.hidden = false; + place(trigger, popup); + } + }; + on(trigger, "pointerenter", (event) => { + if (event.pointerType !== "touch") { + hovering = true; + dismissed = false; + timer = setTimeout(show, 300); + } + }); + on(root, "pointerleave", (event) => { + if (!root.contains(event.relatedTarget)) { + hovering = false; + dismissed = false; + if (root.ownerDocument.activeElement !== trigger) hide(); + } + }); + 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/chunks/overlays-C6nlCHqg.js b/packages/ui/dist/copy/error-state/runtime/chunks/overlays-C6nlCHqg.js deleted file mode 100644 index 9df8503ec..000000000 --- a/packages/ui/dist/copy/error-state/runtime/chunks/overlays-C6nlCHqg.js +++ /dev/null @@ -1,236 +0,0 @@ -import { i as all, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.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, dismissed = false, hovering = false; - const stop = () => { - clearTimeout(timer); - }; - const hide = () => { - stop(); - popup.hidden = true; - }; - const show = () => { - stop(); - if (!dismissed) { - popup.hidden = false; - place(trigger, popup); - } - }; - on(trigger, "pointerenter", (event) => { - if (event.pointerType !== "touch") { - hovering = true; - dismissed = false; - timer = setTimeout(show, 300); - } - }); - on(root, "pointerleave", (event) => { - if (!root.contains(event.relatedTarget)) { - hovering = false; - dismissed = false; - if (root.ownerDocument.activeElement !== trigger) hide(); - } - }); - 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 42d38f9c3..8adf9072e 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-C1XeXVYC.js"; -import { t as feedback } from "../chunks/overlays-C6nlCHqg.js"; +import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; +import { t as feedback } from "../chunks/overlays-Bw8SSDKz.js"; //#region .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-hj5jc9C6nDjhax7f/nHkk1z0tkHTuXGp1LJlDuYyDwU="; + static implementationId = "sha256-NFXjO9uEbTYqbXbZVfFiY8Ge2N54qnmAPnp046iwL4U="; static connect = feedback; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; 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 14d6dc937..5e09ece1b 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1ErrorState } from "../components/error-state.js"; //#region .cache/ui-build/entries/register/error-state.js var element = registerElement("j3w1-error-state", J3w1ErrorState); diff --git a/packages/ui/dist/copy/field/manifest.json b/packages/ui/dist/copy/field/manifest.json index 0f4ae8b86..5a3301287 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/field.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/field.js": "sha256-XVffQJ1x1BaYIujyxerGMhRVXOVJvdiFmAKkTglUyC8=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/field.js": "sha256-pEHbl120kbYNPym5N03ZxIzOQFPHyq+rELTr9RnR2tg=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Rd3CCjOeRNdq9v3ql8A+P+nyw3MOp7Fa0LUD8UqBzFA=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/field/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/field/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/field/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/field/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/field/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/field/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/field/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/field/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/field/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/field/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/field/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/field.js b/packages/ui/dist/copy/field/runtime/components/field.js index 70f9d02d4..432885b11 100644 --- a/packages/ui/dist/copy/field/runtime/components/field.js +++ b/packages/ui/dist/copy/field/runtime/components/field.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Field = class extends J3w1Element { static componentId = "field"; static version = "4.0.0"; - static implementationId = "sha256-CViK07vFgOOS2jQ7u/riONTbtMAUdHVY73iqaGIV1tw="; + static implementationId = "sha256-GDPT/9zMxdyqVusrML6KYJd3mC9Kts0/5zp2/Xi2cYA="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/copy/field/runtime/register/field.js b/packages/ui/dist/copy/field/runtime/register/field.js index 245800b81..875540d71 100644 --- a/packages/ui/dist/copy/field/runtime/register/field.js +++ b/packages/ui/dist/copy/field/runtime/register/field.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Field } from "../components/field.js"; //#region .cache/ui-build/entries/register/field.js var element = registerElement("j3w1-field", J3w1Field); diff --git a/packages/ui/dist/copy/fieldset/manifest.json b/packages/ui/dist/copy/fieldset/manifest.json index 193d37cd3..1636101f2 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/fieldset.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/fieldset.js": "sha256-95mq6oG6gTLPWs+kdvdNqiuSftofqYoBvCulLuTebyE=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/fieldset.js": "sha256-pAzVFWN+M793N7lFAZ2zTybWJLdSOqZl3AmOTomqmTk=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-TPi15SfEwAaSl4PqQvGAd3bFbbB4BJ2trfD5k2+8yrc=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/fieldset/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/fieldset/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/fieldset/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/fieldset/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/fieldset/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/fieldset/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/fieldset/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/fieldset/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/fieldset/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/fieldset/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/fieldset/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/fieldset.js b/packages/ui/dist/copy/fieldset/runtime/components/fieldset.js index 4ed189f3a..062960dc4 100644 --- a/packages/ui/dist/copy/fieldset/runtime/components/fieldset.js +++ b/packages/ui/dist/copy/fieldset/runtime/components/fieldset.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Fieldset = class extends J3w1Element { static componentId = "fieldset"; static version = "4.0.0"; - static implementationId = "sha256-T4bhKoYz9jjaxP51Plfd+oswKiEpk1JGLzi29ItD4mQ="; + static implementationId = "sha256-GMEsNCLKXzxBWy1NzvLrpSNVUG/llwSmGqxbUbScbHQ="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/copy/fieldset/runtime/register/fieldset.js b/packages/ui/dist/copy/fieldset/runtime/register/fieldset.js index 23d5cdd65..4ac632e86 100644 --- a/packages/ui/dist/copy/fieldset/runtime/register/fieldset.js +++ b/packages/ui/dist/copy/fieldset/runtime/register/fieldset.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Fieldset } from "../components/fieldset.js"; //#region .cache/ui-build/entries/register/fieldset.js var element = registerElement("j3w1-fieldset", J3w1Fieldset); diff --git a/packages/ui/dist/copy/file-browser/manifest.json b/packages/ui/dist/copy/file-browser/manifest.json index 7c1fc8b28..95fe580b9 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "register/tree.js", "components/tree.js", - "chunks/advanced-DCpe8Ndv.js", + "chunks/advanced-CqBF0dSb.js", "chunks/markup-DeQ4bEMR.js", "components/file-browser.js", - "chunks/compositions-d6BkKTYf.js", - "chunks/navigation-Dt8ap-9J.js" + "chunks/compositions-D57dCsBz.js", + "chunks/navigation-BfNzDYZB.js" ], "files": { - "runtime/register/file-browser.js": "sha256-3aIWKczcdziEiQIR4gWOFhsKDAxyRTBDe0i3ynmVXis=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/register/tree.js": "sha256-xY8jWYnbMM8UlE/rdQJsu3/URGPvdUC06U1QmKsmFZQ=", - "runtime/components/tree.js": "sha256-1wgpPM9BoC1/T0Or37ZhoekuO2YZ3luXp+DpWKVKBcU=", - "runtime/chunks/advanced-DCpe8Ndv.js": "sha256-nr1LFdLYsGeTM4vDyldvuJygRm0F04sYonxatySPu1g=", + "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-mmsIwfdO+8Xy7vrRylWFBDIwAoWKfkgmb8J17rxDHVs=", - "runtime/chunks/compositions-d6BkKTYf.js": "sha256-El5csGAVMeeZWmJ1ztdXW3O3t2AQPrf3YrEOMkGX17c=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-jXsUncF3ZqNTAY54eALB2XHlOFiiumSXp+AnM14Tz1Q=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/file-browser/runtime/chunks/advanced-DCpe8Ndv.js b/packages/ui/dist/copy/file-browser/runtime/chunks/advanced-CqBF0dSb.js similarity index 97% rename from packages/ui/dist/copy/file-browser/runtime/chunks/advanced-DCpe8Ndv.js rename to packages/ui/dist/copy/file-browser/runtime/chunks/advanced-CqBF0dSb.js index 3390a044c..4a5c45981 100644 --- a/packages/ui/dist/copy/file-browser/runtime/chunks/advanced-DCpe8Ndv.js +++ b/packages/ui/dist/copy/file-browser/runtime/chunks/advanced-CqBF0dSb.js @@ -1,4 +1,4 @@ -import { d as rove, f as visible, i as all, l as nativeInput, o as enabled, s as identify } from "./choice-Db_w_BOQ.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-B7mo5Eq3.js"; import { t as IDREFS } from "./markup-DeQ4bEMR.js"; //#region packages/ui/src/behaviors/advanced.js function tree(root, { on }) { @@ -64,7 +64,12 @@ function tree(root, { on }) { "End" ].includes(event.key)) { event.preventDefault(); - const next = event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : Math.max(0, Math.min(options.length - 1, index + (event.key === "ArrowDown" ? 1 : -1))); + const next = keyIndex({ + key: event.key, + index, + length: options.length, + wrap: false + }); rove(options, next); } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight")) { event.preventDefault(); 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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/file-browser/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/file-browser/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/file-browser/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/chunks/compositions-d6BkKTYf.js b/packages/ui/dist/copy/file-browser/runtime/chunks/compositions-D57dCsBz.js similarity index 94% rename from packages/ui/dist/chunks/compositions-d6BkKTYf.js rename to packages/ui/dist/copy/file-browser/runtime/chunks/compositions-D57dCsBz.js index 7d70275f2..f1da4562e 100644 --- a/packages/ui/dist/chunks/compositions-d6BkKTYf.js +++ b/packages/ui/dist/copy/file-browser/runtime/chunks/compositions-D57dCsBz.js @@ -1,5 +1,5 @@ -import { i as all, o as enabled } from "./choice-Db_w_BOQ.js"; -import { i as tabs } from "./navigation-Dt8ap-9J.js"; +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 function fileBrowser(root, { on }) { const query = root.querySelector("[data-file-query]"), rows = all(root, "tr[data-file-id]"), status = root.querySelector("[data-file-status]"); diff --git a/packages/ui/dist/copy/file-browser/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/file-browser/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/file-browser/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/file-browser/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/file-browser/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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/navigation-BfNzDYZB.js b/packages/ui/dist/copy/file-browser/runtime/chunks/navigation-BfNzDYZB.js new file mode 100644 index 000000000..db2779553 --- /dev/null +++ b/packages/ui/dist/copy/file-browser/runtime/chunks/navigation-BfNzDYZB.js @@ -0,0 +1,377 @@ +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-Dt8ap-9J.js b/packages/ui/dist/copy/file-browser/runtime/chunks/navigation-Dt8ap-9J.js deleted file mode 100644 index 81201c8d5..000000000 --- a/packages/ui/dist/copy/file-browser/runtime/chunks/navigation-Dt8ap-9J.js +++ /dev/null @@ -1,367 +0,0 @@ -import { a as announce, d as rove, f as visible, i as all, l as nativeInput, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.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, event.key === next ? index + 1 : event.key === prev ? index - 1 : event.key === "Home" ? 0 : items.length - 1); - }); - 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, event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : index + (event.key === "ArrowDown" ? 1 : -1)); - } 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/components/file-browser.js b/packages/ui/dist/copy/file-browser/runtime/components/file-browser.js index 17d4a5a03..2c355a89a 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,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as fileBrowser } from "../chunks/compositions-d6BkKTYf.js"; +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 var J3w1FileBrowser = class extends J3w1Element { static componentId = "file-browser"; static version = "4.0.0"; - static implementationId = "sha256-aX7ynrR8fIvhjh+E38lBwgWP8mffpXVi5toiJ1sIa9c="; + static implementationId = "sha256-XNnX1ARH1szUReH6kSeTR1njKOACxLiUhBCmo9iNz8s="; static connect = fileBrowser; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; 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 8a8288b08..e0f6bd8da 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-C1XeXVYC.js"; -import { i as tree } from "../chunks/advanced-DCpe8Ndv.js"; +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 var J3w1Tree = class extends J3w1Element { static componentId = "tree"; static version = "4.0.0"; - static implementationId = "sha256-MaBLx3mLOk+RW8kMweDInlVoWjSFctZly5Jz9BMRFRI="; + static implementationId = "sha256-8E6bGMMWEmhgjIAfuDs1+pxcabRicShQao3beIvcNBY="; static connect = tree; static upgradeProperties = [ "disabled", 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 546633566..6d8b76ed5 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import "./tree.js"; import { J3w1FileBrowser } from "../components/file-browser.js"; //#region .cache/ui-build/entries/register/file-browser.js 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 c6b7d3d39..0ecee9bca 100644 --- a/packages/ui/dist/copy/file-browser/runtime/register/tree.js +++ b/packages/ui/dist/copy/file-browser/runtime/register/tree.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Tree } from "../components/tree.js"; //#region .cache/ui-build/entries/register/tree.js var element = registerElement("j3w1-tree", J3w1Tree); diff --git a/packages/ui/dist/copy/file-input/manifest.json b/packages/ui/dist/copy/file-input/manifest.json index ca770ef41..cb7afba97 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/file-input.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/file-input.js": "sha256-JVcVdlTDOCB4bLa+Gc4LHWSfojAaR3wRwOBxMeLa8z4=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/file-input.js": "sha256-b5A8PD7vS8/xWNzSdVbtt2pV33CllxtkKwdSPtC1CSI=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-ezg9wydBGR6KpQziZgvoKiTXURNTPkh+aD9h3vFuuW4=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/file-input/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/file-input/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/file-input/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/file-input/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/file-input/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/file-input/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/file-input/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/file-input/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/file-input/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/file-input/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/file-input/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/file-input.js b/packages/ui/dist/copy/file-input/runtime/components/file-input.js index 228c9b229..e90ea78d1 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-C1XeXVYC.js"; -import { i as fileInput } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1FileInput = class extends J3w1Element { static componentId = "file-input"; static version = "4.0.0"; - static implementationId = "sha256-m0+3EjPTC3Wr2r8xF2V2Q+38R4z12VAJn9DB7iS0JPc="; + static implementationId = "sha256-DYtJ1M3W9zNvFy3MIif27+5jsw2JssfZ5mpXTXwGBCo="; static connect = fileInput; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; 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 e840437d0..33be9dd6d 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1FileInput } from "../components/file-input.js"; //#region .cache/ui-build/entries/register/file-input.js var element = registerElement("j3w1-file-input", J3w1FileInput); diff --git a/packages/ui/dist/copy/filterable-table/manifest.json b/packages/ui/dist/copy/filterable-table/manifest.json index 3d57ef133..eccd1560f 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "register/search-field.js", "components/search-field.js", - "chunks/native-CAzZmDKR.js", + "chunks/native-BjBt1sUh.js", "components/filterable-table.js", - "chunks/tables-B25ydUHs.js" + "chunks/tables-Cjr1EIJz.js" ], "files": { - "runtime/register/filterable-table.js": "sha256-4o9WlQbHlOnAg8mdJws9+tapo3wueOwNMacJhswL7Hg=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/register/search-field.js": "sha256-Z6IeX4+LKGVQJUcQGuyUnCBL6ggQSoevMhrj75zYisw=", - "runtime/components/search-field.js": "sha256-2ODKfrgzC53SjMT+P7oaRa78AgRY37MG12M7HVRwfQU=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "runtime/components/filterable-table.js": "sha256-1tup9iQXvwHywM5vJL3oiz0gLiDGNw/xjkZ91AA+Sok=", - "runtime/chunks/tables-B25ydUHs.js": "sha256-XqRdyfrSS93rVybWHq6a0WhrmZgaboHi5n8ymgwRbM8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-ZpN1xEJy4fV/PBDvH91mkuN2CZqhCUo5wpeCs27jREo=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/filterable-table/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/filterable-table/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/filterable-table/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/filterable-table/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/filterable-table/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/filterable-table/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/filterable-table/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/filterable-table/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/filterable-table/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/filterable-table/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/filterable-table/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/pagination/runtime/chunks/tables-B25ydUHs.js b/packages/ui/dist/copy/filterable-table/runtime/chunks/tables-Cjr1EIJz.js similarity index 96% rename from packages/ui/dist/copy/pagination/runtime/chunks/tables-B25ydUHs.js rename to packages/ui/dist/copy/filterable-table/runtime/chunks/tables-Cjr1EIJz.js index 172bab830..f82aaf25e 100644 --- a/packages/ui/dist/copy/pagination/runtime/chunks/tables-B25ydUHs.js +++ b/packages/ui/dist/copy/filterable-table/runtime/chunks/tables-Cjr1EIJz.js @@ -1,4 +1,4 @@ -import { d as rove, i as all, o as enabled, s as identify } from "./choice-Db_w_BOQ.js"; +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]; @@ -106,7 +106,12 @@ function table(root, { on }) { "End" ].includes(event.key)) return; event.preventDefault(); - const nextIndex = event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : Math.max(0, Math.min(options.length - 1, index + (event.key === "ArrowDown" ? 1 : -1))); + const nextIndex = keyIndex({ + key: event.key, + index, + length: options.length, + wrap: false + }); const next = rove(options, nextIndex); if (event.shiftKey && selectAll) { anchor ??= row; 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 fdc624ffe..5eb0b2d55 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-C1XeXVYC.js"; -import { n as table } from "../chunks/tables-B25ydUHs.js"; +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 var J3w1FilterableTable = class extends J3w1Element { static componentId = "filterable-table"; static version = "4.0.0"; - static implementationId = "sha256-X8YqHg+uk9WRKBEGt72ID1ciBCXv0ORCorTI2IiT8v8="; + static implementationId = "sha256-SJvvFZ+/THkuQJCx1F2i0vCQ2C54dLton+9ipWE3sS8="; static connect = table; static upgradeProperties = [ "disabled", 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 4d97313b6..666ca6dde 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1SearchField = class extends J3w1Element { static componentId = "search-field"; static version = "4.0.0"; - static implementationId = "sha256-1DXqGUME/dceUQ+jjPOv/UDtTubfoV13HCjmaDde06w="; + static implementationId = "sha256-nopARV2ViNiuyBqGv6KjxLJ3uaaVqRJ3K7Mgtg/mS7Q="; static connect = fields; static upgradeProperties = [ "disabled", 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 067befcb7..25aeaaee0 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import "./search-field.js"; import { J3w1FilterableTable } from "../components/filterable-table.js"; //#region .cache/ui-build/entries/register/filterable-table.js 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 63da3cd5b..169a29a47 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1SearchField } from "../components/search-field.js"; //#region .cache/ui-build/entries/register/search-field.js var element = registerElement("j3w1-search-field", J3w1SearchField); diff --git a/packages/ui/dist/copy/form-builder/element.html b/packages/ui/dist/copy/form-builder/element.html index c504fbb67..72ad127a6 100644 --- a/packages/ui/dist/copy/form-builder/element.html +++ b/packages/ui/dist/copy/form-builder/element.html @@ -1,6 +1,6 @@

The bounded form editor requires JavaScript. Its definition is plain JSON with stable field IDs, labels, help, required flags and explicit option IDs.

+ +

Preview

Definition changes clear preview values. Review validates required values and choices.

+

Transfer definition

Schema version 1 accepts at most 64 KiB and 20 fields. Invalid imports leave the current definition unchanged. Export excludes entered preview values.

The bounded form editor requires JavaScript. Its definition is plain JSON with stable field IDs, labels, help, required flags and explicit option IDs.

diff --git a/packages/ui/dist/copy/form-builder/index.html b/packages/ui/dist/copy/form-builder/index.html index c00886c5c..bba366e68 100644 --- a/packages/ui/dist/copy/form-builder/index.html +++ b/packages/ui/dist/copy/form-builder/index.html @@ -1,7 +1,7 @@ Form builder · j3w1

The bounded form editor requires JavaScript. Its definition is plain JSON with stable field IDs, labels, help, required flags and explicit option IDs.

+ +

Preview

Definition changes clear preview values. Review validates required values and choices.

+

Transfer definition

Schema version 1 accepts at most 64 KiB and 20 fields. Invalid imports leave the current definition unchanged. Export excludes entered preview values.

The bounded form editor requires JavaScript. Its definition is plain JSON with stable field IDs, labels, help, required flags and explicit option IDs.

diff --git a/packages/ui/dist/copy/form-builder/manifest.json b/packages/ui/dist/copy/form-builder/manifest.json index 76ce18794..15d765824 100644 --- a/packages/ui/dist/copy/form-builder/manifest.json +++ b/packages/ui/dist/copy/form-builder/manifest.json @@ -5,26 +5,26 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/form-builder.md", "dependencies": [ "register/form-builder.js", - "chunks/element-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", - "chunks/form-builder-C6Rhfsz6.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", + "chunks/form-builder-C4avSOze.js", "chunks/form-builder-C5Kx5G9b.js", "chunks/form-workflow-DMGni-Gs.js", "chunks/markup-DeQ4bEMR.js" ], "files": { - "runtime/register/form-builder.js": "sha256-eM9TDYrxREfT+vaywPQ8TCrx3X7gAB/fXuj8viaqKzM=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/chunks/form-builder-C6Rhfsz6.js": "sha256-CnwUvLr0BCPWw5F9dlDy1D8Y73slv5huNge/LK40+x8=", + "runtime/register/form-builder.js": "sha256-zzx2G0Mpnm0otVuQM9ahEKFTZLWONt8fx+50KatSAUM=", + "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", + "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", + "runtime/chunks/form-builder-C4avSOze.js": "sha256-+kWLP9s28Z+VcI6eg34y4KyqRM6Lm0nnbOsEL2rJv2Q=", "runtime/chunks/form-builder-C5Kx5G9b.js": "sha256-H2Zi4dAojDJ5ZF7OQWEPsPaCg3kMBiAVVG1k948Yiuw=", "runtime/chunks/form-workflow-DMGni-Gs.js": "sha256-g3g/Afxx3XsClDK4ZfvWQjZKprT6z7Qp1lULS48F0rY=", "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-dgVsrgYuHrvBt6OjTg069abl7yU4iwgXOXUw3n9cB7g=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", - "element.html": "sha256-vq61pWv0xeMFu0tTsDtRWWpAr16AFefjpz5JTSyF440=", - "index.html": "sha256-v74xLbiCzhGoMsKDM8vIO3nwDmWQJymihSOqXqvPlkk=", + "element.html": "sha256-WUjDiy4tZKp/CS/g5I/hIUQY0Mci0zrItPW5k4K7As4=", + "index.html": "sha256-hrjnyBZnoPU8kGIL7jUSLs5EvKHQLCDcBPE6LJPQKfo=", "README.md": "sha256-MGlPh4CEW6DLecBSj7Ym9ww3NAGe8r5V9uANRpZLY48=" } } 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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/form-builder/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/form-builder/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/form-builder/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/form-builder/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/form-builder/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/form-builder/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/form-builder/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/form-builder/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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-C6Rhfsz6.js b/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-C4avSOze.js similarity index 92% rename from packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-C6Rhfsz6.js rename to packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-C4avSOze.js index 2daa2e07f..c7ad23898 100644 --- a/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-C6Rhfsz6.js +++ b/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-C4avSOze.js @@ -1,4 +1,4 @@ -import { t as J3w1Element } from "./element-C1XeXVYC.js"; +import { t as J3w1Element } from "./element-Dovcr9Ky.js"; import { t as mountBuilder } from "./form-builder-C5Kx5G9b.js"; //#region packages/ui/src/behaviors/form-builder.js function formBuilder(root, { signal }) { @@ -22,7 +22,7 @@ function formBuilder(root, { signal }) { var J3w1FormBuilder = class extends J3w1Element { static componentId = "form-builder"; static version = "4.0.0"; - static implementationId = "sha256-uXS+kL7KbvfhlApDhEsvMY+pFsX9bHFlaTF/qUH94mE="; + static implementationId = "sha256-KhHbbANV3xzXIk57mZCL5Uw2aiN4jVv4u4xeVhDxSwU="; static connect = formBuilder; static upgradeProperties = [ "disabled", 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 320e671f8..cb2169fa6 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,5 +1,5 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; -import { t as J3w1FormBuilder } from "../chunks/form-builder-C6Rhfsz6.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { t as J3w1FormBuilder } from "../chunks/form-builder-C4avSOze.js"; //#region .cache/ui-build/entries/register/form-builder.js var element = registerElement("j3w1-form-builder", J3w1FormBuilder); //#endregion diff --git a/packages/ui/dist/copy/i3-window-frame/manifest.json b/packages/ui/dist/copy/i3-window-frame/manifest.json index ba2dedb27..992a32dfa 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/i3-window-frame.js", - "chunks/compositions-d6BkKTYf.js", - "chunks/navigation-Dt8ap-9J.js" + "chunks/compositions-D57dCsBz.js", + "chunks/navigation-BfNzDYZB.js" ], "files": { - "runtime/register/i3-window-frame.js": "sha256-T8BESQEwjGZsf7/+P5mPJcokXWquh+9IX+aeYr2odNE=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/i3-window-frame.js": "sha256-uqfVHNwkr/11a11fshN7f0r/dXipCi1Vfc0AlLb+i9c=", - "runtime/chunks/compositions-d6BkKTYf.js": "sha256-El5csGAVMeeZWmJ1ztdXW3O3t2AQPrf3YrEOMkGX17c=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Yk/0tRkcDttUSZKxyg6O6C9kumrEAGehNElFt382jeA=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/i3-window-frame/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/i3-window-frame/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/i3-window-frame/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/file-browser/runtime/chunks/compositions-d6BkKTYf.js b/packages/ui/dist/copy/i3-window-frame/runtime/chunks/compositions-D57dCsBz.js similarity index 94% rename from packages/ui/dist/copy/file-browser/runtime/chunks/compositions-d6BkKTYf.js rename to packages/ui/dist/copy/i3-window-frame/runtime/chunks/compositions-D57dCsBz.js index 7d70275f2..f1da4562e 100644 --- a/packages/ui/dist/copy/file-browser/runtime/chunks/compositions-d6BkKTYf.js +++ b/packages/ui/dist/copy/i3-window-frame/runtime/chunks/compositions-D57dCsBz.js @@ -1,5 +1,5 @@ -import { i as all, o as enabled } from "./choice-Db_w_BOQ.js"; -import { i as tabs } from "./navigation-Dt8ap-9J.js"; +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 function fileBrowser(root, { on }) { const query = root.querySelector("[data-file-query]"), rows = all(root, "tr[data-file-id]"), status = root.querySelector("[data-file-status]"); diff --git a/packages/ui/dist/copy/i3-window-frame/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/i3-window-frame/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/i3-window-frame/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/i3-window-frame/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/i3-window-frame/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..db2779553 --- /dev/null +++ b/packages/ui/dist/copy/i3-window-frame/runtime/chunks/navigation-BfNzDYZB.js @@ -0,0 +1,377 @@ +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-Dt8ap-9J.js b/packages/ui/dist/copy/i3-window-frame/runtime/chunks/navigation-Dt8ap-9J.js deleted file mode 100644 index 81201c8d5..000000000 --- a/packages/ui/dist/copy/i3-window-frame/runtime/chunks/navigation-Dt8ap-9J.js +++ /dev/null @@ -1,367 +0,0 @@ -import { a as announce, d as rove, f as visible, i as all, l as nativeInput, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.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, event.key === next ? index + 1 : event.key === prev ? index - 1 : event.key === "Home" ? 0 : items.length - 1); - }); - 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, event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : index + (event.key === "ArrowDown" ? 1 : -1)); - } 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/components/i3-window-frame.js b/packages/ui/dist/copy/i3-window-frame/runtime/components/i3-window-frame.js index f7f1bfad9..b22fc628b 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,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { r as windowFrame } from "../chunks/compositions-d6BkKTYf.js"; +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 var J3w1I3WindowFrame = class extends J3w1Element { static componentId = "i3-window-frame"; static version = "4.0.0"; - static implementationId = "sha256-Y4Ce7n8VcttdP/24Otj7l0Ls+ShSo3ACSeSkMKfZg4o="; + static implementationId = "sha256-aoVPpcLCR1nIgTxPmR2un0VYei4XlfuvYsAk1YW7+mU="; static connect = windowFrame; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; 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 dd2360632..75e3eb7d6 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1I3WindowFrame } from "../components/i3-window-frame.js"; //#region .cache/ui-build/entries/register/i3-window-frame.js var element = registerElement("j3w1-i3-window-frame", J3w1I3WindowFrame); diff --git a/packages/ui/dist/copy/icon-button/manifest.json b/packages/ui/dist/copy/icon-button/manifest.json index 9fd13d30d..c21d8e8aa 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/icon-button.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/icon-button.js": "sha256-UWU2VaBVj42dfmtJg9c1yLb2JZ0ObB4FemDN0vyV/uM=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/icon-button.js": "sha256-GQlt7gcCt926nsvoxCtYRyCMMgdI9IZNyV0+40gv/RQ=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-oGnsvpT9vCQjmmGSRaHOeQIJDUE5f5LrSWgR9jdM6/s=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/icon-button/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/icon-button/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/icon-button/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/icon-button/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/icon-button/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/icon-button/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/icon-button/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/icon-button/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/icon-button/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/icon-button/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/icon-button/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/icon-button.js b/packages/ui/dist/copy/icon-button/runtime/components/icon-button.js index 7a65f2c9a..1b617c987 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-C1XeXVYC.js"; -import { t as actions } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1IconButton = class extends J3w1Element { static componentId = "icon-button"; static version = "4.0.0"; - static implementationId = "sha256-yIIam+ZjRGwxBMpAmgZARlOdFeFJZkhR1zP8PoO2q8g="; + static implementationId = "sha256-6B32745m5D4H8EEVZL8U0DDC44RJN37XJIm7LWa43Gg="; static connect = actions; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...[ 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 4a1f9ef47..ffdd0ac88 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1IconButton } from "../components/icon-button.js"; //#region .cache/ui-build/entries/register/icon-button.js var element = registerElement("j3w1-icon-button", J3w1IconButton); diff --git a/packages/ui/dist/copy/kbd/manifest.json b/packages/ui/dist/copy/kbd/manifest.json index 3e1191452..99f234141 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/kbd.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/kbd.js": "sha256-bIqjf3wmYiE5WXjgu0PbMLOsZ/LIWT+En7xpv6yWDNQ=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/kbd.js": "sha256-xi2+ei38C1TTd2xavWMW/PM7cQTzc0o4g+7LNPNHnUQ=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-sKesLjkvspbpsD6walvgEF0NFv1fsIWXNbBy+hhtAUE=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/kbd/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/kbd/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/kbd/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/kbd/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/kbd/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/kbd/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/kbd/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/kbd/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/kbd/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/kbd/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/kbd/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/kbd.js b/packages/ui/dist/copy/kbd/runtime/components/kbd.js index 9b1b92534..0556ef474 100644 --- a/packages/ui/dist/copy/kbd/runtime/components/kbd.js +++ b/packages/ui/dist/copy/kbd/runtime/components/kbd.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Kbd = class extends J3w1Element { static componentId = "kbd"; static version = "4.0.0"; - static implementationId = "sha256-M5H4/+6leZF7LAC7Shi1RDl/6HP+GYN6gzvNdgAGu0o="; + static implementationId = "sha256-/6a09jGbevstnOqzIMGZWFLfMuQtcqnGZ7oWyH64Xdg="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/copy/kbd/runtime/register/kbd.js b/packages/ui/dist/copy/kbd/runtime/register/kbd.js index eed420027..6ae12a7fc 100644 --- a/packages/ui/dist/copy/kbd/runtime/register/kbd.js +++ b/packages/ui/dist/copy/kbd/runtime/register/kbd.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Kbd } from "../components/kbd.js"; //#region .cache/ui-build/entries/register/kbd.js var element = registerElement("j3w1-kbd", J3w1Kbd); diff --git a/packages/ui/dist/copy/link/manifest.json b/packages/ui/dist/copy/link/manifest.json index d16d43ea8..c23ce019f 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/link.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/link.js": "sha256-sR0lpvEqWio1+xbGZ5p+TKd03qMnXyE+UkbdxPPGD9k=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/link.js": "sha256-WC8yN3SdZF28B84F96AQc4WHvgrfmotEdEXUDdPx+gI=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-bMMi6OLOyxVGAoiDlHUR/PYvzH66VbZ4i/UAzrXw4yo=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/link/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/link/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/link/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/link/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/link/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/link/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/link/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/link/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/link/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/link/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/link/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/link.js b/packages/ui/dist/copy/link/runtime/components/link.js index de2420838..2356d4084 100644 --- a/packages/ui/dist/copy/link/runtime/components/link.js +++ b/packages/ui/dist/copy/link/runtime/components/link.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Link = class extends J3w1Element { static componentId = "link"; static version = "4.0.0"; - static implementationId = "sha256-G30Bj9xANI38mlDOkDVPEfBPa0wZWo9ZLpoAHPXMAGE="; + static implementationId = "sha256-rEWDiPkjpyMkw7piXIpFnMc4x8xrVQVhLrBLQWgZXRM="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/copy/link/runtime/register/link.js b/packages/ui/dist/copy/link/runtime/register/link.js index 1ae8adb9e..669ae18ab 100644 --- a/packages/ui/dist/copy/link/runtime/register/link.js +++ b/packages/ui/dist/copy/link/runtime/register/link.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Link } from "../components/link.js"; //#region .cache/ui-build/entries/register/link.js var element = registerElement("j3w1-link", J3w1Link); diff --git a/packages/ui/dist/copy/list/manifest.json b/packages/ui/dist/copy/list/manifest.json index f92f65352..28ff7a2d0 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/list.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/list.js": "sha256-wbjYHGmbf46FoJiajI+Z127P5eUpLr9c6BSonN2FqnQ=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/list.js": "sha256-EfhH50w/Jxw1dj4a/Ul3Xi6WmUlbeRhgpAeATkhO8EU=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-MSEasr2r2kyu8iJSxcX+m4nWTD2FHPKwBU7K8T/9844=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/list/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/list/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/list/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/list/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/list/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/list/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/list/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/list/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/list/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/list/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/list/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/list.js b/packages/ui/dist/copy/list/runtime/components/list.js index 3e5713699..247cffcc3 100644 --- a/packages/ui/dist/copy/list/runtime/components/list.js +++ b/packages/ui/dist/copy/list/runtime/components/list.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1List = class extends J3w1Element { static componentId = "list"; static version = "4.0.0"; - static implementationId = "sha256-bxsrs/DyJ6xpQGoZP+g3PJhsF5XpL6aWGvL7lM0TCNY="; + static implementationId = "sha256-14u9zr26qx+pniqBnH8sp+D6R9pyXRKm+KsUR/WnsOU="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/copy/list/runtime/register/list.js b/packages/ui/dist/copy/list/runtime/register/list.js index 46d02889b..2642fae97 100644 --- a/packages/ui/dist/copy/list/runtime/register/list.js +++ b/packages/ui/dist/copy/list/runtime/register/list.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1List } from "../components/list.js"; //#region .cache/ui-build/entries/register/list.js var element = registerElement("j3w1-list", J3w1List); diff --git a/packages/ui/dist/copy/loading-indicator/manifest.json b/packages/ui/dist/copy/loading-indicator/manifest.json index 6707978d4..74e973142 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/loading-indicator.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/loading-indicator.js": "sha256-4wKk+e/O8cCnxAR2RouY4I5/K1UuOcPjh3ehR7I9oqo=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/loading-indicator.js": "sha256-iTQYSJMXD02jZHXKFvaFfVLsSwVgLrG7ERC0uWAqpvU=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-eNbtRNqnJDdDaKs9tYapfgCNRwMffdQ7e2TqjrYuL6w=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/loading-indicator/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/loading-indicator/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/loading-indicator/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/loading-indicator/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/loading-indicator/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/loading-indicator/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/loading-indicator/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/loading-indicator/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/loading-indicator/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/loading-indicator/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/loading-indicator/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/loading-indicator.js b/packages/ui/dist/copy/loading-indicator/runtime/components/loading-indicator.js index db1fc292b..85ead853a 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,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1LoadingIndicator = class extends J3w1Element { static componentId = "loading-indicator"; static version = "4.0.0"; - static implementationId = "sha256-oylPiWm24mRL7UT6FnHzCqajisyWBH6qEks6sQ4t3Uc="; + static implementationId = "sha256-IeUo78vKcH/jhCptrFf5Js2XH0mNmrbHQA3dBow7Sb8="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; 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 20938b029..5e3a0b442 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1LoadingIndicator } from "../components/loading-indicator.js"; //#region .cache/ui-build/entries/register/loading-indicator.js var element = registerElement("j3w1-loading-indicator", J3w1LoadingIndicator); diff --git a/packages/ui/dist/copy/menu/manifest.json b/packages/ui/dist/copy/menu/manifest.json index 967b0a7f5..0b1f32ce7 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/menu.js", - "chunks/navigation-Dt8ap-9J.js" + "chunks/navigation-BfNzDYZB.js" ], "files": { - "runtime/register/menu.js": "sha256-YX+9ydadaIbkPIBFhLWX4Jv3V9vIl4UY1qolxLGfZUg=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/menu.js": "sha256-AMtJth+M+4jqb8imqdn9VcM3aKvtgCWkPySfsI7htH8=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-SIubQgNKqhuy1abCUQB+rvpnPXZTQ9fiW5Yb6XWT5MQ=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/menu/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/menu/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/menu/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/menu/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/menu/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/menu/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/menu/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/menu/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..db2779553 --- /dev/null +++ b/packages/ui/dist/copy/menu/runtime/chunks/navigation-BfNzDYZB.js @@ -0,0 +1,377 @@ +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-Dt8ap-9J.js b/packages/ui/dist/copy/menu/runtime/chunks/navigation-Dt8ap-9J.js deleted file mode 100644 index 81201c8d5..000000000 --- a/packages/ui/dist/copy/menu/runtime/chunks/navigation-Dt8ap-9J.js +++ /dev/null @@ -1,367 +0,0 @@ -import { a as announce, d as rove, f as visible, i as all, l as nativeInput, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.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, event.key === next ? index + 1 : event.key === prev ? index - 1 : event.key === "Home" ? 0 : items.length - 1); - }); - 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, event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : index + (event.key === "ArrowDown" ? 1 : -1)); - } 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/components/menu.js b/packages/ui/dist/copy/menu/runtime/components/menu.js index 3f1e4b50c..b35ceb43e 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-C1XeXVYC.js"; -import { r as menu } from "../chunks/navigation-Dt8ap-9J.js"; +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 var J3w1Menu = class extends J3w1Element { static componentId = "menu"; static version = "4.0.0"; - static implementationId = "sha256-jIlJcU1Nx7Q5MB7Fqfcn4f9vr0IW1gmGwNdP5Rk72Aw="; + static implementationId = "sha256-oS0Ubl9rLRKcmk22aO7KDARBpUoA/Y7sR2AvyqabH+U="; static connect = menu; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/copy/menu/runtime/register/menu.js b/packages/ui/dist/copy/menu/runtime/register/menu.js index 734c05e98..655b77a5a 100644 --- a/packages/ui/dist/copy/menu/runtime/register/menu.js +++ b/packages/ui/dist/copy/menu/runtime/register/menu.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Menu } from "../components/menu.js"; //#region .cache/ui-build/entries/register/menu.js var element = registerElement("j3w1-menu", J3w1Menu); diff --git a/packages/ui/dist/copy/multiselect/manifest.json b/packages/ui/dist/copy/multiselect/manifest.json index e5a4033b2..57c0be67c 100644 --- a/packages/ui/dist/copy/multiselect/manifest.json +++ b/packages/ui/dist/copy/multiselect/manifest.json @@ -5,18 +5,18 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/multiselect.md", "dependencies": [ "register/multiselect.js", - "chunks/element-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/multiselect.js", - "chunks/advanced-DCpe8Ndv.js", + "chunks/advanced-CqBF0dSb.js", "chunks/markup-DeQ4bEMR.js" ], "files": { - "runtime/register/multiselect.js": "sha256-96pmTEj2wLhjjLNib4gB1d7Twzrt5QcyklLK7RfzavA=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/multiselect.js": "sha256-8L2lHVliSgOdCXDMUzLPyUu9JYyowyYfha4hm57F5/E=", - "runtime/chunks/advanced-DCpe8Ndv.js": "sha256-nr1LFdLYsGeTM4vDyldvuJygRm0F04sYonxatySPu1g=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-NHeO9yzX+pKu8X05cxcbMC+aba6f5KV7SQL1E+N/kKM=", diff --git a/packages/ui/dist/copy/multiselect/runtime/chunks/advanced-DCpe8Ndv.js b/packages/ui/dist/copy/multiselect/runtime/chunks/advanced-CqBF0dSb.js similarity index 97% rename from packages/ui/dist/copy/multiselect/runtime/chunks/advanced-DCpe8Ndv.js rename to packages/ui/dist/copy/multiselect/runtime/chunks/advanced-CqBF0dSb.js index 3390a044c..4a5c45981 100644 --- a/packages/ui/dist/copy/multiselect/runtime/chunks/advanced-DCpe8Ndv.js +++ b/packages/ui/dist/copy/multiselect/runtime/chunks/advanced-CqBF0dSb.js @@ -1,4 +1,4 @@ -import { d as rove, f as visible, i as all, l as nativeInput, o as enabled, s as identify } from "./choice-Db_w_BOQ.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-B7mo5Eq3.js"; import { t as IDREFS } from "./markup-DeQ4bEMR.js"; //#region packages/ui/src/behaviors/advanced.js function tree(root, { on }) { @@ -64,7 +64,12 @@ function tree(root, { on }) { "End" ].includes(event.key)) { event.preventDefault(); - const next = event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : Math.max(0, Math.min(options.length - 1, index + (event.key === "ArrowDown" ? 1 : -1))); + const next = keyIndex({ + key: event.key, + index, + length: options.length, + wrap: false + }); rove(options, next); } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight")) { event.preventDefault(); diff --git a/packages/ui/dist/copy/multiselect/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/multiselect/runtime/chunks/choice-B7mo5Eq3.js new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/multiselect/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/multiselect/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/multiselect/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/multiselect/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/multiselect/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/multiselect/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/multiselect/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/multiselect/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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/components/multiselect.js b/packages/ui/dist/copy/multiselect/runtime/components/multiselect.js index 20a588ed0..cb58ac304 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-C1XeXVYC.js"; -import { n as multiselect } from "../chunks/advanced-DCpe8Ndv.js"; +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 var J3w1Multiselect = class extends J3w1Element { static componentId = "multiselect"; static version = "4.0.0"; - static implementationId = "sha256-OPa5V1nQSQlq4kVkfylH8e9/Aw6ID9xFd3Wd2jg9JT4="; + static implementationId = "sha256-M7eRaWl+u1uQgXFKvnBd0GCc8U7xIWfp5yT7U9eMjTg="; static connect = multiselect; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/copy/multiselect/runtime/register/multiselect.js b/packages/ui/dist/copy/multiselect/runtime/register/multiselect.js index 8a91da5b0..9183e5e5a 100644 --- a/packages/ui/dist/copy/multiselect/runtime/register/multiselect.js +++ b/packages/ui/dist/copy/multiselect/runtime/register/multiselect.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Multiselect } from "../components/multiselect.js"; //#region .cache/ui-build/entries/register/multiselect.js var element = registerElement("j3w1-multiselect", J3w1Multiselect); diff --git a/packages/ui/dist/copy/number-field/manifest.json b/packages/ui/dist/copy/number-field/manifest.json index aa318a149..35d791137 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/number-field.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/number-field.js": "sha256-jCevLNvnx84VrjcqcaLN+LoayqMvlOZqbeB0vfcKCTw=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/number-field.js": "sha256-27HebtimgA50TSf1kwNGySNCBamP+Cu+9VCSbvOxcDg=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-agyrkFz7FiKZpcU4J9QsaeTNRYBw7yWJQcMOdSd8SPc=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/number-field/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/number-field/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/number-field/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/number-field/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/number-field/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/number-field/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/number-field/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/number-field/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/number-field/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/number-field/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/number-field/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/number-field.js b/packages/ui/dist/copy/number-field/runtime/components/number-field.js index af0b10715..41733ea16 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1NumberField = class extends J3w1Element { static componentId = "number-field"; static version = "4.0.0"; - static implementationId = "sha256-gb44C85yifc6xKGrJuKPEX7vvpX08h4rRm5NPWN3woo="; + static implementationId = "sha256-XSucS362OAqtU9RKAYp52Tc3M6K6uMWKmB6UdK8+/o0="; static connect = fields; static upgradeProperties = [ "disabled", 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 c8e0e7c36..8553c5a33 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1NumberField } from "../components/number-field.js"; //#region .cache/ui-build/entries/register/number-field.js var element = registerElement("j3w1-number-field", J3w1NumberField); diff --git a/packages/ui/dist/copy/pagination/manifest.json b/packages/ui/dist/copy/pagination/manifest.json index 2e0632af6..e9ef886d0 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/pagination.js", - "chunks/tables-B25ydUHs.js" + "chunks/tables-Cjr1EIJz.js" ], "files": { - "runtime/register/pagination.js": "sha256-pgp0U5vF4tER52b++qgmdpAuRSmpiybgRt6HfLmtBqU=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/pagination.js": "sha256-yrEJa21eYjbFYfF3K/IdLp2FXFcKGFkLEVD4bxibWrE=", - "runtime/chunks/tables-B25ydUHs.js": "sha256-XqRdyfrSS93rVybWHq6a0WhrmZgaboHi5n8ymgwRbM8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-J6AIVbVHNyS581oA3enNH84ZCf3yRHxSsjlqUa9Z6d0=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/pagination/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/pagination/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/pagination/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/pagination/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/pagination/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/pagination/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/pagination/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/pagination/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/pagination/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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-B25ydUHs.js b/packages/ui/dist/copy/pagination/runtime/chunks/tables-Cjr1EIJz.js similarity index 96% rename from packages/ui/dist/chunks/tables-B25ydUHs.js rename to packages/ui/dist/copy/pagination/runtime/chunks/tables-Cjr1EIJz.js index 172bab830..f82aaf25e 100644 --- a/packages/ui/dist/chunks/tables-B25ydUHs.js +++ b/packages/ui/dist/copy/pagination/runtime/chunks/tables-Cjr1EIJz.js @@ -1,4 +1,4 @@ -import { d as rove, i as all, o as enabled, s as identify } from "./choice-Db_w_BOQ.js"; +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]; @@ -106,7 +106,12 @@ function table(root, { on }) { "End" ].includes(event.key)) return; event.preventDefault(); - const nextIndex = event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : Math.max(0, Math.min(options.length - 1, index + (event.key === "ArrowDown" ? 1 : -1))); + const nextIndex = keyIndex({ + key: event.key, + index, + length: options.length, + wrap: false + }); const next = rove(options, nextIndex); if (event.shiftKey && selectAll) { anchor ??= row; diff --git a/packages/ui/dist/copy/pagination/runtime/components/pagination.js b/packages/ui/dist/copy/pagination/runtime/components/pagination.js index ef3f9cb03..140293f27 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-C1XeXVYC.js"; -import { t as pagination } from "../chunks/tables-B25ydUHs.js"; +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 var J3w1Pagination = class extends J3w1Element { static componentId = "pagination"; static version = "4.0.0"; - static implementationId = "sha256-euvVvLa2uqHPWf4lao8liCwhVeUZHrDFF8Z30hRttNg="; + static implementationId = "sha256-HgWIYJ3ex0Ayw+BLic3BdN3dNV9ChkM7wiwgp/qkkAE="; static connect = pagination; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/copy/pagination/runtime/register/pagination.js b/packages/ui/dist/copy/pagination/runtime/register/pagination.js index 2dfeec151..26680a048 100644 --- a/packages/ui/dist/copy/pagination/runtime/register/pagination.js +++ b/packages/ui/dist/copy/pagination/runtime/register/pagination.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Pagination } from "../components/pagination.js"; //#region .cache/ui-build/entries/register/pagination.js var element = registerElement("j3w1-pagination", J3w1Pagination); diff --git a/packages/ui/dist/copy/popover/manifest.json b/packages/ui/dist/copy/popover/manifest.json index 1c598b30f..951f9984d 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/popover.js", - "chunks/overlays-C6nlCHqg.js" + "chunks/overlays-Bw8SSDKz.js" ], "files": { - "runtime/register/popover.js": "sha256-eWKTLAUIMPauNqccfCSWaTkpN6Eyrj+GtlvM7FRaKHc=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/popover.js": "sha256-P63Ou+ew1qtVXdZkxnO6uM5ZG7w9hOBlPK+HNXQbkAU=", - "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", + "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-qVz5uQ2xxsSVcKXfgit5JgjSZ3kzPvm9/Mt3A4X1NEg=", + "runtime/chunks/overlays-Bw8SSDKz.js": "sha256-YrX9CL2A48QwI7COQQ5anYJLPOxpKrIeyz+jtfp+T+I=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-53zGKZZyZMB+sdGIbnQk30oFXcLvjoplsW7FfQ9W0u0=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/popover/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/popover/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/popover/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/popover/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/popover/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/popover/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/popover/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/popover/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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-Bw8SSDKz.js b/packages/ui/dist/copy/popover/runtime/chunks/overlays-Bw8SSDKz.js new file mode 100644 index 000000000..3eeb8ff0d --- /dev/null +++ b/packages/ui/dist/copy/popover/runtime/chunks/overlays-Bw8SSDKz.js @@ -0,0 +1,236 @@ +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, dismissed = false, hovering = false; + const stop = () => { + clearTimeout(timer); + }; + const hide = () => { + stop(); + popup.hidden = true; + }; + const show = () => { + stop(); + if (!dismissed) { + popup.hidden = false; + place(trigger, popup); + } + }; + on(trigger, "pointerenter", (event) => { + if (event.pointerType !== "touch") { + hovering = true; + dismissed = false; + timer = setTimeout(show, 300); + } + }); + on(root, "pointerleave", (event) => { + if (!root.contains(event.relatedTarget)) { + hovering = false; + dismissed = false; + if (root.ownerDocument.activeElement !== trigger) hide(); + } + }); + 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/chunks/overlays-C6nlCHqg.js b/packages/ui/dist/copy/popover/runtime/chunks/overlays-C6nlCHqg.js deleted file mode 100644 index 9df8503ec..000000000 --- a/packages/ui/dist/copy/popover/runtime/chunks/overlays-C6nlCHqg.js +++ /dev/null @@ -1,236 +0,0 @@ -import { i as all, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.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, dismissed = false, hovering = false; - const stop = () => { - clearTimeout(timer); - }; - const hide = () => { - stop(); - popup.hidden = true; - }; - const show = () => { - stop(); - if (!dismissed) { - popup.hidden = false; - place(trigger, popup); - } - }; - on(trigger, "pointerenter", (event) => { - if (event.pointerType !== "touch") { - hovering = true; - dismissed = false; - timer = setTimeout(show, 300); - } - }); - on(root, "pointerleave", (event) => { - if (!root.contains(event.relatedTarget)) { - hovering = false; - dismissed = false; - if (root.ownerDocument.activeElement !== trigger) hide(); - } - }); - 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 bbc79107c..4ca710f90 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-C1XeXVYC.js"; -import { r as popover } from "../chunks/overlays-C6nlCHqg.js"; +import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; +import { r as popover } from "../chunks/overlays-Bw8SSDKz.js"; //#region .cache/ui-build/entries/components/popover.js var J3w1Popover = class extends J3w1Element { static componentId = "popover"; static version = "4.0.0"; - static implementationId = "sha256-R3mF1UXSn1CBWM10egGi9EjTZGc775igXYWKiLNBZSY="; + static implementationId = "sha256-8KG7XOC5HTOmJW+CysUIXfhkV3COWEwpPzmG6HXdN80="; static connect = popover; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/copy/popover/runtime/register/popover.js b/packages/ui/dist/copy/popover/runtime/register/popover.js index 4a5798987..5f801317f 100644 --- a/packages/ui/dist/copy/popover/runtime/register/popover.js +++ b/packages/ui/dist/copy/popover/runtime/register/popover.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Popover } from "../components/popover.js"; //#region .cache/ui-build/entries/register/popover.js var element = registerElement("j3w1-popover", J3w1Popover); diff --git a/packages/ui/dist/copy/progress/manifest.json b/packages/ui/dist/copy/progress/manifest.json index 43d34b01c..1503d03dc 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/progress.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/progress.js": "sha256-wcMNQVWBoGiWoasImip5urxM4QZkIIiDqdTbDHFb09c=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/progress.js": "sha256-SoIKI41QOIzDVzCbEX4RjUwuYIgyVdRipglbNI30PdE=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-qVh6/s9QPg2t6WrczrtP5i8fP1blV8a6S9OZUF5oJdY=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/progress/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/progress/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/progress/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/progress/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/progress/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/progress/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/progress/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/progress/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/progress/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/progress/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/progress/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/progress.js b/packages/ui/dist/copy/progress/runtime/components/progress.js index 2328cc005..c4664d716 100644 --- a/packages/ui/dist/copy/progress/runtime/components/progress.js +++ b/packages/ui/dist/copy/progress/runtime/components/progress.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Progress = class extends J3w1Element { static componentId = "progress"; static version = "4.0.0"; - static implementationId = "sha256-pb/hnKbLN1fkkVEzliJMaxoY12bTHrD8nlVbfWNTXGE="; + static implementationId = "sha256-ayNpjS/tJF/VzILGmci24aDE3GR3edKDd1sGAVN7HtQ="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/copy/progress/runtime/register/progress.js b/packages/ui/dist/copy/progress/runtime/register/progress.js index 54bd975e5..29de54fb7 100644 --- a/packages/ui/dist/copy/progress/runtime/register/progress.js +++ b/packages/ui/dist/copy/progress/runtime/register/progress.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Progress } from "../components/progress.js"; //#region .cache/ui-build/entries/register/progress.js var element = registerElement("j3w1-progress", J3w1Progress); diff --git a/packages/ui/dist/copy/radio-group/manifest.json b/packages/ui/dist/copy/radio-group/manifest.json index 19bc2600c..55c5980bc 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/radio-group.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/radio-group.js": "sha256-L7TPdkL+uckYkNZ8nwZWjfTisSvOmPO7rqB3QlmfaTI=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/radio-group.js": "sha256-UtfAZUI/Cr3R29YvS/0As27FUks0dSZ5e2Jcx6yDfxk=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Ig6nuF1jMxOL71ppi7cvN8DjEKs9unk/ugZ0b1XTImY=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/radio-group/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/radio-group/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/radio-group/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/radio-group/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/radio-group/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/radio-group/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/radio-group/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/radio-group/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/radio-group/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/radio-group/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/radio-group/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/radio-group.js b/packages/ui/dist/copy/radio-group/runtime/components/radio-group.js index e82d3422f..9c5100135 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,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1RadioGroup = class extends J3w1Element { static componentId = "radio-group"; static version = "4.0.0"; - static implementationId = "sha256-zaWExle/kKyvESOFtr11ZVTV64fMoCjROxiCHKlvwyY="; + static implementationId = "sha256-qoOHybVksZNlma+H614aGdgiZ/u0EegTSeDcIojBXA0="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; 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 e40f29b44..a41f213ff 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1RadioGroup } from "../components/radio-group.js"; //#region .cache/ui-build/entries/register/radio-group.js var element = registerElement("j3w1-radio-group", J3w1RadioGroup); diff --git a/packages/ui/dist/copy/range/manifest.json b/packages/ui/dist/copy/range/manifest.json index 13d25c2a9..b978fdaf7 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/range.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/range.js": "sha256-g8jU/JKj2ySLza7/G+XS4TC2NE8Gwuw6lyc+G1k9pi4=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/range.js": "sha256-uAqR2sA5IXjunYSDuvl+0MoUbuwonAPLwhQFCExPI/I=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-XwLMipanpFGzjbmGs1VEzJL/+7DPUuYTewuadW6x3zE=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/range/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/range/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/range/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/range/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/range/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/range/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/range/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/range/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/range/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/range/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/range/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/range.js b/packages/ui/dist/copy/range/runtime/components/range.js index 8c18e09bc..b560b2a51 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Range = class extends J3w1Element { static componentId = "range"; static version = "4.0.0"; - static implementationId = "sha256-775qtEkdJpV+XXDTSY5Jta+nPBg9zq9OpoCwXoM1X30="; + static implementationId = "sha256-zCJuNTps0+QV29mUu6dGnyhnpifuS7WnpWWjLJtkpdo="; static connect = fields; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/copy/range/runtime/register/range.js b/packages/ui/dist/copy/range/runtime/register/range.js index 9711437a7..63b83eab7 100644 --- a/packages/ui/dist/copy/range/runtime/register/range.js +++ b/packages/ui/dist/copy/range/runtime/register/range.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Range } from "../components/range.js"; //#region .cache/ui-build/entries/register/range.js var element = registerElement("j3w1-range", J3w1Range); diff --git a/packages/ui/dist/copy/repeater/manifest.json b/packages/ui/dist/copy/repeater/manifest.json index bad57a698..8c209aad3 100644 --- a/packages/ui/dist/copy/repeater/manifest.json +++ b/packages/ui/dist/copy/repeater/manifest.json @@ -5,18 +5,18 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/repeater.md", "dependencies": [ "register/repeater.js", - "chunks/element-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/repeater.js", - "chunks/advanced-DCpe8Ndv.js", + "chunks/advanced-CqBF0dSb.js", "chunks/markup-DeQ4bEMR.js" ], "files": { - "runtime/register/repeater.js": "sha256-CL1MU0vVSqQyPhS6UQWzKLVZqxO0fbuljqqDRE9GvUA=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/repeater.js": "sha256-pe+MgGoQpseF+J8HpfkS5wU84MsVLuCJl6BAzoyS+lU=", - "runtime/chunks/advanced-DCpe8Ndv.js": "sha256-nr1LFdLYsGeTM4vDyldvuJygRm0F04sYonxatySPu1g=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-IEhREL5vlXFRdDmE8HHaqwhAbMJ8feOqTJ5MMrQGztk=", diff --git a/packages/ui/dist/copy/repeater/runtime/chunks/advanced-CqBF0dSb.js b/packages/ui/dist/copy/repeater/runtime/chunks/advanced-CqBF0dSb.js new file mode 100644 index 000000000..4a5c45981 --- /dev/null +++ b/packages/ui/dist/copy/repeater/runtime/chunks/advanced-CqBF0dSb.js @@ -0,0 +1,345 @@ +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/advanced-DCpe8Ndv.js b/packages/ui/dist/copy/repeater/runtime/chunks/advanced-DCpe8Ndv.js deleted file mode 100644 index 3390a044c..000000000 --- a/packages/ui/dist/copy/repeater/runtime/chunks/advanced-DCpe8Ndv.js +++ /dev/null @@ -1,340 +0,0 @@ -import { d as rove, f as visible, i as all, l as nativeInput, o as enabled, s as identify } from "./choice-Db_w_BOQ.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 = event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : Math.max(0, Math.min(options.length - 1, index + (event.key === "ArrowDown" ? 1 : -1))); - 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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/repeater/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/repeater/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/repeater/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/repeater/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/repeater/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/repeater/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/repeater/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/repeater/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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/components/repeater.js b/packages/ui/dist/copy/repeater/runtime/components/repeater.js index 1660aee7c..0874370f2 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-C1XeXVYC.js"; -import { r as repeater } from "../chunks/advanced-DCpe8Ndv.js"; +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 var J3w1Repeater = class extends J3w1Element { static componentId = "repeater"; static version = "4.0.0"; - static implementationId = "sha256-Tx+pvPHZeC66CE52/uMEXatMD8QBTtQd+OahbHnBVuY="; + static implementationId = "sha256-G3uVYtEsLo70OmMPhofMD2YylFEq1kezRvUEMrNnRII="; static connect = repeater; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...[ diff --git a/packages/ui/dist/copy/repeater/runtime/register/repeater.js b/packages/ui/dist/copy/repeater/runtime/register/repeater.js index b53fb3ce5..6565442ff 100644 --- a/packages/ui/dist/copy/repeater/runtime/register/repeater.js +++ b/packages/ui/dist/copy/repeater/runtime/register/repeater.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Repeater } from "../components/repeater.js"; //#region .cache/ui-build/entries/register/repeater.js var element = registerElement("j3w1-repeater", J3w1Repeater); diff --git a/packages/ui/dist/copy/search-field/manifest.json b/packages/ui/dist/copy/search-field/manifest.json index 9d1ba700a..5cc7e844c 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/search-field.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/search-field.js": "sha256-Z6IeX4+LKGVQJUcQGuyUnCBL6ggQSoevMhrj75zYisw=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/search-field.js": "sha256-2ODKfrgzC53SjMT+P7oaRa78AgRY37MG12M7HVRwfQU=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-LKiZdfWdQXHUoEdFnG1o5Aka8mOS8NP98IdndPFnsbQ=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/search-field/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/search-field/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/search-field/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/search-field/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/search-field/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/search-field/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/search-field/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/search-field/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/search-field/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/search-field/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/search-field/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/search-field.js b/packages/ui/dist/copy/search-field/runtime/components/search-field.js index 4d97313b6..666ca6dde 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1SearchField = class extends J3w1Element { static componentId = "search-field"; static version = "4.0.0"; - static implementationId = "sha256-1DXqGUME/dceUQ+jjPOv/UDtTubfoV13HCjmaDde06w="; + static implementationId = "sha256-nopARV2ViNiuyBqGv6KjxLJ3uaaVqRJ3K7Mgtg/mS7Q="; static connect = fields; static upgradeProperties = [ "disabled", 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 63da3cd5b..169a29a47 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1SearchField } from "../components/search-field.js"; //#region .cache/ui-build/entries/register/search-field.js var element = registerElement("j3w1-search-field", J3w1SearchField); diff --git a/packages/ui/dist/copy/segmented-control/manifest.json b/packages/ui/dist/copy/segmented-control/manifest.json index 53fe3d934..2cb47988f 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/segmented-control.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/segmented-control.js": "sha256-Hp1iRTlBtVJffhsTkXPWleCnHa8ag50yeW35VsnXQ4c=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/segmented-control.js": "sha256-xN4DQLVyEFJSMDcuTBBrd//fR3iSCEjqnQHkYV4GtbE=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Dq4r47NU2yi+AVRCcT0g+RV5YoPw7Z3JUhDMJqtUoJM=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/segmented-control/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/segmented-control/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/segmented-control/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/segmented-control/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/segmented-control/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/segmented-control/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/segmented-control/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/segmented-control/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/segmented-control/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/segmented-control/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/segmented-control/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/segmented-control.js b/packages/ui/dist/copy/segmented-control/runtime/components/segmented-control.js index e72128f6a..6ffc9b94e 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,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1SegmentedControl = class extends J3w1Element { static componentId = "segmented-control"; static version = "4.0.0"; - static implementationId = "sha256-9PLNL13EHbz4Q4W5X5YLzVqofRhbsR0BeD0TPmji/8Q="; + static implementationId = "sha256-ULY50CCb++GAub0Bdb1hOwDWjDszJVNB0Fwnbmwbg1c="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; 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 20f7f4d8a..526fd7f71 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1SegmentedControl } from "../components/segmented-control.js"; //#region .cache/ui-build/entries/register/segmented-control.js var element = registerElement("j3w1-segmented-control", J3w1SegmentedControl); diff --git a/packages/ui/dist/copy/select/manifest.json b/packages/ui/dist/copy/select/manifest.json index 0adc6d554..46096ff1a 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/select.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/select.js": "sha256-zXXuJRnrp9EVnk1A8VpgUzF/JPShcAImY9zRc6nQasQ=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/select.js": "sha256-yyq0jsJOysQGTPpFoA1C1aRWSIukrk+M4Ro2ZwCyWbw=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-F7S6++WxoGrwiPfTq2NRQciL64rhre0zZKEhwee9I1E=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/select/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/select/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/select/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/select/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/select/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/select/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/select/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/select/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/select/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/select/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/select/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/select.js b/packages/ui/dist/copy/select/runtime/components/select.js index f15a0462d..a59b0acab 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Select = class extends J3w1Element { static componentId = "select"; static version = "4.0.0"; - static implementationId = "sha256-x5f4XAk757Fq5+Tl0cEgt1x3VCTPpITjazQZUo+WpvQ="; + static implementationId = "sha256-/4CAqDSF84DTC0pEcQUtcmmtAaVge6ifWVX3elTZzLM="; static connect = fields; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/copy/select/runtime/register/select.js b/packages/ui/dist/copy/select/runtime/register/select.js index b97661d55..6fcd3d855 100644 --- a/packages/ui/dist/copy/select/runtime/register/select.js +++ b/packages/ui/dist/copy/select/runtime/register/select.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Select } from "../components/select.js"; //#region .cache/ui-build/entries/register/select.js var element = registerElement("j3w1-select", J3w1Select); diff --git a/packages/ui/dist/copy/settings-panel/manifest.json b/packages/ui/dist/copy/settings-panel/manifest.json index b0dcd7f9c..f01823c00 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "register/switch.js", "components/switch.js", - "chunks/native-CAzZmDKR.js", + "chunks/native-BjBt1sUh.js", "components/settings-panel.js", - "chunks/forms-BT3z7lNC.js" + "chunks/forms-CE_hP1hg.js" ], "files": { - "runtime/register/settings-panel.js": "sha256-tecYNnB3mOO1ir+NYaorlqzgeTXRhGpkaMeZZ5TKo7k=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/register/switch.js": "sha256-WA0Avt/JJmz7DqxDx8v5Rnw3WCZFaVGJjPdibTQKkSc=", - "runtime/components/switch.js": "sha256-Cad08u/MHjqLKKV0MpUQNKaHz1fLJnvy5dfayoqsjvI=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "runtime/components/settings-panel.js": "sha256-eL+HBTD98ipggaB6cWxKOgb2UXkBgKT50n7xxlWPHn0=", - "runtime/chunks/forms-BT3z7lNC.js": "sha256-Txmae07dWLj1H/FL869U0Kv84TQxzpdFeOg0g8zGK6I=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-bKV+vxJoQcQ+/WSkUADY0AkxpU9pAMAviGj+BrOQK1w=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/settings-panel/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/settings-panel/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/settings-panel/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/settings-panel/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/settings-panel/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/settings-panel/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/settings-panel/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/settings-panel/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/settings-panel/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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-BT3z7lNC.js b/packages/ui/dist/copy/settings-panel/runtime/chunks/forms-CE_hP1hg.js similarity index 98% rename from packages/ui/dist/copy/admin-form/runtime/chunks/forms-BT3z7lNC.js rename to packages/ui/dist/copy/settings-panel/runtime/chunks/forms-CE_hP1hg.js index 65f1f0e71..6ad3b48f5 100644 --- a/packages/ui/dist/copy/admin-form/runtime/chunks/forms-BT3z7lNC.js +++ b/packages/ui/dist/copy/settings-panel/runtime/chunks/forms-CE_hP1hg.js @@ -1,4 +1,4 @@ -import { c as make, i as all, o as enabled } from "./choice-Db_w_BOQ.js"; +import { i as all, l as make, o as enabled } from "./choice-B7mo5Eq3.js"; //#region 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"); 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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/settings-panel/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/settings-panel/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/settings-panel/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/settings-panel.js b/packages/ui/dist/copy/settings-panel/runtime/components/settings-panel.js index 0d8bf3d6a..4d48521a3 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,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { t as formComposition } from "../chunks/forms-BT3z7lNC.js"; +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 var J3w1SettingsPanel = class extends J3w1Element { static componentId = "settings-panel"; static version = "4.0.0"; - static implementationId = "sha256-EIIJELO3DpCDTENzI+0vWiDG0OCBjrf8QBh5vGHkR/M="; + static implementationId = "sha256-Or1edewP4Rk9HC/kFygK+IUyEoPDHJFEyWO9Acv3Ge4="; static connect = formComposition; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; 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 8dd46651f..87c027482 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-C1XeXVYC.js"; -import { a as switchControl } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Switch = class extends J3w1Element { static componentId = "switch"; static version = "4.0.0"; - static implementationId = "sha256-Wsym3Y7lkfx+vDtiTBtZS2h3anSfvc8bYabeqBAc4ms="; + static implementationId = "sha256-FqTv7TNhvOBWq10QKBC1FBB+4Wxd4wo2qtt4bCUEvbA="; static connect = switchControl; static upgradeProperties = [ "disabled", 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 20c582b67..0067d590e 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import "./switch.js"; import { J3w1SettingsPanel } from "../components/settings-panel.js"; //#region .cache/ui-build/entries/register/settings-panel.js 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 05a2f592f..5e227ec0d 100644 --- a/packages/ui/dist/copy/settings-panel/runtime/register/switch.js +++ b/packages/ui/dist/copy/settings-panel/runtime/register/switch.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Switch } from "../components/switch.js"; //#region .cache/ui-build/entries/register/switch.js var element = registerElement("j3w1-switch", J3w1Switch); diff --git a/packages/ui/dist/copy/sidebar-nav/manifest.json b/packages/ui/dist/copy/sidebar-nav/manifest.json index f93673f85..74f1a40a2 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/sidebar-nav.js", - "chunks/navigation-Dt8ap-9J.js" + "chunks/navigation-BfNzDYZB.js" ], "files": { - "runtime/register/sidebar-nav.js": "sha256-X/t0V38SB2UnmTa0KqYTvD4OKdvRFtsN75azWmcPa90=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/sidebar-nav.js": "sha256-LfEAicAsreVm6Jp/H/ocft61HelJ6RZo1rIPWFWRCCU=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-daIsd5K5mOs8Mmspd3m8ktJKgxTzPCRGoQY/6MQCDww=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/sidebar-nav/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/sidebar-nav/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/sidebar-nav/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/sidebar-nav/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/sidebar-nav/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/sidebar-nav/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/sidebar-nav/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/sidebar-nav/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..db2779553 --- /dev/null +++ b/packages/ui/dist/copy/sidebar-nav/runtime/chunks/navigation-BfNzDYZB.js @@ -0,0 +1,377 @@ +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-Dt8ap-9J.js b/packages/ui/dist/copy/sidebar-nav/runtime/chunks/navigation-Dt8ap-9J.js deleted file mode 100644 index 81201c8d5..000000000 --- a/packages/ui/dist/copy/sidebar-nav/runtime/chunks/navigation-Dt8ap-9J.js +++ /dev/null @@ -1,367 +0,0 @@ -import { a as announce, d as rove, f as visible, i as all, l as nativeInput, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.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, event.key === next ? index + 1 : event.key === prev ? index - 1 : event.key === "Home" ? 0 : items.length - 1); - }); - 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, event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : index + (event.key === "ArrowDown" ? 1 : -1)); - } 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/components/sidebar-nav.js b/packages/ui/dist/copy/sidebar-nav/runtime/components/sidebar-nav.js index 17b99366b..03f391cbd 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-C1XeXVYC.js"; -import { n as disclosure } from "../chunks/navigation-Dt8ap-9J.js"; +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 var J3w1SidebarNav = class extends J3w1Element { static componentId = "sidebar-nav"; static version = "4.0.0"; - static implementationId = "sha256-7P+xFrwVfLOcV9jD54m5q0GPgMxEknJwkB/ex41V9/E="; + static implementationId = "sha256-rKjBWaKv0/VZBCTIvYNnUx/X/HyPypn7MJrL9+nt6cM="; static connect = disclosure; static upgradeProperties = [ "disabled", 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 8f0297afb..59f4cc44a 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1SidebarNav } from "../components/sidebar-nav.js"; //#region .cache/ui-build/entries/register/sidebar-nav.js var element = registerElement("j3w1-sidebar-nav", J3w1SidebarNav); diff --git a/packages/ui/dist/copy/skeleton/manifest.json b/packages/ui/dist/copy/skeleton/manifest.json index 1127c0d44..057f38618 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/skeleton.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/skeleton.js": "sha256-LZWZWuDy/lr/JDq+2VL59KCkU2EurStRQaUsuNF4US4=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/skeleton.js": "sha256-Ou8+/8NCHGRzG6ik6k6762M8G4PMLaBQXj4aPynetXo=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-JI92x7GOktbjpIm0AQnODJ4rVTJnEQA4DLP34bflM4k=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/skeleton/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/skeleton/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/skeleton/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/skeleton/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/skeleton/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/skeleton/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/skeleton/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/skeleton/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/skeleton/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/skeleton/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/skeleton/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/skeleton.js b/packages/ui/dist/copy/skeleton/runtime/components/skeleton.js index c6e8e7fc4..16c0393a3 100644 --- a/packages/ui/dist/copy/skeleton/runtime/components/skeleton.js +++ b/packages/ui/dist/copy/skeleton/runtime/components/skeleton.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Skeleton = class extends J3w1Element { static componentId = "skeleton"; static version = "4.0.0"; - static implementationId = "sha256-fM5rtzoVG8RbNxxxkZnyxAlMU2Y7X34uknqD80CcjkA="; + static implementationId = "sha256-ZyHv2dS6YAfZGShU1uHi9YjORc4siAkmG4ledp4rX5I="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/copy/skeleton/runtime/register/skeleton.js b/packages/ui/dist/copy/skeleton/runtime/register/skeleton.js index 71f911e98..ed0ab489a 100644 --- a/packages/ui/dist/copy/skeleton/runtime/register/skeleton.js +++ b/packages/ui/dist/copy/skeleton/runtime/register/skeleton.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Skeleton } from "../components/skeleton.js"; //#region .cache/ui-build/entries/register/skeleton.js var element = registerElement("j3w1-skeleton", J3w1Skeleton); diff --git a/packages/ui/dist/copy/skip-link/manifest.json b/packages/ui/dist/copy/skip-link/manifest.json index 4dca9be87..209ced812 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/skip-link.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/skip-link.js": "sha256-J3W8TBKgxKkjPInemg2o0yMPFluGS5Q/lPN9NQYBXAo=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/skip-link.js": "sha256-PjQqYJSg0aTsGAbfb9qa+aisYGXDJgGgWN+ZwS/vgFQ=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-KCkIExZyQJQhySZCEQIOrm9lPtDzOq95R9+IED0MI8A=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/skip-link/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/skip-link/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/skip-link/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/skip-link/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/skip-link/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/skip-link/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/skip-link/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/skip-link/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/skip-link/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/skip-link/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/skip-link/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/skip-link.js b/packages/ui/dist/copy/skip-link/runtime/components/skip-link.js index 31537fda3..65021bd9d 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,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1SkipLink = class extends J3w1Element { static componentId = "skip-link"; static version = "4.0.0"; - static implementationId = "sha256-KdblE6x/JhgGz9zwqnBxtLslwBM2YaG4D+gQYhv8+U8="; + static implementationId = "sha256-S77cz706XKgfI8OMLIyAhZab0PRCJkMplNQrcZjKP3c="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; 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 24e9f3d0c..7f93eeef8 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1SkipLink } from "../components/skip-link.js"; //#region .cache/ui-build/entries/register/skip-link.js var element = registerElement("j3w1-skip-link", J3w1SkipLink); diff --git a/packages/ui/dist/copy/switch/manifest.json b/packages/ui/dist/copy/switch/manifest.json index aa583d23b..ea90ec62f 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/switch.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/switch.js": "sha256-WA0Avt/JJmz7DqxDx8v5Rnw3WCZFaVGJjPdibTQKkSc=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/switch.js": "sha256-Cad08u/MHjqLKKV0MpUQNKaHz1fLJnvy5dfayoqsjvI=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-wQ5f/FFGWolJtnjyPar452XqRgkIhBLJEQbc8ziQvag=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/switch/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/switch/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/switch/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/switch/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/switch/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/switch/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/switch/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/switch/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/switch/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/switch/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/switch/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/switch.js b/packages/ui/dist/copy/switch/runtime/components/switch.js index 8dd46651f..87c027482 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-C1XeXVYC.js"; -import { a as switchControl } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Switch = class extends J3w1Element { static componentId = "switch"; static version = "4.0.0"; - static implementationId = "sha256-Wsym3Y7lkfx+vDtiTBtZS2h3anSfvc8bYabeqBAc4ms="; + static implementationId = "sha256-FqTv7TNhvOBWq10QKBC1FBB+4Wxd4wo2qtt4bCUEvbA="; static connect = switchControl; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/copy/switch/runtime/register/switch.js b/packages/ui/dist/copy/switch/runtime/register/switch.js index 05a2f592f..5e227ec0d 100644 --- a/packages/ui/dist/copy/switch/runtime/register/switch.js +++ b/packages/ui/dist/copy/switch/runtime/register/switch.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Switch } from "../components/switch.js"; //#region .cache/ui-build/entries/register/switch.js var element = registerElement("j3w1-switch", J3w1Switch); diff --git a/packages/ui/dist/copy/table/manifest.json b/packages/ui/dist/copy/table/manifest.json index 525560668..f51dfe76b 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/table.js", - "chunks/tables-B25ydUHs.js" + "chunks/tables-Cjr1EIJz.js" ], "files": { - "runtime/register/table.js": "sha256-MdQKdnzPN7NGGdLpVWq6qbgJvHQFdZaIpYLaOLJxRfo=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/table.js": "sha256-leonu0udFEH8CaIXE0yhLXubdVcLX8V/g+fDayFea7E=", - "runtime/chunks/tables-B25ydUHs.js": "sha256-XqRdyfrSS93rVybWHq6a0WhrmZgaboHi5n8ymgwRbM8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-ZLczhksx4+OpxZGChcR6o/jBIHldhOt8XpRDJPyDfeU=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/table/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/table/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/table/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/table/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/table/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/table/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/table/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/table/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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-B25ydUHs.js b/packages/ui/dist/copy/table/runtime/chunks/tables-B25ydUHs.js deleted file mode 100644 index 172bab830..000000000 --- a/packages/ui/dist/copy/table/runtime/chunks/tables-B25ydUHs.js +++ /dev/null @@ -1,212 +0,0 @@ -import { d as rove, i as all, o as enabled, s as identify } from "./choice-Db_w_BOQ.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 = event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : Math.max(0, Math.min(options.length - 1, index + (event.key === "ArrowDown" ? 1 : -1))); - 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-Cjr1EIJz.js b/packages/ui/dist/copy/table/runtime/chunks/tables-Cjr1EIJz.js new file mode 100644 index 000000000..f82aaf25e --- /dev/null +++ b/packages/ui/dist/copy/table/runtime/chunks/tables-Cjr1EIJz.js @@ -0,0 +1,217 @@ +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/components/table.js b/packages/ui/dist/copy/table/runtime/components/table.js index 747e23ad7..a79632ad4 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-C1XeXVYC.js"; -import { n as table } from "../chunks/tables-B25ydUHs.js"; +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 var J3w1Table = class extends J3w1Element { static componentId = "table"; static version = "4.0.0"; - static implementationId = "sha256-1o7THlBOZhryugncv5/v3bAs3dEZx7OD0QGD47Fx2q4="; + static implementationId = "sha256-dYinCl3vod1TSMh+SSPtibWEFlVRwhAF7TZ09eviokw="; static connect = table; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/copy/table/runtime/register/table.js b/packages/ui/dist/copy/table/runtime/register/table.js index 10a75676a..b8eda4f9d 100644 --- a/packages/ui/dist/copy/table/runtime/register/table.js +++ b/packages/ui/dist/copy/table/runtime/register/table.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Table } from "../components/table.js"; //#region .cache/ui-build/entries/register/table.js var element = registerElement("j3w1-table", J3w1Table); diff --git a/packages/ui/dist/copy/tabs/manifest.json b/packages/ui/dist/copy/tabs/manifest.json index ae1b96e4b..21965ae04 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/tabs.js", - "chunks/navigation-Dt8ap-9J.js" + "chunks/navigation-BfNzDYZB.js" ], "files": { - "runtime/register/tabs.js": "sha256-ZNIa4RlyyzL89jDO8N637zceDABaxE+yPzulw77+N9c=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/tabs.js": "sha256-42FcvN/By1ouS+HE0CiZ9FaasHLpN8HY7TiypjcFkdQ=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-zVXkxQteKGqZmvOgx444SE+3ubxZ6YdRaGci9hT3GeU=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/tabs/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/tabs/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/tabs/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/tabs/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/tabs/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/tabs/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/tabs/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/tabs/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..db2779553 --- /dev/null +++ b/packages/ui/dist/copy/tabs/runtime/chunks/navigation-BfNzDYZB.js @@ -0,0 +1,377 @@ +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-Dt8ap-9J.js b/packages/ui/dist/copy/tabs/runtime/chunks/navigation-Dt8ap-9J.js deleted file mode 100644 index 81201c8d5..000000000 --- a/packages/ui/dist/copy/tabs/runtime/chunks/navigation-Dt8ap-9J.js +++ /dev/null @@ -1,367 +0,0 @@ -import { a as announce, d as rove, f as visible, i as all, l as nativeInput, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.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, event.key === next ? index + 1 : event.key === prev ? index - 1 : event.key === "Home" ? 0 : items.length - 1); - }); - 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, event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : index + (event.key === "ArrowDown" ? 1 : -1)); - } 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/components/tabs.js b/packages/ui/dist/copy/tabs/runtime/components/tabs.js index dfdc18518..448e73b8b 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-C1XeXVYC.js"; -import { i as tabs } from "../chunks/navigation-Dt8ap-9J.js"; +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 var J3w1Tabs = class extends J3w1Element { static componentId = "tabs"; static version = "4.0.0"; - static implementationId = "sha256-yl6ifi/c/BHYGqaMMbePuD6uCP50aeMMOiJFXfy/C6s="; + static implementationId = "sha256-vWyT4Mr1GxnXVkpNXHK/nd/+0BmdRogsb7+eE6EnQ7A="; static connect = tabs; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/copy/tabs/runtime/register/tabs.js b/packages/ui/dist/copy/tabs/runtime/register/tabs.js index d2f3bb53e..218ebc6da 100644 --- a/packages/ui/dist/copy/tabs/runtime/register/tabs.js +++ b/packages/ui/dist/copy/tabs/runtime/register/tabs.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Tabs } from "../components/tabs.js"; //#region .cache/ui-build/entries/register/tabs.js var element = registerElement("j3w1-tabs", J3w1Tabs); diff --git a/packages/ui/dist/copy/terminal/manifest.json b/packages/ui/dist/copy/terminal/manifest.json index 40f88d737..dd653f333 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/terminal.js", - "chunks/display-dj9YaBfn.js" + "chunks/display-Jm9bAsnb.js" ], "files": { - "runtime/register/terminal.js": "sha256-HI+Ed6H0sblV3/oR4o14WYg9OG1oLmgIOC/HbV2sFos=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/terminal.js": "sha256-nnvO5VIA3kECyTshxbykc7AqrK88ML0IDEe6bYvfsQs=", - "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-U9mukzoAnquuoQ1KFzbK6bI+fxJdrdrhSiZgfwulwJM=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/terminal/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/terminal/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/terminal/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place 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 new file mode 100644 index 000000000..5bc817830 --- /dev/null +++ b/packages/ui/dist/copy/terminal/runtime/chunks/display-Jm9bAsnb.js @@ -0,0 +1,212 @@ +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-dj9YaBfn.js b/packages/ui/dist/copy/terminal/runtime/chunks/display-dj9YaBfn.js deleted file mode 100644 index 80833d5da..000000000 --- a/packages/ui/dist/copy/terminal/runtime/chunks/display-dj9YaBfn.js +++ /dev/null @@ -1,212 +0,0 @@ -import { c as make, i as all, o as enabled } from "./choice-Db_w_BOQ.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/element-C1XeXVYC.js b/packages/ui/dist/copy/terminal/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/terminal/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/terminal/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/terminal/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 b6b36123c..d9c12358a 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-C1XeXVYC.js"; -import { r as developerView } from "../chunks/display-dj9YaBfn.js"; +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 var J3w1Terminal = class extends J3w1Element { static componentId = "terminal"; static version = "4.0.0"; - static implementationId = "sha256-YtjoIQGA3MHvquAi/l7AGweWpTNBe/ruD7iYJIEkkoc="; + static implementationId = "sha256-vnYvMfEFdH6UbGXHQ5OrfeJTspczt8hiaTWYnXnhlJc="; static connect = developerView; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/copy/terminal/runtime/register/terminal.js b/packages/ui/dist/copy/terminal/runtime/register/terminal.js index 252927e52..0f41964d0 100644 --- a/packages/ui/dist/copy/terminal/runtime/register/terminal.js +++ b/packages/ui/dist/copy/terminal/runtime/register/terminal.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Terminal } from "../components/terminal.js"; //#region .cache/ui-build/entries/register/terminal.js var element = registerElement("j3w1-terminal", J3w1Terminal); diff --git a/packages/ui/dist/copy/text-field/manifest.json b/packages/ui/dist/copy/text-field/manifest.json index 71b32a046..683243fa8 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/text-field.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/text-field.js": "sha256-DD+ctMlKClOK6B/glshiJwIjKilewzY171GvKtVGf1A=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/text-field.js": "sha256-6f5tLWwF57IFY+uH5zM0afiU3g09PW3M4772zC7zD4Q=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Y3xQDYeeCQmNtobwOfTiTh/OVHOCJt5If76c4411/ns=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/text-field/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/text-field/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/text-field/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/text-field/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/text-field/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/text-field/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/text-field/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/text-field/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/text-field/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/text-field/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/text-field/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/text-field.js b/packages/ui/dist/copy/text-field/runtime/components/text-field.js index 469ab73da..5f6946538 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1TextField = class extends J3w1Element { static componentId = "text-field"; static version = "4.0.0"; - static implementationId = "sha256-zLqXpOHelLAc+ttryZKIkoe3xzw0YRD1AHJXXSXMwdg="; + static implementationId = "sha256-k06i0LBPa/oPe2VNmxbJkBzisp1zcAENq3MeVnKZzAo="; static connect = fields; static upgradeProperties = [ "disabled", 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 e3bf71d74..01007e107 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1TextField } from "../components/text-field.js"; //#region .cache/ui-build/entries/register/text-field.js var element = registerElement("j3w1-text-field", J3w1TextField); diff --git a/packages/ui/dist/copy/textarea/manifest.json b/packages/ui/dist/copy/textarea/manifest.json index 00bbcb881..0b2c2c5a4 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/textarea.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/textarea.js": "sha256-H+BMjmdgnMxVEA9KvLSSKoOlHTAH91Qy7+pjUiTlgEE=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/textarea.js": "sha256-qJqDEskuaVeBUFjefVF+KSbJV3s6vpaKCtd4aQ4QtoY=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-BbcGdXHTnD7C55UItp05tibzn6AUyioSMT0hgk45J68=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/textarea/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/textarea/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/textarea/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/textarea/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/textarea/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/textarea/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/textarea/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/textarea/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/textarea/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/textarea/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/textarea/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/textarea.js b/packages/ui/dist/copy/textarea/runtime/components/textarea.js index 35ed045a1..850762b41 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Textarea = class extends J3w1Element { static componentId = "textarea"; static version = "4.0.0"; - static implementationId = "sha256-hrpvVFypogHx9xxUI1Lemq3AlNYBkdbjqujfPFl8BM0="; + static implementationId = "sha256-BoVEmVsZUWTLPVMKc4WLoQfNpjGc4Wy8j7o7zHck1uQ="; static connect = fields; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/copy/textarea/runtime/register/textarea.js b/packages/ui/dist/copy/textarea/runtime/register/textarea.js index ea76ce485..2e9a5db69 100644 --- a/packages/ui/dist/copy/textarea/runtime/register/textarea.js +++ b/packages/ui/dist/copy/textarea/runtime/register/textarea.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Textarea } from "../components/textarea.js"; //#region .cache/ui-build/entries/register/textarea.js var element = registerElement("j3w1-textarea", J3w1Textarea); diff --git a/packages/ui/dist/copy/time-picker/manifest.json b/packages/ui/dist/copy/time-picker/manifest.json index f0235953b..6c706a87b 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/time-picker.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/time-picker.js": "sha256-2BVpwqf8Gmd8NnGgY7TdxAtrN4oIOg8cMn0kMOqj9Y4=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/time-picker.js": "sha256-K1tUYKUlk8oOLnC7XwOpKWl/CUzqs0NmsRJ38SjjI1U=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-J5VoJUQp+zDREm8yqwh0jq7TRzMH+H8XMK+3CWxjgIU=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/time-picker/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/time-picker/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/time-picker/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/time-picker/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/time-picker/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/time-picker/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/time-picker/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/time-picker/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/time-picker/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/time-picker/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/time-picker/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/time-picker.js b/packages/ui/dist/copy/time-picker/runtime/components/time-picker.js index 384dca63b..182becce4 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-C1XeXVYC.js"; -import { r as fields } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1TimePicker = class extends J3w1Element { static componentId = "time-picker"; static version = "4.0.0"; - static implementationId = "sha256-NixIqVSP1+pZBmD/nUflx8v6ZEWVt0qAVhGMMZv7eWQ="; + static implementationId = "sha256-IYFVpO+yyMztyk5IQgkfuuyrieY/xyLgcisHM1D02DA="; static connect = fields; static upgradeProperties = [ "disabled", 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 244c895c6..f69ab0f23 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,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1TimePicker } from "../components/time-picker.js"; //#region .cache/ui-build/entries/register/time-picker.js var element = registerElement("j3w1-time-picker", J3w1TimePicker); diff --git a/packages/ui/dist/copy/timeline/manifest.json b/packages/ui/dist/copy/timeline/manifest.json index 257ae2756..80515ac27 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/timeline.js", - "chunks/native-CAzZmDKR.js" + "chunks/native-BjBt1sUh.js" ], "files": { - "runtime/register/timeline.js": "sha256-DmcJVvF9PvFZM0ka0qgQH9L6lE7TCHhDf56kHMV+SA4=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/timeline.js": "sha256-c1+8tebuE76i5IkY1RRqwNlDkRBrhVwBH4BiCMTSBs4=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-VnvBxMC1c6IWen0gQ3RLi0m3FOelH4E8j4xG+B5Zoas=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/timeline/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/timeline/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/timeline/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/timeline/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/timeline/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/timeline/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/timeline/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/timeline/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..032f76c74 --- /dev/null +++ b/packages/ui/dist/copy/timeline/runtime/chunks/native-BjBt1sUh.js @@ -0,0 +1,289 @@ +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-CAzZmDKR.js b/packages/ui/dist/copy/timeline/runtime/chunks/native-CAzZmDKR.js deleted file mode 100644 index 558c774e5..000000000 --- a/packages/ui/dist/copy/timeline/runtime/chunks/native-CAzZmDKR.js +++ /dev/null @@ -1,289 +0,0 @@ -import { c as make, i as all, l as nativeInput, n as mountChoice, o as enabled, r as mountTemporal } from "./choice-Db_w_BOQ.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/components/timeline.js b/packages/ui/dist/copy/timeline/runtime/components/timeline.js index 49eeb39d4..b5e0249ea 100644 --- a/packages/ui/dist/copy/timeline/runtime/components/timeline.js +++ b/packages/ui/dist/copy/timeline/runtime/components/timeline.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { n as content } from "../chunks/native-CAzZmDKR.js"; +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 var J3w1Timeline = class extends J3w1Element { static componentId = "timeline"; static version = "4.0.0"; - static implementationId = "sha256-CHqFmIx9nQ6y8hgR0WE3+faD/i7oj5KwbMMOpibojI4="; + static implementationId = "sha256-AeDLITSMVmcqyJwXO1iz+6eWe9/9kWYL6lepUxS5ZtU="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/copy/timeline/runtime/register/timeline.js b/packages/ui/dist/copy/timeline/runtime/register/timeline.js index 82d652b24..6b8f4b354 100644 --- a/packages/ui/dist/copy/timeline/runtime/register/timeline.js +++ b/packages/ui/dist/copy/timeline/runtime/register/timeline.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Timeline } from "../components/timeline.js"; //#region .cache/ui-build/entries/register/timeline.js var element = registerElement("j3w1-timeline", J3w1Timeline); diff --git a/packages/ui/dist/copy/toast/manifest.json b/packages/ui/dist/copy/toast/manifest.json index b87a5e7c4..ec8d78f00 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/toast.js", - "chunks/overlays-C6nlCHqg.js" + "chunks/overlays-Bw8SSDKz.js" ], "files": { - "runtime/register/toast.js": "sha256-IdIE1uz4eUV1mu94jhavw3kQx9Omawr6aMO+ij/EIRU=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/toast.js": "sha256-v6J5D8moC3m7GxC2mVYytkK8MOkwHSwODcmKmj1Kkgk=", - "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", + "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-WIMDZ+G0PKE8LTL9S9wLE1enIZrIXAt4h0Isi5xnGTU=", + "runtime/chunks/overlays-Bw8SSDKz.js": "sha256-YrX9CL2A48QwI7COQQ5anYJLPOxpKrIeyz+jtfp+T+I=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-dMp7q8HbznH2LxwbeRaoK7WL/2M2GeVwkitql3aJ3GE=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/toast/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/toast/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/toast/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/toast/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/toast/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/toast/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/toast/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/toast/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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-Bw8SSDKz.js b/packages/ui/dist/copy/toast/runtime/chunks/overlays-Bw8SSDKz.js new file mode 100644 index 000000000..3eeb8ff0d --- /dev/null +++ b/packages/ui/dist/copy/toast/runtime/chunks/overlays-Bw8SSDKz.js @@ -0,0 +1,236 @@ +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, dismissed = false, hovering = false; + const stop = () => { + clearTimeout(timer); + }; + const hide = () => { + stop(); + popup.hidden = true; + }; + const show = () => { + stop(); + if (!dismissed) { + popup.hidden = false; + place(trigger, popup); + } + }; + on(trigger, "pointerenter", (event) => { + if (event.pointerType !== "touch") { + hovering = true; + dismissed = false; + timer = setTimeout(show, 300); + } + }); + on(root, "pointerleave", (event) => { + if (!root.contains(event.relatedTarget)) { + hovering = false; + dismissed = false; + if (root.ownerDocument.activeElement !== trigger) hide(); + } + }); + 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/chunks/overlays-C6nlCHqg.js b/packages/ui/dist/copy/toast/runtime/chunks/overlays-C6nlCHqg.js deleted file mode 100644 index 9df8503ec..000000000 --- a/packages/ui/dist/copy/toast/runtime/chunks/overlays-C6nlCHqg.js +++ /dev/null @@ -1,236 +0,0 @@ -import { i as all, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.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, dismissed = false, hovering = false; - const stop = () => { - clearTimeout(timer); - }; - const hide = () => { - stop(); - popup.hidden = true; - }; - const show = () => { - stop(); - if (!dismissed) { - popup.hidden = false; - place(trigger, popup); - } - }; - on(trigger, "pointerenter", (event) => { - if (event.pointerType !== "touch") { - hovering = true; - dismissed = false; - timer = setTimeout(show, 300); - } - }); - on(root, "pointerleave", (event) => { - if (!root.contains(event.relatedTarget)) { - hovering = false; - dismissed = false; - if (root.ownerDocument.activeElement !== trigger) hide(); - } - }); - 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 bfce21732..b400752aa 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-C1XeXVYC.js"; -import { t as feedback } from "../chunks/overlays-C6nlCHqg.js"; +import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; +import { t as feedback } from "../chunks/overlays-Bw8SSDKz.js"; //#region .cache/ui-build/entries/components/toast.js var J3w1Toast = class extends J3w1Element { static componentId = "toast"; static version = "4.0.0"; - static implementationId = "sha256-rhHX0XsrYevsAon0WzlROHjbfJksZhr/XraWeBmZhxA="; + static implementationId = "sha256-BqW1X3i3Z1X0gaHK/29B1mrUpyhmHpV2a30eW/aK+y4="; static connect = feedback; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/copy/toast/runtime/register/toast.js b/packages/ui/dist/copy/toast/runtime/register/toast.js index 39672f0fe..55941b8ec 100644 --- a/packages/ui/dist/copy/toast/runtime/register/toast.js +++ b/packages/ui/dist/copy/toast/runtime/register/toast.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Toast } from "../components/toast.js"; //#region .cache/ui-build/entries/register/toast.js var element = registerElement("j3w1-toast", J3w1Toast); diff --git a/packages/ui/dist/copy/toolbar/manifest.json b/packages/ui/dist/copy/toolbar/manifest.json index 0ad1503f9..2210a0419 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/toolbar.js", - "chunks/navigation-Dt8ap-9J.js", + "chunks/navigation-BfNzDYZB.js", "register/menu.js", "components/menu.js" ], "files": { - "runtime/register/toolbar.js": "sha256-OSMJIpjPl64KP4YMacdMSLwBugQjcBJHhX/8qyJT0aM=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/toolbar.js": "sha256-xBBCFoguW9JGO+jaNyPrdGYVP2YwJ4BhX3FWPRxoqfs=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "runtime/register/menu.js": "sha256-YX+9ydadaIbkPIBFhLWX4Jv3V9vIl4UY1qolxLGfZUg=", - "runtime/components/menu.js": "sha256-AMtJth+M+4jqb8imqdn9VcM3aKvtgCWkPySfsI7htH8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-uTfyFdWFrx91RdklrAzqAHNf5B2q1psaqjlF71eT+Xc=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/toolbar/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/toolbar/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/toolbar/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/toolbar/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/toolbar/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/toolbar/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/toolbar/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/toolbar/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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 new file mode 100644 index 000000000..db2779553 --- /dev/null +++ b/packages/ui/dist/copy/toolbar/runtime/chunks/navigation-BfNzDYZB.js @@ -0,0 +1,377 @@ +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-Dt8ap-9J.js b/packages/ui/dist/copy/toolbar/runtime/chunks/navigation-Dt8ap-9J.js deleted file mode 100644 index 81201c8d5..000000000 --- a/packages/ui/dist/copy/toolbar/runtime/chunks/navigation-Dt8ap-9J.js +++ /dev/null @@ -1,367 +0,0 @@ -import { a as announce, d as rove, f as visible, i as all, l as nativeInput, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.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, event.key === next ? index + 1 : event.key === prev ? index - 1 : event.key === "Home" ? 0 : items.length - 1); - }); - 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, event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : index + (event.key === "ArrowDown" ? 1 : -1)); - } 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/components/menu.js b/packages/ui/dist/copy/toolbar/runtime/components/menu.js index 3f1e4b50c..b35ceb43e 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-C1XeXVYC.js"; -import { r as menu } from "../chunks/navigation-Dt8ap-9J.js"; +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 var J3w1Menu = class extends J3w1Element { static componentId = "menu"; static version = "4.0.0"; - static implementationId = "sha256-jIlJcU1Nx7Q5MB7Fqfcn4f9vr0IW1gmGwNdP5Rk72Aw="; + static implementationId = "sha256-oS0Ubl9rLRKcmk22aO7KDARBpUoA/Y7sR2AvyqabH+U="; static connect = menu; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/copy/toolbar/runtime/components/toolbar.js b/packages/ui/dist/copy/toolbar/runtime/components/toolbar.js index c2b5f4a84..195494e1d 100644 --- a/packages/ui/dist/copy/toolbar/runtime/components/toolbar.js +++ b/packages/ui/dist/copy/toolbar/runtime/components/toolbar.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-C1XeXVYC.js"; -import { a as toolbar } from "../chunks/navigation-Dt8ap-9J.js"; +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 var J3w1Toolbar = class extends J3w1Element { static componentId = "toolbar"; static version = "4.0.0"; - static implementationId = "sha256-7FoTDU41k2QPRk6gXO/G9yZKsFEuxE/63FSt+FSMAlQ="; + static implementationId = "sha256-VCE2y9mKILLuKe6e6CYb+KzHmhM/oKWGD3XWHaHGRw0="; static connect = toolbar; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/copy/toolbar/runtime/register/menu.js b/packages/ui/dist/copy/toolbar/runtime/register/menu.js index 734c05e98..655b77a5a 100644 --- a/packages/ui/dist/copy/toolbar/runtime/register/menu.js +++ b/packages/ui/dist/copy/toolbar/runtime/register/menu.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Menu } from "../components/menu.js"; //#region .cache/ui-build/entries/register/menu.js var element = registerElement("j3w1-menu", J3w1Menu); diff --git a/packages/ui/dist/copy/toolbar/runtime/register/toolbar.js b/packages/ui/dist/copy/toolbar/runtime/register/toolbar.js index e39eab7da..0de0d853e 100644 --- a/packages/ui/dist/copy/toolbar/runtime/register/toolbar.js +++ b/packages/ui/dist/copy/toolbar/runtime/register/toolbar.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Toolbar } from "../components/toolbar.js"; import "./menu.js"; //#region .cache/ui-build/entries/register/toolbar.js diff --git a/packages/ui/dist/copy/tooltip/manifest.json b/packages/ui/dist/copy/tooltip/manifest.json index 8c8004da2..b2222fd9c 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/tooltip.js", - "chunks/overlays-C6nlCHqg.js" + "chunks/overlays-Bw8SSDKz.js" ], "files": { - "runtime/register/tooltip.js": "sha256-HkIZuQ8Gs11kQ0MzBEIBWrfaPopBPdUh+ODRas1HzLk=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/tooltip.js": "sha256-3/N04wmhF1WPLWW0LBMN2pFnpLGTy7p7toYw2pZpNw0=", - "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", + "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-MhBgu8Nu2Vx7dqARBvSKFOY+LCcOut1TAcB/5QSwPPI=", + "runtime/chunks/overlays-Bw8SSDKz.js": "sha256-YrX9CL2A48QwI7COQQ5anYJLPOxpKrIeyz+jtfp+T+I=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Skdu3czE82hMaq0VZwtG6ERV4Hud75l3iMhOfMR7K7U=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/tooltip/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/tooltip/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/tooltip/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/tooltip/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/tooltip/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/tooltip/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/tooltip/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/tooltip/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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-Bw8SSDKz.js b/packages/ui/dist/copy/tooltip/runtime/chunks/overlays-Bw8SSDKz.js new file mode 100644 index 000000000..3eeb8ff0d --- /dev/null +++ b/packages/ui/dist/copy/tooltip/runtime/chunks/overlays-Bw8SSDKz.js @@ -0,0 +1,236 @@ +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, dismissed = false, hovering = false; + const stop = () => { + clearTimeout(timer); + }; + const hide = () => { + stop(); + popup.hidden = true; + }; + const show = () => { + stop(); + if (!dismissed) { + popup.hidden = false; + place(trigger, popup); + } + }; + on(trigger, "pointerenter", (event) => { + if (event.pointerType !== "touch") { + hovering = true; + dismissed = false; + timer = setTimeout(show, 300); + } + }); + on(root, "pointerleave", (event) => { + if (!root.contains(event.relatedTarget)) { + hovering = false; + dismissed = false; + if (root.ownerDocument.activeElement !== trigger) hide(); + } + }); + 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/chunks/overlays-C6nlCHqg.js b/packages/ui/dist/copy/tooltip/runtime/chunks/overlays-C6nlCHqg.js deleted file mode 100644 index 9df8503ec..000000000 --- a/packages/ui/dist/copy/tooltip/runtime/chunks/overlays-C6nlCHqg.js +++ /dev/null @@ -1,236 +0,0 @@ -import { i as all, o as enabled, s as identify, u as place } from "./choice-Db_w_BOQ.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, dismissed = false, hovering = false; - const stop = () => { - clearTimeout(timer); - }; - const hide = () => { - stop(); - popup.hidden = true; - }; - const show = () => { - stop(); - if (!dismissed) { - popup.hidden = false; - place(trigger, popup); - } - }; - on(trigger, "pointerenter", (event) => { - if (event.pointerType !== "touch") { - hovering = true; - dismissed = false; - timer = setTimeout(show, 300); - } - }); - on(root, "pointerleave", (event) => { - if (!root.contains(event.relatedTarget)) { - hovering = false; - dismissed = false; - if (root.ownerDocument.activeElement !== trigger) hide(); - } - }); - 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 a796e5788..e641fa5b8 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-C1XeXVYC.js"; -import { i as tooltip } from "../chunks/overlays-C6nlCHqg.js"; +import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; +import { i as tooltip } from "../chunks/overlays-Bw8SSDKz.js"; //#region .cache/ui-build/entries/components/tooltip.js var J3w1Tooltip = class extends J3w1Element { static componentId = "tooltip"; static version = "4.0.0"; - static implementationId = "sha256-nhRIjLsKxdM5/M6c+0RvOzlv1sK6VJDshft6xhMUbtE="; + static implementationId = "sha256-GLt9uL8KQ+UknDKUAP+CEU7bTChO5TO3WPwmpJzH62M="; static connect = tooltip; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; diff --git a/packages/ui/dist/copy/tooltip/runtime/register/tooltip.js b/packages/ui/dist/copy/tooltip/runtime/register/tooltip.js index b8308dd65..262fbe4be 100644 --- a/packages/ui/dist/copy/tooltip/runtime/register/tooltip.js +++ b/packages/ui/dist/copy/tooltip/runtime/register/tooltip.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Tooltip } from "../components/tooltip.js"; //#region .cache/ui-build/entries/register/tooltip.js var element = registerElement("j3w1-tooltip", J3w1Tooltip); diff --git a/packages/ui/dist/copy/tree/manifest.json b/packages/ui/dist/copy/tree/manifest.json index 16c631511..325bbc4f8 100644 --- a/packages/ui/dist/copy/tree/manifest.json +++ b/packages/ui/dist/copy/tree/manifest.json @@ -5,18 +5,18 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/tree.md", "dependencies": [ "register/tree.js", - "chunks/element-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/tree.js", - "chunks/advanced-DCpe8Ndv.js", + "chunks/advanced-CqBF0dSb.js", "chunks/markup-DeQ4bEMR.js" ], "files": { - "runtime/register/tree.js": "sha256-xY8jWYnbMM8UlE/rdQJsu3/URGPvdUC06U1QmKsmFZQ=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/tree.js": "sha256-1wgpPM9BoC1/T0Or37ZhoekuO2YZ3luXp+DpWKVKBcU=", - "runtime/chunks/advanced-DCpe8Ndv.js": "sha256-nr1LFdLYsGeTM4vDyldvuJygRm0F04sYonxatySPu1g=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-CMMLz+0autEo86UbTxzkyHVpMoNtyKskesgbIua+YiQ=", diff --git a/packages/ui/dist/copy/tree/runtime/chunks/advanced-CqBF0dSb.js b/packages/ui/dist/copy/tree/runtime/chunks/advanced-CqBF0dSb.js new file mode 100644 index 000000000..4a5c45981 --- /dev/null +++ b/packages/ui/dist/copy/tree/runtime/chunks/advanced-CqBF0dSb.js @@ -0,0 +1,345 @@ +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/advanced-DCpe8Ndv.js b/packages/ui/dist/copy/tree/runtime/chunks/advanced-DCpe8Ndv.js deleted file mode 100644 index 3390a044c..000000000 --- a/packages/ui/dist/copy/tree/runtime/chunks/advanced-DCpe8Ndv.js +++ /dev/null @@ -1,340 +0,0 @@ -import { d as rove, f as visible, i as all, l as nativeInput, o as enabled, s as identify } from "./choice-Db_w_BOQ.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 = event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : Math.max(0, Math.min(options.length - 1, index + (event.key === "ArrowDown" ? 1 : -1))); - 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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/tree/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/tree/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/tree/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/tree/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/tree/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/tree/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/tree/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/tree/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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/components/tree.js b/packages/ui/dist/copy/tree/runtime/components/tree.js index 8a8288b08..e0f6bd8da 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-C1XeXVYC.js"; -import { i as tree } from "../chunks/advanced-DCpe8Ndv.js"; +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 var J3w1Tree = class extends J3w1Element { static componentId = "tree"; static version = "4.0.0"; - static implementationId = "sha256-MaBLx3mLOk+RW8kMweDInlVoWjSFctZly5Jz9BMRFRI="; + static implementationId = "sha256-8E6bGMMWEmhgjIAfuDs1+pxcabRicShQao3beIvcNBY="; static connect = tree; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/copy/tree/runtime/register/tree.js b/packages/ui/dist/copy/tree/runtime/register/tree.js index c6b7d3d39..0ecee9bca 100644 --- a/packages/ui/dist/copy/tree/runtime/register/tree.js +++ b/packages/ui/dist/copy/tree/runtime/register/tree.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Tree } from "../components/tree.js"; //#region .cache/ui-build/entries/register/tree.js var element = registerElement("j3w1-tree", J3w1Tree); diff --git a/packages/ui/dist/copy/wizard/manifest.json b/packages/ui/dist/copy/wizard/manifest.json index eff65cd79..4d5b23b62 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-C1XeXVYC.js", - "chunks/choice-Db_w_BOQ.js", + "chunks/element-Dovcr9Ky.js", + "chunks/choice-B7mo5Eq3.js", "components/wizard.js", - "chunks/forms-BT3z7lNC.js" + "chunks/forms-CE_hP1hg.js" ], "files": { - "runtime/register/wizard.js": "sha256-8JwKlLD2lG42fsQh0+nf+OZ0pvg6Vy7Uexn7bdkWEe0=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/wizard.js": "sha256-WMaA9QqPtqe0dUBowMDw++tHyL+HZFO8+VoCJpn+HXM=", - "runtime/chunks/forms-BT3z7lNC.js": "sha256-Txmae07dWLj1H/FL869U0Kv84TQxzpdFeOg0g8zGK6I=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-TIsUn3die+vDqK/B4+HqIiSctLsbfAW5EflsX5y1oJA=", "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 new file mode 100644 index 000000000..849c80b8b --- /dev/null +++ b/packages/ui/dist/copy/wizard/runtime/chunks/choice-B7mo5Eq3.js @@ -0,0 +1,938 @@ +//#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-Db_w_BOQ.js b/packages/ui/dist/copy/wizard/runtime/chunks/choice-Db_w_BOQ.js deleted file mode 100644 index aebc478b6..000000000 --- a/packages/ui/dist/copy/wizard/runtime/chunks/choice-Db_w_BOQ.js +++ /dev/null @@ -1,932 +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 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, make as c, rove as d, visible as f, all as i, nativeInput as l, mountChoice as n, enabled as o, mountTemporal as r, identify as s, enhanceControls as t, place as u }; diff --git a/packages/ui/dist/copy/wizard/runtime/chunks/element-C1XeXVYC.js b/packages/ui/dist/copy/wizard/runtime/chunks/element-C1XeXVYC.js deleted file mode 100644 index a943f150d..000000000 --- a/packages/ui/dist/copy/wizard/runtime/chunks/element-C1XeXVYC.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-Db_w_BOQ.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/element-Dovcr9Ky.js b/packages/ui/dist/copy/wizard/runtime/chunks/element-Dovcr9Ky.js new file mode 100644 index 000000000..aa7a67cb4 --- /dev/null +++ b/packages/ui/dist/copy/wizard/runtime/chunks/element-Dovcr9Ky.js @@ -0,0 +1,232 @@ +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-BT3z7lNC.js b/packages/ui/dist/copy/wizard/runtime/chunks/forms-CE_hP1hg.js similarity index 98% rename from packages/ui/dist/copy/wizard/runtime/chunks/forms-BT3z7lNC.js rename to packages/ui/dist/copy/wizard/runtime/chunks/forms-CE_hP1hg.js index 65f1f0e71..6ad3b48f5 100644 --- a/packages/ui/dist/copy/wizard/runtime/chunks/forms-BT3z7lNC.js +++ b/packages/ui/dist/copy/wizard/runtime/chunks/forms-CE_hP1hg.js @@ -1,4 +1,4 @@ -import { c as make, i as all, o as enabled } from "./choice-Db_w_BOQ.js"; +import { i as all, l as make, o as enabled } from "./choice-B7mo5Eq3.js"; //#region 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"); diff --git a/packages/ui/dist/copy/wizard/runtime/components/wizard.js b/packages/ui/dist/copy/wizard/runtime/components/wizard.js index 4d9bbaefc..852097735 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-C1XeXVYC.js"; -import { n as wizard } from "../chunks/forms-BT3z7lNC.js"; +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 var J3w1Wizard = class extends J3w1Element { static componentId = "wizard"; static version = "4.0.0"; - static implementationId = "sha256-io0DYHj45iX5Dvck9xDTbxK9av2V6Z42KQERETAWGb4="; + static implementationId = "sha256-RPzZPFnWZYndDTCn4JxgWR8s+kGEDCPgKxzzaesMZdk="; static connect = wizard; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/copy/wizard/runtime/register/wizard.js b/packages/ui/dist/copy/wizard/runtime/register/wizard.js index e78c20e3e..df8a879a1 100644 --- a/packages/ui/dist/copy/wizard/runtime/register/wizard.js +++ b/packages/ui/dist/copy/wizard/runtime/register/wizard.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Wizard } from "../components/wizard.js"; //#region .cache/ui-build/entries/register/wizard.js var element = registerElement("j3w1-wizard", J3w1Wizard); diff --git a/packages/ui/dist/enhance/choice.js b/packages/ui/dist/enhance/choice.js index 518c7eb43..7b9f12b2c 100644 --- a/packages/ui/dist/enhance/choice.js +++ b/packages/ui/dist/enhance/choice.js @@ -1 +1 @@ -export { t as enhanceControls } from "../chunks/choice-Db_w_BOQ.js"; +export { t as enhanceControls } from "../chunks/choice-B7mo5Eq3.js"; diff --git a/packages/ui/dist/examples.json b/packages/ui/dist/examples.json index bcb95cf26..4589aa688 100644 --- a/packages/ui/dist/examples.json +++ b/packages/ui/dist/examples.json @@ -93,7 +93,7 @@ "icons": "

Step 1 of 4: Source

" }, "form-builder": { - "default": "

The bounded form editor requires JavaScript. Its definition is plain JSON with stable field IDs, labels, help, required flags and explicit option IDs.

" + "default": "

The bounded form editor requires JavaScript. Its definition is plain JSON with stable field IDs, labels, help, required flags and explicit option IDs.

" }, "tabs": { "default": "
\n
\n \n \n \n
\n
\n

Window gaps, bar height and the focus follows mouse setting.

\n
\n \n \n
", diff --git a/packages/ui/dist/examples/form-builder.json b/packages/ui/dist/examples/form-builder.json index 03446a8dd..1cee742fa 100644 --- a/packages/ui/dist/examples/form-builder.json +++ b/packages/ui/dist/examples/form-builder.json @@ -1,3 +1,3 @@ { - "default": "

The bounded form editor requires JavaScript. Its definition is plain JSON with stable field IDs, labels, help, required flags and explicit option IDs.

" + "default": "

The bounded form editor requires JavaScript. Its definition is plain JSON with stable field IDs, labels, help, required flags and explicit option IDs.

" } diff --git a/packages/ui/dist/index.js b/packages/ui/dist/index.js index e2a7d53b9..64063409c 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-C6Rhfsz6.js"; +import { t as J3w1FormBuilder } from "./chunks/form-builder-C4avSOze.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 ac123b6ea..e9cfbe5ee 100644 --- a/packages/ui/dist/manifest.json +++ b/packages/ui/dist/manifest.json @@ -516,18 +516,18 @@ "copy": { "directory": "copy/button/", "files": { - "runtime/register/button.js": "sha256-nrgSUK+JnRhipV1b5VKANBtP+ap6ANYd4xnpZYpHYM0=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/button.js": "sha256-uMPPvidQWPs9e0OGW6Q+cI2izylinOUSgrBAM94vxAA=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-79ycU5ojNv1Z2yHzJ6KXDmshFL1we3mQNOoIwfMXnyg=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-kLEcMMhF4Tv+byKkImEgGIqqR+QYh6uOOCz/mg5hkPs=", "index.html": "sha256-uj00vnflsiaqN+2apiLHqJpCJQQxYasFb7KAWllw5dM=", "README.md": "sha256-q0HhyjwcljqPHR5pUVYK1uw9OCz+qKStetrXmYwvBR0=", - "manifest.json": "sha256-c6TgjUcOcYCt67r5dMnrTmZpgv9LuAg3v1JdKvlJv+I=" + "manifest.json": "sha256-9aPod8autncWE6MMIq3cg0M3HLELyCDUbauos9Lmay8=" } } }, @@ -898,18 +898,18 @@ "copy": { "directory": "copy/icon-button/", "files": { - "runtime/register/icon-button.js": "sha256-UWU2VaBVj42dfmtJg9c1yLb2JZ0ObB4FemDN0vyV/uM=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/icon-button.js": "sha256-GQlt7gcCt926nsvoxCtYRyCMMgdI9IZNyV0+40gv/RQ=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-oGnsvpT9vCQjmmGSRaHOeQIJDUE5f5LrSWgR9jdM6/s=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Zd5z+/mavK2J24Rl+RQLGhMT+nTLwoOf3bAJevwrz7s=", "index.html": "sha256-1y5bo9Aq1K+z6CIM0Ef/YeTqqv1dTsU0UQCeeo8cxrs=", "README.md": "sha256-kfL9rqvRiTy+cXrhgmDnHSmrAvPR1uA5rKGMQPP1UIM=", - "manifest.json": "sha256-ySWwdGJTFvqUPfIPiE//EF2SBXqYn8iDa05Ljnz5WmE=" + "manifest.json": "sha256-oKil4+MHybcN978zie4LFpqLGOsbcddS9ILW1oS8BUg=" } } }, @@ -1237,18 +1237,18 @@ "copy": { "directory": "copy/link/", "files": { - "runtime/register/link.js": "sha256-sR0lpvEqWio1+xbGZ5p+TKd03qMnXyE+UkbdxPPGD9k=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/link.js": "sha256-WC8yN3SdZF28B84F96AQc4WHvgrfmotEdEXUDdPx+gI=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-bMMi6OLOyxVGAoiDlHUR/PYvzH66VbZ4i/UAzrXw4yo=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-I9IW2mf0VnX5LtCoHDI29AJHW7PXUxnRReiAbsbd094=", "index.html": "sha256-kh0VS0IbzhJnHVnQwZQ2ZRbX2qADJqm2SjicvR49IB0=", "README.md": "sha256-x8NFY5DSM/rYjOcAeTMFjFuNeI2xoG8yxyGfTnk8/wk=", - "manifest.json": "sha256-9RCBHV2eK/OPYH+iLaWZUBLLRL/3/Db67A/AA/gLtVA=" + "manifest.json": "sha256-3HLwWPQ4f3n5kWRcOa538HFBnmCshfVhVu3YDi6njKI=" } } }, @@ -1577,18 +1577,18 @@ "copy": { "directory": "copy/button-group/", "files": { - "runtime/register/button-group.js": "sha256-iOfzUy8ZfhYmriDjbhxJtVBL2w+EPgppfO8UNoOm6QM=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/button-group.js": "sha256-9kyXdp1HjHBA1/8MAvS/4B8TzQnyUUIVFbxkMteeCH4=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-f5VJ2bwUNXUnsb5AcdxUYbcOC7PeghM/cnXvDSuGuMs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-4NLobHuAfZnWUQDNQ3ENH9ucyjTTUTD6gk0XV7SHGng=", "index.html": "sha256-jp7d1/nw1z4Jpji1Vc8gp8BdBvkGTLC7tdVzkGSKG28=", "README.md": "sha256-lxk9uEo0CDVb02dn3zqLATkEEbC7gk0mkkX9yRpWCC8=", - "manifest.json": "sha256-vwsYAxmno4/3Uq0+30v3izOHgMpzwUEntDgsiFb/uAE=" + "manifest.json": "sha256-jdstAsXBIYH7Fn/eAXxFfPkA1FXs81QYJ3o5InKuAbE=" } } }, @@ -2045,18 +2045,18 @@ "copy": { "directory": "copy/segmented-control/", "files": { - "runtime/register/segmented-control.js": "sha256-Hp1iRTlBtVJffhsTkXPWleCnHa8ag50yeW35VsnXQ4c=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/segmented-control.js": "sha256-xN4DQLVyEFJSMDcuTBBrd//fR3iSCEjqnQHkYV4GtbE=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Dq4r47NU2yi+AVRCcT0g+RV5YoPw7Z3JUhDMJqtUoJM=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-/y5XrVYeuiIc2/pZ/wdJWuadUAGF48in7tED7hWQGYI=", "index.html": "sha256-zUD5N3s3EYsmNmV+t33T6lt+kNsDMoRbcdyTYDikNPI=", "README.md": "sha256-lEaJfO3PJMUKPPqSK45yRRL6euErAHItarIyeoshEI4=", - "manifest.json": "sha256-H33N4ElTkCkBMh2MbBR3SPIPib1+HsrpF2WqEwYwOow=" + "manifest.json": "sha256-mtPWQuT+66s2vpxWJcVaB8keW/TMjasZjnnCJjIMXd4=" } } }, @@ -2436,18 +2436,18 @@ "copy": { "directory": "copy/field/", "files": { - "runtime/register/field.js": "sha256-XVffQJ1x1BaYIujyxerGMhRVXOVJvdiFmAKkTglUyC8=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/field.js": "sha256-pEHbl120kbYNPym5N03ZxIzOQFPHyq+rELTr9RnR2tg=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Rd3CCjOeRNdq9v3ql8A+P+nyw3MOp7Fa0LUD8UqBzFA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-M+Faw3Q4PMYCRgzzkpyGYO6m3Sefbyj3JZ3/wdlvGPU=", "index.html": "sha256-60Xj3vT6YA5V4cnFFqd+JceMzjQ4nZCBnBjOt3OId+A=", "README.md": "sha256-AzjdGpWnzYlGi9+vtMZD2GQ180dH8au7cLFaahlKJZw=", - "manifest.json": "sha256-w3/ZZLfNarfyG9UY8KNfqo/QA/4ufORLVSWeIwS/iYY=" + "manifest.json": "sha256-2KbVkBRdn8QGAt3fcHfn5hSJFIPpIvcothSRK0bQYx4=" } } }, @@ -2989,18 +2989,18 @@ "copy": { "directory": "copy/text-field/", "files": { - "runtime/register/text-field.js": "sha256-DD+ctMlKClOK6B/glshiJwIjKilewzY171GvKtVGf1A=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/text-field.js": "sha256-6f5tLWwF57IFY+uH5zM0afiU3g09PW3M4772zC7zD4Q=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Y3xQDYeeCQmNtobwOfTiTh/OVHOCJt5If76c4411/ns=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-R8UtNVXLOQSMMT+NPAGht8BHx8b1yIjvTii2pQlPs8k=", "index.html": "sha256-J9hbLzXuEnbSdeQVzpl5q51KXvGGqGz+Y21d3vAb3a4=", "README.md": "sha256-U5UskFkuRc314VHTU09nhnEvLqV//5UXlnD2tS0RftI=", - "manifest.json": "sha256-T+FFVaCn+rM3sQkUSAo7Rt0qWttJ1BhryEiHTCNVafE=" + "manifest.json": "sha256-ZFtcAd9B/pkPWzu13gZXvk2xrA55t5jubwRPDjbraks=" } } }, @@ -3499,18 +3499,18 @@ "copy": { "directory": "copy/textarea/", "files": { - "runtime/register/textarea.js": "sha256-H+BMjmdgnMxVEA9KvLSSKoOlHTAH91Qy7+pjUiTlgEE=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/textarea.js": "sha256-qJqDEskuaVeBUFjefVF+KSbJV3s6vpaKCtd4aQ4QtoY=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-BbcGdXHTnD7C55UItp05tibzn6AUyioSMT0hgk45J68=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-FrTRU04fY9wZ6rThXepEiAOHAf/WPEcefiPDsYvSLsM=", "index.html": "sha256-xM2w2jkYyi5BE0Nc6YGqICrh5wAW+DKYGmHHjEB1tOM=", "README.md": "sha256-F6nGVVbKhFVOmZH/GiI2JV5yeoVGMJCFzjcytVdyGrs=", - "manifest.json": "sha256-TWjfrH63Bc/kflpuBQDJbS27RePsfSb9IsUWdkGRiwA=" + "manifest.json": "sha256-MJE8N929g+k7J0CHLayqvw21/OU44JIZ2678hr+A5YQ=" } } }, @@ -4123,18 +4123,18 @@ "copy": { "directory": "copy/select/", "files": { - "runtime/register/select.js": "sha256-zXXuJRnrp9EVnk1A8VpgUzF/JPShcAImY9zRc6nQasQ=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/select.js": "sha256-yyq0jsJOysQGTPpFoA1C1aRWSIukrk+M4Ro2ZwCyWbw=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-F7S6++WxoGrwiPfTq2NRQciL64rhre0zZKEhwee9I1E=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-1rMGJynWvvm/FG3mKaD7Cc+QHA+zhkGFyc7tL4Ul37Q=", "index.html": "sha256-f4rQyCq7pkNwF1oV2xWbeCAut4dwtAt0CPyZLBiz+1Y=", "README.md": "sha256-MrNAdB126mt16m2mdh0VynM3ujESd5+tjBkbyYHVpQw=", - "manifest.json": "sha256-Auv8G7CtLAflBo0zzaMsITFuEZmyeNhvlcRInd1XK04=" + "manifest.json": "sha256-Cc9jhJojKlMJ2nG8AUgH++eJJUFMvpQKfAMi2EHRrx0=" } } }, @@ -4631,18 +4631,18 @@ "copy": { "directory": "copy/checkbox/", "files": { - "runtime/register/checkbox.js": "sha256-Bcfx68O9tVUsOU2UXt39Iw36ZluRIGYHI88jMpSDEjk=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/checkbox.js": "sha256-dKDUoVoQi9btazDX3FlRb0fnVzLkYEN+W08CewNGTnI=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-PpwiBtqgcGIHn1KgKDXvrsX0DeTZ4PfyQsMnUpwCUrI=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-D5pZAWuWF8+C90nVIZnSREv1i0fk6q9L+6SEdvU1Okk=", "index.html": "sha256-zm4zdpqK+QV2pfYf2WrPK1bYk0S65vU+AWWPEq60/mE=", "README.md": "sha256-WEnN989sIQKKMpAjmYvjRbS2hGIBqYi+IEj9c/xhVFs=", - "manifest.json": "sha256-kFFpTffP1dDIr9wzNmLVN7foHnf/nRwRbekip3C4oYY=" + "manifest.json": "sha256-objP3WhT1Jq2OhCFDVjtysUtDf8cG7rSSGnEFk6oHkA=" } } }, @@ -5044,18 +5044,18 @@ "copy": { "directory": "copy/radio-group/", "files": { - "runtime/register/radio-group.js": "sha256-L7TPdkL+uckYkNZ8nwZWjfTisSvOmPO7rqB3QlmfaTI=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/radio-group.js": "sha256-UtfAZUI/Cr3R29YvS/0As27FUks0dSZ5e2Jcx6yDfxk=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Ig6nuF1jMxOL71ppi7cvN8DjEKs9unk/ugZ0b1XTImY=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-6HA7gvr2JUQeKZ5jWPcVyfSw5t4FmaqlAA/+mhuSJjc=", "index.html": "sha256-4ptm1dy28zuJlLU04Zd8QtEveiw6njq8DNNQd89W/1w=", "README.md": "sha256-L+Z3W5VfP83lnvB20pwCI2E1gQ/vKF4Yvd/mDw4diyE=", - "manifest.json": "sha256-UpYcgVSqDnhnjaAHOl5w3cY9WJP0x1sLlAONVAGlg78=" + "manifest.json": "sha256-zUkTL5FcsZlvLHOTIx4RNU5lTVvTPGr/1IQX35UzkKk=" } } }, @@ -5456,18 +5456,18 @@ "copy": { "directory": "copy/switch/", "files": { - "runtime/register/switch.js": "sha256-WA0Avt/JJmz7DqxDx8v5Rnw3WCZFaVGJjPdibTQKkSc=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/switch.js": "sha256-Cad08u/MHjqLKKV0MpUQNKaHz1fLJnvy5dfayoqsjvI=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-wQ5f/FFGWolJtnjyPar452XqRgkIhBLJEQbc8ziQvag=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-bja8BqOYebPhAJ/84m7EUQysf7pqQJ3wMJ10wj4YBz4=", "index.html": "sha256-UZvqjISxPBGEl7MJkilEMem3b7sjRYRpBJpzJneqq/Q=", "README.md": "sha256-9Yw9PXXsjkMqCnWGR6UbhauQtlI0q6dR39YdGBbG71A=", - "manifest.json": "sha256-YSfVQXXYORkF8TYDuvw8UDQFQ0C2BvhbCcgmyhHx5aE=" + "manifest.json": "sha256-9xj2uziqsoVvDxHlrWeYtax1DhDv15vtgrzyE6M7E80=" } } }, @@ -6029,18 +6029,18 @@ "copy": { "directory": "copy/range/", "files": { - "runtime/register/range.js": "sha256-g8jU/JKj2ySLza7/G+XS4TC2NE8Gwuw6lyc+G1k9pi4=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/range.js": "sha256-uAqR2sA5IXjunYSDuvl+0MoUbuwonAPLwhQFCExPI/I=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-XwLMipanpFGzjbmGs1VEzJL/+7DPUuYTewuadW6x3zE=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-F3TYZf5Pysp2EfVbSAxBHmgiviXyRS3/dKjUdvZrzF0=", "index.html": "sha256-xuKPgkTCOPNTZ8muQffKPJpVLWZpA03yfkf+90bVZmw=", "README.md": "sha256-lW1eqkbbrr3cTilmwEqgWHViJTPEMEDqDOHhsAizE1I=", - "manifest.json": "sha256-9Fj1tjDQyex5Ybg8lOvcWuVuHic/EnjnNXfR/YPoO7c=" + "manifest.json": "sha256-2zOSEiGiOqY7xfv7/vuey0GKbJG9CJIjDHjsLU36960=" } } }, @@ -6412,18 +6412,18 @@ "copy": { "directory": "copy/fieldset/", "files": { - "runtime/register/fieldset.js": "sha256-95mq6oG6gTLPWs+kdvdNqiuSftofqYoBvCulLuTebyE=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/fieldset.js": "sha256-pAzVFWN+M793N7lFAZ2zTybWJLdSOqZl3AmOTomqmTk=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-TPi15SfEwAaSl4PqQvGAd3bFbbB4BJ2trfD5k2+8yrc=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Z916I2upHIzzffRAz/6w6FSTBwegAd+L49E9Juck2fo=", "index.html": "sha256-/G/GqORWDhO+K+ngVGX8Mrb/mp0XHqSZ3PP1WwffRXQ=", "README.md": "sha256-dNh39iesY0kLTE75KP+a0WhhHDQpT+j04MoZgMmV4F8=", - "manifest.json": "sha256-uljFodRq8xH/+kpic5mcTdwYRi6D8uRATY8/65tRHSA=" + "manifest.json": "sha256-Icof6ix6nIGawAfa4gGLYuk+5HuPjVTjIy7CMKv3Gus=" } } }, @@ -7037,18 +7037,18 @@ "copy": { "directory": "copy/number-field/", "files": { - "runtime/register/number-field.js": "sha256-jCevLNvnx84VrjcqcaLN+LoayqMvlOZqbeB0vfcKCTw=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/number-field.js": "sha256-27HebtimgA50TSf1kwNGySNCBamP+Cu+9VCSbvOxcDg=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-agyrkFz7FiKZpcU4J9QsaeTNRYBw7yWJQcMOdSd8SPc=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-wabUKPjMJ+zn/+oKJMogtcDlppICQ8zTGXEbhGwm+iQ=", "index.html": "sha256-yH23EzsY61NhYO5ZTaRXcpIb2OUYezkZl+VlqSSVS/M=", "README.md": "sha256-ZNn4SinUkL66soe9hksIPf65yrk5SCJshryFP1N2GnI=", - "manifest.json": "sha256-p6h3APhk2/kyaXbWKAEHdHQKn9zMYnarGK9hRLu/MKg=" + "manifest.json": "sha256-hCbMC7IlXDmxCwg/QFY9q54+XiopRwcxLcGXi5qcsB0=" } } }, @@ -7538,18 +7538,18 @@ "copy": { "directory": "copy/search-field/", "files": { - "runtime/register/search-field.js": "sha256-Z6IeX4+LKGVQJUcQGuyUnCBL6ggQSoevMhrj75zYisw=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/search-field.js": "sha256-2ODKfrgzC53SjMT+P7oaRa78AgRY37MG12M7HVRwfQU=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-LKiZdfWdQXHUoEdFnG1o5Aka8mOS8NP98IdndPFnsbQ=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-HUFhtyi3m/bOmHYH5vU0uD/8e/TFVZ6EmUZzoucKCCM=", "index.html": "sha256-pNWMnOcTZTr/TNcGVa53Ac8S3/6iWYnBj5B5CjnTcVI=", "README.md": "sha256-aDgof37yYQAYKjMAPaaPxNDPtVVxOfCjHh2aT60B4xo=", - "manifest.json": "sha256-pnh7Ao4SBHM7H6SMJlWsYLXgxVp7AdEhbo+/35vi72k=" + "manifest.json": "sha256-X2C6mB7tjK5+K1tt523eqZrLi+n8t21TOjfncY+ulSY=" } } }, @@ -8103,18 +8103,18 @@ "copy": { "directory": "copy/combobox/", "files": { - "runtime/register/combobox.js": "sha256-wSm80gvqOsgkhwOnsCIjr2a4w8W7WCRQqBXn2frDhak=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/combobox.js": "sha256-5b1Sa2zwhRyysK9sVyLiBCGsYfJyYnfGDsb6r3sA9MA=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-f4pI9RLIKYsRggzuVcLA2zYdXHZXY3+DbGFjvBCtbSg=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-/SDEtn3D/9kfnULtpHPFEgK1FAkmwe+77gdxlWNewhY=", "index.html": "sha256-TgE5FDYDcg51ETqt8UekGbIULwjwCa+CjxGdU63wd/k=", "README.md": "sha256-d6hom7buY1pZpNug4Bx9SqSXvSLDY+cq2xwlZ2Fei/U=", - "manifest.json": "sha256-rdA+FV9dwxEdykFLa7tzZnjl+60iBGTXLBwm5cfXOnE=" + "manifest.json": "sha256-LC5lxRaEjCGeCQs8KzUb7Kib9EekddKOWGaaXDBODQs=" } } }, @@ -8610,11 +8610,11 @@ "copy": { "directory": "copy/multiselect/", "files": { - "runtime/register/multiselect.js": "sha256-96pmTEj2wLhjjLNib4gB1d7Twzrt5QcyklLK7RfzavA=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/multiselect.js": "sha256-8L2lHVliSgOdCXDMUzLPyUu9JYyowyYfha4hm57F5/E=", - "runtime/chunks/advanced-DCpe8Ndv.js": "sha256-nr1LFdLYsGeTM4vDyldvuJygRm0F04sYonxatySPu1g=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-NHeO9yzX+pKu8X05cxcbMC+aba6f5KV7SQL1E+N/kKM=", @@ -8622,7 +8622,7 @@ "element.html": "sha256-1E4hftJizWZX+Gn6uhOJBXC2VAC62t50q2kwRpgS2pQ=", "index.html": "sha256-/iSVBFFALSTS0ebIls1qu3/g280a8lbMULm2Al9zFMM=", "README.md": "sha256-754Tt+bveWNGF8niAMoHQEB7D8SGYGEJhu6GpbhKpiU=", - "manifest.json": "sha256-vXlR0srvz+KDPAaPbWuMQCTQmQGqocNNjF2ccKGVUeA=" + "manifest.json": "sha256-nKMzjOfdVCU41TBMPw0LQ1xs2gpD6VKkxbgNrjoXu74=" } } }, @@ -9211,18 +9211,18 @@ "copy": { "directory": "copy/date-picker/", "files": { - "runtime/register/date-picker.js": "sha256-QyyWDOnYnSGxEdY+mxrtYtsLqoQAkhvTLJ5z7kjo3/w=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/date-picker.js": "sha256-rglCYTqoXYDZ63YUb01UqeMk0HRjOeYkVcqadAX0qmM=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-InOm4+AU0uQu6XZs3K+f13FA89Jf7iQO1GuL/2+s9YA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Nho5WRdNWOIx9zrVkZR8s5NrC95hgRBVnvDTdnZ7qoo=", "index.html": "sha256-eGq952lAjjjM/6cG7o5Rv4hcM4Tuc6zA38HiAPrEevM=", "README.md": "sha256-7Nf1YMBxm1cGzO+rzOKvfqWgRfugAjR+6/WjnVo2qpc=", - "manifest.json": "sha256-48K6bsVp7ch78EFmIyDgXpAaLzUWaLgA1nfjOo2NwZo=" + "manifest.json": "sha256-HTadscpISlfLGMTeD2aqKFA3XTQ0944fT4Nta8m/a5Q=" } } }, @@ -9795,18 +9795,18 @@ "copy": { "directory": "copy/time-picker/", "files": { - "runtime/register/time-picker.js": "sha256-2BVpwqf8Gmd8NnGgY7TdxAtrN4oIOg8cMn0kMOqj9Y4=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/time-picker.js": "sha256-K1tUYKUlk8oOLnC7XwOpKWl/CUzqs0NmsRJ38SjjI1U=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-J5VoJUQp+zDREm8yqwh0jq7TRzMH+H8XMK+3CWxjgIU=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-RLfLhDEtkzyeISgOb1Njmp8QsxMKjIUzebwrMAg9GNk=", "index.html": "sha256-0uRkUg8W3uzjOeM45/CL0JXuey7R36hf4eL2pcTXKZY=", "README.md": "sha256-bK7PieiUKZ/3zwSldV/HlWMak7kwtWyvgpYy1YfAmbM=", - "manifest.json": "sha256-6dQepccMEMurDmXDGAXKgSfV2lWmb9ekpIZ/3hodceI=" + "manifest.json": "sha256-TsyWY0+4rJxb2osbgC2wSnuTVY1vEQYHcpQelUBOPuc=" } } }, @@ -10334,18 +10334,18 @@ "copy": { "directory": "copy/file-input/", "files": { - "runtime/register/file-input.js": "sha256-JVcVdlTDOCB4bLa+Gc4LHWSfojAaR3wRwOBxMeLa8z4=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/file-input.js": "sha256-b5A8PD7vS8/xWNzSdVbtt2pV33CllxtkKwdSPtC1CSI=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-ezg9wydBGR6KpQziZgvoKiTXURNTPkh+aD9h3vFuuW4=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-3MysNuXXyX6HzlWv0wFhnto4CU9Q/n0JHK2wx1ufwbE=", "index.html": "sha256-fBkoQQjmYl2pS2ZhIJZ6zX3QXl6l6HTDfKsrsy4jmb8=", "README.md": "sha256-fT5UasqXVH/Um8vNgVGEXNG0Pk7WZ4Aq+K44FBlAdpk=", - "manifest.json": "sha256-PCFjtc+DwT+gaXF4ED4ra/J3ypLKXVDF9kT/4IXn4No=" + "manifest.json": "sha256-bH56aJVEFuoALa30Gr50CeAhnI4prQtCX+Tlg7ISm6g=" } } }, @@ -10712,11 +10712,11 @@ "copy": { "directory": "copy/repeater/", "files": { - "runtime/register/repeater.js": "sha256-CL1MU0vVSqQyPhS6UQWzKLVZqxO0fbuljqqDRE9GvUA=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/repeater.js": "sha256-pe+MgGoQpseF+J8HpfkS5wU84MsVLuCJl6BAzoyS+lU=", - "runtime/chunks/advanced-DCpe8Ndv.js": "sha256-nr1LFdLYsGeTM4vDyldvuJygRm0F04sYonxatySPu1g=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-IEhREL5vlXFRdDmE8HHaqwhAbMJ8feOqTJ5MMrQGztk=", @@ -10724,7 +10724,7 @@ "element.html": "sha256-DSCQzrRbDwFOKtw5YmpR+3oYWMIBJFIPnJpes5bSMPY=", "index.html": "sha256-c0jxp+wZ+Fh6pdflIdXG673av6oOTGx7HobpD63O2Sk=", "README.md": "sha256-iFFjPHWI+gh/aJ7+flDL4I/Qaclwv1yCfGRuJ06o6tE=", - "manifest.json": "sha256-Ek/0mqQpQIztzCidbtl1wboLnvHJjvWQ7BM/s4lZ5FM=" + "manifest.json": "sha256-JQ4FuJwvAez8YhIdTjgxq2ItTIEaKdSzvz38cbU6ChU=" } } }, @@ -11361,18 +11361,18 @@ "copy": { "directory": "copy/wizard/", "files": { - "runtime/register/wizard.js": "sha256-8JwKlLD2lG42fsQh0+nf+OZ0pvg6Vy7Uexn7bdkWEe0=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/wizard.js": "sha256-WMaA9QqPtqe0dUBowMDw++tHyL+HZFO8+VoCJpn+HXM=", - "runtime/chunks/forms-BT3z7lNC.js": "sha256-Txmae07dWLj1H/FL869U0Kv84TQxzpdFeOg0g8zGK6I=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-TIsUn3die+vDqK/B4+HqIiSctLsbfAW5EflsX5y1oJA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-T5EJ8DcqnD1rFEoCwvdUpmBCh0hH9dJSmq5oOkC+mi4=", "index.html": "sha256-x7w0JHEaRfh3sRM0TmJcKmqI73CDTfRHzbgURIS3m80=", "README.md": "sha256-B9klMh35GlqO5l2mxI77I6x2Gwfl8AMNSH6P+up7GdY=", - "manifest.json": "sha256-m2daflOEDFk6WotvcUWzd9v4LCJpXkBoOyA2h+etXNI=" + "manifest.json": "sha256-UhjeLs5rph69L+MfnhqE+VaHTj1lp+R96NBkf02w9pY=" } } }, @@ -12256,20 +12256,20 @@ "copy": { "directory": "copy/form-builder/", "files": { - "runtime/register/form-builder.js": "sha256-eM9TDYrxREfT+vaywPQ8TCrx3X7gAB/fXuj8viaqKzM=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/chunks/form-builder-C6Rhfsz6.js": "sha256-CnwUvLr0BCPWw5F9dlDy1D8Y73slv5huNge/LK40+x8=", + "runtime/register/form-builder.js": "sha256-zzx2G0Mpnm0otVuQM9ahEKFTZLWONt8fx+50KatSAUM=", + "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", + "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", + "runtime/chunks/form-builder-C4avSOze.js": "sha256-+kWLP9s28Z+VcI6eg34y4KyqRM6Lm0nnbOsEL2rJv2Q=", "runtime/chunks/form-builder-C5Kx5G9b.js": "sha256-H2Zi4dAojDJ5ZF7OQWEPsPaCg3kMBiAVVG1k948Yiuw=", "runtime/chunks/form-workflow-DMGni-Gs.js": "sha256-g3g/Afxx3XsClDK4ZfvWQjZKprT6z7Qp1lULS48F0rY=", "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-dgVsrgYuHrvBt6OjTg069abl7yU4iwgXOXUw3n9cB7g=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", - "element.html": "sha256-vq61pWv0xeMFu0tTsDtRWWpAr16AFefjpz5JTSyF440=", - "index.html": "sha256-v74xLbiCzhGoMsKDM8vIO3nwDmWQJymihSOqXqvPlkk=", + "element.html": "sha256-WUjDiy4tZKp/CS/g5I/hIUQY0Mci0zrItPW5k4K7As4=", + "index.html": "sha256-hrjnyBZnoPU8kGIL7jUSLs5EvKHQLCDcBPE6LJPQKfo=", "README.md": "sha256-MGlPh4CEW6DLecBSj7Ym9ww3NAGe8r5V9uANRpZLY48=", - "manifest.json": "sha256-/AJpK7InIcUrx5C6r4HWc3McmNfuSvcN0bFFLRwFx7s=" + "manifest.json": "sha256-FLvmL17oFKsay5ANEQsyqUMotNS7tqHqJqbAXCGyPhw=" } } }, @@ -12673,18 +12673,18 @@ "copy": { "directory": "copy/tabs/", "files": { - "runtime/register/tabs.js": "sha256-ZNIa4RlyyzL89jDO8N637zceDABaxE+yPzulw77+N9c=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/tabs.js": "sha256-42FcvN/By1ouS+HE0CiZ9FaasHLpN8HY7TiypjcFkdQ=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-zVXkxQteKGqZmvOgx444SE+3ubxZ6YdRaGci9hT3GeU=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-xe4UR+a4C9oNodr9UlW5OGE5DR5R9JErwW0UAalo8oE=", "index.html": "sha256-w1fTqm25U4WCS0w6RvFvuUPfonjfue1T0ZJN83ccPr0=", "README.md": "sha256-uBwdwc6EkHrqha/dCs9PWntoU1l7EAJb7Y6nx+zzrqI=", - "manifest.json": "sha256-PM9hfuUIQtvrIekuc8ckBWWQXjPFXTSvcBTd9ovfoQY=" + "manifest.json": "sha256-GdzO1hAPIfEsd0BOsp3t5RLbqZfJkGnn1ZCXXToYFZU=" } } }, @@ -13030,18 +13030,18 @@ "copy": { "directory": "copy/breadcrumbs/", "files": { - "runtime/register/breadcrumbs.js": "sha256-Q0duBAI2kOEbn33M/8S8M3ciNcrLKYFaLDl2PvMF4MY=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/breadcrumbs.js": "sha256-GtJDiM9iN77t0CIkD7Feiu8A1MQ5DeirIUfSVxO6o7Q=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-pJjvksTD6NTZ2QRx/SBxS4j7xy1rVLprovo5OnTOafs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-W9qk0XtcetNK1me7748lByEMSMUZyP6NT//vet/Kt0I=", "index.html": "sha256-OWJN8qhGZ4YIN1OKUp03drZk8CY4D66GaO0t6LtKvJs=", "README.md": "sha256-KtiYxcVwfGDIDiTnYI/c2MhmVKez7eLztyU55QJQXgs=", - "manifest.json": "sha256-EalDQFcoOagLdF+WFVS1L0RqDU9zG7P6zi6BdvHcFFM=" + "manifest.json": "sha256-sxScJ5LWeXb+RcxzzKt3BInF6XNPWZanItclgpTAtnQ=" } } }, @@ -13425,18 +13425,18 @@ "copy": { "directory": "copy/pagination/", "files": { - "runtime/register/pagination.js": "sha256-pgp0U5vF4tER52b++qgmdpAuRSmpiybgRt6HfLmtBqU=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/pagination.js": "sha256-yrEJa21eYjbFYfF3K/IdLp2FXFcKGFkLEVD4bxibWrE=", - "runtime/chunks/tables-B25ydUHs.js": "sha256-XqRdyfrSS93rVybWHq6a0WhrmZgaboHi5n8ymgwRbM8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-J6AIVbVHNyS581oA3enNH84ZCf3yRHxSsjlqUa9Z6d0=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-jp4BjPewAxszUnraKXf7iG6Zty7ZB7J8SdFyHQg7hL4=", "index.html": "sha256-/fV58cVZi1JLHRPrv8jsrMD51D/264mvCsNHTj4WEYM=", "README.md": "sha256-CkmYa5gHgFCQLGpkV2WpwdaxjhezkCTRRw8d9KDRUqg=", - "manifest.json": "sha256-VnFhaAlOvHjn6UY3qGk2yBXuPfa3PI1CYjoFCi9AAJo=" + "manifest.json": "sha256-nx5efHd3Yq/LgORnwJ2ml5WZ9s91EpMEcsuClG7EU4U=" } } }, @@ -13868,18 +13868,18 @@ "copy": { "directory": "copy/sidebar-nav/", "files": { - "runtime/register/sidebar-nav.js": "sha256-X/t0V38SB2UnmTa0KqYTvD4OKdvRFtsN75azWmcPa90=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/sidebar-nav.js": "sha256-LfEAicAsreVm6Jp/H/ocft61HelJ6RZo1rIPWFWRCCU=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-daIsd5K5mOs8Mmspd3m8ktJKgxTzPCRGoQY/6MQCDww=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-LBoiPSLgtVIozM1wEFWbV78DaFWbIW+6OgOjaCSim8g=", "index.html": "sha256-iigY56T4Y5udSqoBZloU6658GNUHY+ynrBQSOg/+UIc=", "README.md": "sha256-QjtvSq2sHwF8bsMsDu3BpvOyATxZ0oanPWICItjaETU=", - "manifest.json": "sha256-vJwnwnVoCLZuwhSZpsPKP7dmOI/CkQQTmVryV7sm25s=" + "manifest.json": "sha256-XWT+KUPg4g4OKKRN7TMBUwPrk7ejk8fiyzBpuM5WPPQ=" } } }, @@ -14418,20 +14418,20 @@ "copy": { "directory": "copy/toolbar/", "files": { - "runtime/register/toolbar.js": "sha256-OSMJIpjPl64KP4YMacdMSLwBugQjcBJHhX/8qyJT0aM=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/toolbar.js": "sha256-xBBCFoguW9JGO+jaNyPrdGYVP2YwJ4BhX3FWPRxoqfs=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "runtime/register/menu.js": "sha256-YX+9ydadaIbkPIBFhLWX4Jv3V9vIl4UY1qolxLGfZUg=", - "runtime/components/menu.js": "sha256-AMtJth+M+4jqb8imqdn9VcM3aKvtgCWkPySfsI7htH8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-uTfyFdWFrx91RdklrAzqAHNf5B2q1psaqjlF71eT+Xc=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-MRU95stqvOm7gd3wzi8XadrYOLU9MRKqdwFO/bmSaPY=", "index.html": "sha256-qzep40OKd67lZTxeQflCRA+sfx2A6/zxVgtV4re8LgY=", "README.md": "sha256-jPzt7MdgG4yEEJJ6qWZk3Cgw9KNNNHEKkwz/nnKK3co=", - "manifest.json": "sha256-8hlyqGGelr15H1t7evcG0FBb95rGUZnTNnn/7YboC68=" + "manifest.json": "sha256-zrNVk9H7z4L1LcjXysnS9k61jvrlzeBWR1qX2vhQ10E=" } } }, @@ -14971,18 +14971,18 @@ "copy": { "directory": "copy/menu/", "files": { - "runtime/register/menu.js": "sha256-YX+9ydadaIbkPIBFhLWX4Jv3V9vIl4UY1qolxLGfZUg=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/menu.js": "sha256-AMtJth+M+4jqb8imqdn9VcM3aKvtgCWkPySfsI7htH8=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-SIubQgNKqhuy1abCUQB+rvpnPXZTQ9fiW5Yb6XWT5MQ=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-0SXVO1pxUxzA5mgZzG5YXw21f3G/n81DtP3vy14Nv5M=", "index.html": "sha256-nwGZ4fZm7plv8ayxNa3zbvZ6jTO5Efxv0EvQBeohNN8=", "README.md": "sha256-ICc5PzI3f6/Kpyf9KXWame8aNgGPR8JKtgBhHc9HrsE=", - "manifest.json": "sha256-Ud+V3UiG+NGVSscSNIvn3E4AuJOFFvDO/8r2oe1R9sw=" + "manifest.json": "sha256-MVQ5cZlXdmFAA34VqlXLFuybCnCpay7xluf8sdFC9Rc=" } } }, @@ -15395,11 +15395,11 @@ "copy": { "directory": "copy/command-palette/", "files": { - "runtime/register/command-palette.js": "sha256-lGGoaVMCbjDzpQkjNlUs9K1jnmKtBfQi/K3dG35cCd0=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/command-palette.js": "sha256-KMSKyY2a0yyVe6zxGdWjBFFsgbL/DjNUvU8lnxB6USQ=", - "runtime/chunks/advanced-DCpe8Ndv.js": "sha256-nr1LFdLYsGeTM4vDyldvuJygRm0F04sYonxatySPu1g=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-sXrks2txpylBLDX4L9vKPIvAj11p73qrX0apfh7EgTg=", @@ -15407,7 +15407,7 @@ "element.html": "sha256-mNRkLE+yYA4PARM4rv5bXDj90Oq8yxQLPgoUW8bX6ns=", "index.html": "sha256-I5o97Y3ykrn6MCqMmtWvFGTxDBltracgMFnF25iNwZk=", "README.md": "sha256-KLn7bklioLvnV4bRDAgf3A5aqqCSezXa9kKARSYCUcw=", - "manifest.json": "sha256-RxOWXeniso+hvwGsCJGdxMEfsQnCjBbPcgMkNi70XEY=" + "manifest.json": "sha256-uA8GN+OL2y7mOBmNlsfhjC5/h7doA6mKnA5NaP2Y4XU=" } } }, @@ -15752,11 +15752,11 @@ "copy": { "directory": "copy/tree/", "files": { - "runtime/register/tree.js": "sha256-xY8jWYnbMM8UlE/rdQJsu3/URGPvdUC06U1QmKsmFZQ=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/tree.js": "sha256-1wgpPM9BoC1/T0Or37ZhoekuO2YZ3luXp+DpWKVKBcU=", - "runtime/chunks/advanced-DCpe8Ndv.js": "sha256-nr1LFdLYsGeTM4vDyldvuJygRm0F04sYonxatySPu1g=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-CMMLz+0autEo86UbTxzkyHVpMoNtyKskesgbIua+YiQ=", @@ -15764,7 +15764,7 @@ "element.html": "sha256-F1zSdM5xw3/jlndjR4iQRRyZ7K9gfkgofh1Oin9xUAo=", "index.html": "sha256-+NV68HiyyQfXclh/Z5F0O/9UwWGzR6RouwMjxM/4DZI=", "README.md": "sha256-rkAg9VO8TxgNCrXXP8dhUJ24Zori5pT/6k3w7gj4ixA=", - "manifest.json": "sha256-b/wUhzdct+NttP79qt24e+b3XsS9ej8bN1kxxKgJ7m8=" + "manifest.json": "sha256-t6nwj1LYRLPcxFNduvbbCOjxgKAl4ixOUmYtB+vqH9A=" } } }, @@ -16105,18 +16105,18 @@ "copy": { "directory": "copy/disclosure/", "files": { - "runtime/register/disclosure.js": "sha256-QAWXKSki5SRPPTshefR54Zy2gycHjHlG61aTWPL1Q4g=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/disclosure.js": "sha256-T++duSnTm8ippxMGxtM25ykxUO+HYIt0HK55RkVOrHQ=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-vVNjPU0AXLKLnxgRPgOVmN3dS6S3pxA6xLFfJFK8ex4=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-ZbpW/j8ZGKofIgL/uVEO47xXhxXmS2mrK5w32n/BWZA=", "index.html": "sha256-IGRscuNxsfbVQd8cDkiBz1/QAEamMHSToesnIwq38AU=", "README.md": "sha256-eHT7DdGUFZxUFoiTNsB5j6dKCRG6kf9fT0gY1oSBy/8=", - "manifest.json": "sha256-srtw0ECNjqeIbiyT88LWtptOK+3TJpxgjEzBwafyhBE=" + "manifest.json": "sha256-IhTnTf9y8wxbgmzrMuAtQT43sT0qEhunebh3YsPvSnk=" } } }, @@ -16411,18 +16411,18 @@ "copy": { "directory": "copy/skip-link/", "files": { - "runtime/register/skip-link.js": "sha256-J3W8TBKgxKkjPInemg2o0yMPFluGS5Q/lPN9NQYBXAo=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/skip-link.js": "sha256-PjQqYJSg0aTsGAbfb9qa+aisYGXDJgGgWN+ZwS/vgFQ=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-KCkIExZyQJQhySZCEQIOrm9lPtDzOq95R9+IED0MI8A=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-TllH5VfEO0Xn2+KsNK2k/W4RJWPv9CVLWE38btvoOpw=", "index.html": "sha256-/HDnZh+ZTER/j0o82CsKR1s11+5KNWqzGpG3Q+RrG1Q=", "README.md": "sha256-YX3Ch7JuUJRqIpsiYPlIc/09irmjC9OLqMTSPNUidYM=", - "manifest.json": "sha256-/jHANaZlfExigzc9YSvrmpKwOgJsNkh3BLB4kOMIj5c=" + "manifest.json": "sha256-qToWGFnF2ZHAppCVsK6F37uSNCkaiJa0o9dRC980408=" } } }, @@ -16790,18 +16790,18 @@ "copy": { "directory": "copy/card/", "files": { - "runtime/register/card.js": "sha256-zbAWuZuKNPZkVbl9pW5S2Mzg9/mlHJ7BeQEgQAUhrlA=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/card.js": "sha256-REUcny20Az6YiLn0F6l0ZkmNrj18xAqRj9bWUmvkhLo=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-pfXQBPkrp6iF0OlQiLQh9DMUwtsCinOaL1HLAjlChII=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Rc0IwITP8X0cKscYMBt4LgzFbntPHkCAdDQ4xLh2LXs=", "index.html": "sha256-IvoBispcGfdc1cclMkSpIk4mImhXxUS8/bDAr0dLmcU=", "README.md": "sha256-7NvZudM1FuKwW/ZySKs98FmFwxwir6nLM/lGAvvcI+4=", - "manifest.json": "sha256-i+pJofI3U2yKMpy/iUtg9GQYpMJuhdXqk8eQsj/fFsk=" + "manifest.json": "sha256-surQ2SRSiqDj/nzNCiD1yEFyfhPCm61p0Yjf7gl8rnE=" } } }, @@ -17214,18 +17214,18 @@ "copy": { "directory": "copy/list/", "files": { - "runtime/register/list.js": "sha256-wbjYHGmbf46FoJiajI+Z127P5eUpLr9c6BSonN2FqnQ=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/list.js": "sha256-EfhH50w/Jxw1dj4a/Ul3Xi6WmUlbeRhgpAeATkhO8EU=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-MSEasr2r2kyu8iJSxcX+m4nWTD2FHPKwBU7K8T/9844=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-tiKX+fFUPCsBJEryliaQ7y9RhU4zlh8aEqMJ0aSO8Lk=", "index.html": "sha256-sY1ilmVvk6pArKOSGuz/1p4PN883f3mu5PXF1sOLwX4=", "README.md": "sha256-lw1NGV62/UGys6imJuVkK5qPyHaJqiOgSEuHCgehwNc=", - "manifest.json": "sha256-SbBbbXQ5+Bc1H2Pt8GwTLH1s6pniel+amh1L4cKgwss=" + "manifest.json": "sha256-bhWcTAujbBE3PS/Y2T+CsTQki57VdAggFJLePzTl+xw=" } } }, @@ -17512,18 +17512,18 @@ "copy": { "directory": "copy/description-list/", "files": { - "runtime/register/description-list.js": "sha256-yhsiXjAR6wy2d0ePQtFlXsvPwWsBDWwuJiOZu/UqR1g=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/description-list.js": "sha256-qKd9CujEm+EgRSZfWHW9YXH9JY/d5wMBkkfqqP3z5so=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-MvWyrX2+45DLgWL1ZxTdk0IFVjl5WyfGYZdOYpIeoak=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-h2HPGz9Kz0LvMiuTC767wAQvYHOVVmffDECwh46tG0c=", "index.html": "sha256-mGxvifjxa5eFOtCBUQR3P/9IKtYsKd4nsTfWb9+u9w0=", "README.md": "sha256-RrAu5lsq7QsSDTX+KygEzIsHJphBaeLyKmqBc+xa5G0=", - "manifest.json": "sha256-X4Ucl253TcuE6dHaVe7snooGjXH6qNADSDI8KIVB11A=" + "manifest.json": "sha256-t+51h630XT9WJSqr9Ew+KF7288yZS+EGHbNlUvzKauc=" } } }, @@ -17981,18 +17981,18 @@ "copy": { "directory": "copy/badge/", "files": { - "runtime/register/badge.js": "sha256-v2MgL8efVFZ4zJl9rvTmIYZxswZz69oeyrHTaYTAojs=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/badge.js": "sha256-l72iC8CAJp/xCXpSX/oJ3xsz8VT4N6UAcVhVSKeC/zs=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-K2TPkFZfKUt35HniL/ub9icdMukZ7wCx0S5+D1FOv8Y=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-rXaOLdDbEK5SMtYsw5TegOMtcnLijmgtU07RVrvJx8o=", "index.html": "sha256-adxgp7aQqS8TWwQ8h7ZunxvDdJpxjaS8oGagTh0d+s0=", "README.md": "sha256-5TsNDY9d5k6gLYa4KQycTh+1uwvXsoF0XilR9xhKVVw=", - "manifest.json": "sha256-dYqinOxtXZZbvC2MgSv3k1KR+2WgDw7MIWYvM1syecw=" + "manifest.json": "sha256-2ZbcqLs0w7N2cnu6znQmM45vwV2jYqlVYeROhMVGDXY=" } } }, @@ -18384,18 +18384,18 @@ "copy": { "directory": "copy/chip/", "files": { - "runtime/register/chip.js": "sha256-nhg2cNNdf2EtWAVdLGFMWDTHx5f02Oe0Zf06cTV+sY8=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/chip.js": "sha256-u34FDCir8vK2ro61A5etBvzomb22WIhnIx7vL6Xcf3k=", - "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", + "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-zqlDj7D8NyN4xQ/pnlXuOTnA8NlRXPBwW6qG+JcjoDY=", + "runtime/chunks/overlays-Bw8SSDKz.js": "sha256-YrX9CL2A48QwI7COQQ5anYJLPOxpKrIeyz+jtfp+T+I=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-nKS3XC8eLjQCMMZHRRKSiHiaNGZgYD6CXzVULJoDU3g=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-yjXdYrZ4DqpcZ/ZDGxD0cgfYY/xqj0qeSkX1dJmVhfY=", "index.html": "sha256-w6jTubEaofdbvKO8llTmtTpw3a/ixglUtu1tDybz2iY=", "README.md": "sha256-Ay+51qOAHcbN22QHsMfcbrA/66D52crp5OlQCHyMYmg=", - "manifest.json": "sha256-yT0JmPG1bG7dWQAeyCEaG9vmhKJg43cR+dngTQc3ToY=" + "manifest.json": "sha256-QGjrjIpek7P7Yi72gBE9aw5WBUsqe4QAZRMfkbJ6DVo=" } } }, @@ -18675,18 +18675,18 @@ "copy": { "directory": "copy/avatar/", "files": { - "runtime/register/avatar.js": "sha256-5DYNLWi7ycaPY4mr7DXYNOCVEbo97Pnr3INC7MFexbM=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/avatar.js": "sha256-ewC6RhKRQwH+7jEF62lU5q8KPwKXfyEg/JWISD2N/FE=", - "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-XYCR7yVoWMnpJrQG4A+pL3xESyHR6OKMuwJfZGgDpKA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-R1Q+6UFu76jOlVP9cadBrMxVS3+Yb2JgIDkcnKxWvtk=", "index.html": "sha256-6wIoUvdBP1c8DCQbO8yN3AbgSvI4jPyNvKs6IYYA/7o=", "README.md": "sha256-u+Rv0zskk5yOTH1pAzZ2eB3pId21guCqbzSFwIC5pcw=", - "manifest.json": "sha256-c6GiHt1iB6I4HICzh/PnoN9D4wm4omp6h7bp2vBfftg=" + "manifest.json": "sha256-d3157WFbkfMSnAyhscjitsbHKfZ5RIkgA5UPkxlBRyw=" } } }, @@ -19121,18 +19121,18 @@ "copy": { "directory": "copy/table/", "files": { - "runtime/register/table.js": "sha256-MdQKdnzPN7NGGdLpVWq6qbgJvHQFdZaIpYLaOLJxRfo=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/table.js": "sha256-leonu0udFEH8CaIXE0yhLXubdVcLX8V/g+fDayFea7E=", - "runtime/chunks/tables-B25ydUHs.js": "sha256-XqRdyfrSS93rVybWHq6a0WhrmZgaboHi5n8ymgwRbM8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-ZLczhksx4+OpxZGChcR6o/jBIHldhOt8XpRDJPyDfeU=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-eTlfzsTldT7TjA25qNYpX+MAAskuYiA9Y+zZW9/B+MU=", "index.html": "sha256-wHPL38nEdZyiESe+MlLb9ZgRLg+MfbRXMzN538tD0pE=", "README.md": "sha256-hZvyqPLVQoQuOKc7t2j0cESQRW84E8XfCL/ad6sXIdw=", - "manifest.json": "sha256-uE41ppP3fPQSO1RWxPnhd8Zoqlh9cVyfgTKwwVT5Ajs=" + "manifest.json": "sha256-gr4sDXDH6C1w5B4FlFNPxU1RkmMpBWG+Mx3Ge9fNES0=" } } }, @@ -19745,21 +19745,21 @@ "copy": { "directory": "copy/data-table/", "files": { - "runtime/register/data-table.js": "sha256-BtE8hPANffhtRYhX+PBKWwtZUJMtlvG/m3ctxaSCwTU=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/register/menu.js": "sha256-YX+9ydadaIbkPIBFhLWX4Jv3V9vIl4UY1qolxLGfZUg=", - "runtime/components/menu.js": "sha256-AMtJth+M+4jqb8imqdn9VcM3aKvtgCWkPySfsI7htH8=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", - "runtime/components/data-table.js": "sha256-jj60XwNxQlssKZTff5HB9Z6v14UDZdK8O80kLP082l4=", - "runtime/chunks/tables-B25ydUHs.js": "sha256-XqRdyfrSS93rVybWHq6a0WhrmZgaboHi5n8ymgwRbM8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-aygLfHiZmFXenQHQrHnjVcw8W0tp2SLdB7d/laGcKgA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-FieIuPCt66UIxpdAH0wuPBOrPEVXUqjJfyWMyCdO9nI=", "index.html": "sha256-wxdZWAwB7Q/aPOpcvws/xlqJAMNO1twAxfHnSVMuNlo=", "README.md": "sha256-bS0eRb53j0VgRsRbFv81sqclvoIS7Uv4m/FIBGXMqTw=", - "manifest.json": "sha256-2ou/6/GgNuGgAaCssLJwSinsCUqepjlg+x2p8l6YANI=" + "manifest.json": "sha256-OCyt7FSrvzT/nqyGad7t90WQqktfbHMhmLRKVC7ayI8=" } } }, @@ -20047,18 +20047,18 @@ "copy": { "directory": "copy/timeline/", "files": { - "runtime/register/timeline.js": "sha256-DmcJVvF9PvFZM0ka0qgQH9L6lE7TCHhDf56kHMV+SA4=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/timeline.js": "sha256-c1+8tebuE76i5IkY1RRqwNlDkRBrhVwBH4BiCMTSBs4=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-VnvBxMC1c6IWen0gQ3RLi0m3FOelH4E8j4xG+B5Zoas=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-pj/LmsP7e5l3NZI2ZWOLcerU4j0Vn1w2EloUpExz0nw=", "index.html": "sha256-Ob/LUhVAfw+2yZ5HV+/MpGcf5gBqNfOvKXpabGlMOEs=", "README.md": "sha256-CNaX7w50n7r2LnTaBiC5oWdtQN0tep2SK/Q0ggYScgo=", - "manifest.json": "sha256-0Or3Y8Tm/QMqmLp4lpUHlYERYtvsxQV0B7ZW9XTw6fg=" + "manifest.json": "sha256-I6GYvjBcp+vO3kJk8Fst/bUcq2ZqzEyTlSdwUfdhyu4=" } } }, @@ -20400,18 +20400,18 @@ "copy": { "directory": "copy/chart/", "files": { - "runtime/register/chart.js": "sha256-5iBwKSjcyRylARXTeL2emhbuI2FCMQ757IBdPqFnU0U=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/chart.js": "sha256-J4rkX+ylh8URHbl2DxJ2FtbkHBtan2UOpNGVJIh1LjQ=", - "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-/W9/IEOepx6zAHtGcRJs1x0lwfMFkVEiYDCV4y4byXw=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Wk7EuPuisom2ohEBkZvcgafrpN7xXzlCUaNrWq7BZEA=", "index.html": "sha256-HuXni+L2aI7ES/QsPUPIODbff80dbY+jNFEIzyVxLFg=", "README.md": "sha256-AvM1lRutn7M/qWu0sIsbdBF9wn5nT5Ag8avrXpfo9a4=", - "manifest.json": "sha256-lm2ZxifbDt5iYTAwiLkbvEREqGAmkeGkqLeoqfgfbLw=" + "manifest.json": "sha256-F/2fv5nZscYggNH2x3Z0v/7Jg7onkrxtjw3NNZ95mf8=" } } }, @@ -20671,18 +20671,18 @@ "copy": { "directory": "copy/kbd/", "files": { - "runtime/register/kbd.js": "sha256-bIqjf3wmYiE5WXjgu0PbMLOsZ/LIWT+En7xpv6yWDNQ=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/kbd.js": "sha256-xi2+ei38C1TTd2xavWMW/PM7cQTzc0o4g+7LNPNHnUQ=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-sKesLjkvspbpsD6walvgEF0NFv1fsIWXNbBy+hhtAUE=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-tpH9QDJi6WP1xXEjkGhicB0miKDe2fe69wAALVp2X5A=", "index.html": "sha256-n95EF5vEOXJJV0vVrIVOke9WC7Ja83CiFAFm4jiOY3w=", "README.md": "sha256-CY2b+9Xug3mHZLhawZDvq8BFYG/fjfij5F7sNanjAy4=", - "manifest.json": "sha256-N3o7jonx7ZxjgaydH4c9BuaHiyHBNtfdwvsGJReVWvc=" + "manifest.json": "sha256-0oroIGs5QHHIsEFAS8mzBCOPGSulP+DHSkFwKqbOqfE=" } } }, @@ -21133,18 +21133,18 @@ "copy": { "directory": "copy/alert/", "files": { - "runtime/register/alert.js": "sha256-da/DH6uAJcK9QeCEbqBELiYsVrWkN9elrGzFJKH78ZI=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/alert.js": "sha256-afRZEs1g1g0l5Fh9oTXjl7R4w6ChNBFZ+N8x/BeJexg=", - "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", + "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-viVrXu+dUgCAMDq7iuljYYljZLxreTt4cQ+40NUQ3Js=", + "runtime/chunks/overlays-Bw8SSDKz.js": "sha256-YrX9CL2A48QwI7COQQ5anYJLPOxpKrIeyz+jtfp+T+I=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-cEV4WAKxLNKgYY5pU9nDVSG4toj5mM7vGZwyE+6Ui8o=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-QUAq9dxIFB1jlxB27CrSrEZKRLa4rC6qRLbWmR2t/ug=", "index.html": "sha256-F+j2IXSP/bqqvJ5iiyqLOkHvIuLBvN0FsF+7CX+ZhVs=", "README.md": "sha256-tx+34leZRjiZARWtxlnmDc9/6JPBGKFZl1od0IYo4kc=", - "manifest.json": "sha256-2ZbWfxl+0O3OjPAuMynLSs9Kp25QuUMiwXSpMKBlxQ0=" + "manifest.json": "sha256-GdtuucxCeKVz8/V2jsQmrExTynqtoj18Ngk2eibPo1A=" } } }, @@ -21674,18 +21674,18 @@ "copy": { "directory": "copy/toast/", "files": { - "runtime/register/toast.js": "sha256-IdIE1uz4eUV1mu94jhavw3kQx9Omawr6aMO+ij/EIRU=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/toast.js": "sha256-v6J5D8moC3m7GxC2mVYytkK8MOkwHSwODcmKmj1Kkgk=", - "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", + "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-WIMDZ+G0PKE8LTL9S9wLE1enIZrIXAt4h0Isi5xnGTU=", + "runtime/chunks/overlays-Bw8SSDKz.js": "sha256-YrX9CL2A48QwI7COQQ5anYJLPOxpKrIeyz+jtfp+T+I=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-dMp7q8HbznH2LxwbeRaoK7WL/2M2GeVwkitql3aJ3GE=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-2DXrOBOlEPzc9p3N5SEbw98qHHSMYTxlOnR6gT91kkU=", "index.html": "sha256-UfXmgxl10YQJyIiSccW0Sy7gHSjlICq9a865B0vR+7Q=", "README.md": "sha256-Gqkqv+2L4+y8mTQfPGpUxoV4B+6QJazzN5XtXWfyj4w=", - "manifest.json": "sha256-5G6eFKtb0RzEvUaf7y/U2BUwja0sO/DtWmx8/bruQU8=" + "manifest.json": "sha256-cO1fkE2cxytYMT7X5VXymS8J2mqSvNmVpdw8u5n58ZU=" } } }, @@ -21989,18 +21989,18 @@ "copy": { "directory": "copy/progress/", "files": { - "runtime/register/progress.js": "sha256-wcMNQVWBoGiWoasImip5urxM4QZkIIiDqdTbDHFb09c=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/progress.js": "sha256-SoIKI41QOIzDVzCbEX4RjUwuYIgyVdRipglbNI30PdE=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-qVh6/s9QPg2t6WrczrtP5i8fP1blV8a6S9OZUF5oJdY=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Bm2XYmsDcMrSYl/yKw1emmfA++ea/EjE5wzSjdg0eyw=", "index.html": "sha256-PMCQa/n0AlL1bSbPiT96VPfHTQgJmUowUoHElZGYf5k=", "README.md": "sha256-oXXC+n+f426Xr1+uHSEamfpzBwqmaBbe41P73puQ9p4=", - "manifest.json": "sha256-r+zhlEfXkdl5bcryLN+l4mssjPuUGlyjB4vslOUMdck=" + "manifest.json": "sha256-v1IrrUgpbjJYfPnq8pHamsdybSUnPAa8pRh6S8p+PSQ=" } } }, @@ -22292,18 +22292,18 @@ "copy": { "directory": "copy/loading-indicator/", "files": { - "runtime/register/loading-indicator.js": "sha256-4wKk+e/O8cCnxAR2RouY4I5/K1UuOcPjh3ehR7I9oqo=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/loading-indicator.js": "sha256-iTQYSJMXD02jZHXKFvaFfVLsSwVgLrG7ERC0uWAqpvU=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-eNbtRNqnJDdDaKs9tYapfgCNRwMffdQ7e2TqjrYuL6w=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-yiCrGr/OXo7SakIH4qRV3wDHbj09EqyJ2F7eTQHbnbc=", "index.html": "sha256-MGxeLPPCJTIT6qFSP0xS4GBpdzFTGjBojEELvbNO6VY=", "README.md": "sha256-YVFITjZXVN2sAQCTUcMZO5v0Xsc63owlmsQGMTQ42wY=", - "manifest.json": "sha256-E5QH4rXH0Q8cEQtr0bOGShuzZQlv5Y0cZ76Um3cCKCg=" + "manifest.json": "sha256-+AYJYt3+YOXzkhh2cHyzuvahnmCB9rfq9SOV4G+Rb1U=" } } }, @@ -22591,18 +22591,18 @@ "copy": { "directory": "copy/skeleton/", "files": { - "runtime/register/skeleton.js": "sha256-LZWZWuDy/lr/JDq+2VL59KCkU2EurStRQaUsuNF4US4=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/skeleton.js": "sha256-Ou8+/8NCHGRzG6ik6k6762M8G4PMLaBQXj4aPynetXo=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-JI92x7GOktbjpIm0AQnODJ4rVTJnEQA4DLP34bflM4k=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-/g7jxryHfbaG3yxoxK8NfCh2k5U92wPPELD/107+2Ps=", "index.html": "sha256-wOHcfVLjvDJzcjrxHt2FdIU6zvsgQKyM+mk68FWiW1g=", "README.md": "sha256-nzNnLPK+pu75MG+iTs+EMp/xOyJFTC/9GM9JCwIoCno=", - "manifest.json": "sha256-4LwxROheBPrSRHAZZzi9L4TDIlPOW7pk4CjtpDmBKQw=" + "manifest.json": "sha256-Tse4D2OoORQr9mD6VjfJczC882UFnIjNvurneAO/X9U=" } } }, @@ -22965,18 +22965,18 @@ "copy": { "directory": "copy/tooltip/", "files": { - "runtime/register/tooltip.js": "sha256-HkIZuQ8Gs11kQ0MzBEIBWrfaPopBPdUh+ODRas1HzLk=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/tooltip.js": "sha256-3/N04wmhF1WPLWW0LBMN2pFnpLGTy7p7toYw2pZpNw0=", - "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", + "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-MhBgu8Nu2Vx7dqARBvSKFOY+LCcOut1TAcB/5QSwPPI=", + "runtime/chunks/overlays-Bw8SSDKz.js": "sha256-YrX9CL2A48QwI7COQQ5anYJLPOxpKrIeyz+jtfp+T+I=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Skdu3czE82hMaq0VZwtG6ERV4Hud75l3iMhOfMR7K7U=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-+kSohyFbJg7z8/YUnlkzY1UQAu9ZLX7qE1eFLvk/1hI=", "index.html": "sha256-E+iyir+kE7FZW4yp4r+zjaBJSIcRsJGbvmwPckUJga0=", "README.md": "sha256-gCdLT45+37bldGYfH9LhZjTXGX04d3jZOS7ARTD3bCE=", - "manifest.json": "sha256-LkcqlVgeLQw44bCRmlXlSU+9P8cA2jVRRTLSgZlvDps=" + "manifest.json": "sha256-Me0HsoZyvQ2n2VjoDO5Lw49BbBBX6TZjPCZ1QmE/0bM=" } } }, @@ -23318,18 +23318,18 @@ "copy": { "directory": "copy/popover/", "files": { - "runtime/register/popover.js": "sha256-eWKTLAUIMPauNqccfCSWaTkpN6Eyrj+GtlvM7FRaKHc=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/popover.js": "sha256-P63Ou+ew1qtVXdZkxnO6uM5ZG7w9hOBlPK+HNXQbkAU=", - "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", + "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-qVz5uQ2xxsSVcKXfgit5JgjSZ3kzPvm9/Mt3A4X1NEg=", + "runtime/chunks/overlays-Bw8SSDKz.js": "sha256-YrX9CL2A48QwI7COQQ5anYJLPOxpKrIeyz+jtfp+T+I=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-53zGKZZyZMB+sdGIbnQk30oFXcLvjoplsW7FfQ9W0u0=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-tBbkSUEedfklBWmTm/lh13o3rlYHe/9AGgvmXp+p/Lo=", "index.html": "sha256-qj6qyYYBmNfnfn4cPT10GeMQN/ToGtN/ZB6H3yjUV/g=", "README.md": "sha256-2w2CMw7jTANV0wE6ux5POoe9QeMf/7BVerq3YrpiziI=", - "manifest.json": "sha256-Phnn5besyYINT3a2SO+Oyfo34q3wPJpuLaWvH2pQWAU=" + "manifest.json": "sha256-77eZwFgpetX/GOZnOtSMNU/CDHsi/KG+ixW0IpkmiwM=" } } }, @@ -24030,18 +24030,18 @@ "copy": { "directory": "copy/dialog/", "files": { - "runtime/register/dialog.js": "sha256-Y6MRVCgkK5UEzcEdMHQSCUf6gMnxsPOJuhfEFWmJXOw=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/dialog.js": "sha256-e9pTCjxk1e95o6PW5WuKLJsHz87/SQRFeL9+DTQyk5I=", - "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", + "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-mYfz6BnuRAPGKxNiVulnuJ4IEMvqr5BPqrNrZCRR5H8=", + "runtime/chunks/overlays-Bw8SSDKz.js": "sha256-YrX9CL2A48QwI7COQQ5anYJLPOxpKrIeyz+jtfp+T+I=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-d4bh9HaP4YOtfgWmP42qVqw3nqSJ3DF629AWjqoZTn4=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-wFFtRxUFWBTzxYOcblp+JjddYxJQF3QKoOb0/hIuSL0=", "index.html": "sha256-cDDMTM4Wj+7faOBKrvRWjGkb2tcMvyJcbhuH6ForsLs=", "README.md": "sha256-qhTQOsunJthiAQNFRNPTJx74lX2dH6rh6jISELzgD5Q=", - "manifest.json": "sha256-ffV0ZOGvzK4N5REfOqb5SopYFtk70wS5so3vIH5qUHc=" + "manifest.json": "sha256-ojK2lUJ8amSjYbXkYaErv1Tz8TPOx9vQe0FohxK9PvA=" } } }, @@ -24743,18 +24743,18 @@ "copy": { "directory": "copy/drawer/", "files": { - "runtime/register/drawer.js": "sha256-6AFbTqS+kQAd15TJ9NzKLIyNKPdVVmxyZMeHJXtNEhU=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/drawer.js": "sha256-vwjZdEg2SybEwAsIBL+uJuAs6ArJnLfrtqdRiOtleqA=", - "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", + "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-jGdxQ8JnwAPl1aTJWnbXrRb0kPIs7kJZo5rIrmfBTF4=", + "runtime/chunks/overlays-Bw8SSDKz.js": "sha256-YrX9CL2A48QwI7COQQ5anYJLPOxpKrIeyz+jtfp+T+I=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-39DmGp3B3f8+C/QGAv6xbiVXT7QviSaVCnHk8XpC158=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-RNAiKQJPioHCtfhMtqcsFaQFfwhKvdH+iIfLXOWo6QQ=", "index.html": "sha256-CbS/ignNl9YlA8MUwmXMnGVVRk6rR78IN2YGSe3T/OI=", "README.md": "sha256-fOfwfTYC9vdlgQFOfWiigzqCKfrU93VWnGHVQW9kH8s=", - "manifest.json": "sha256-4F6UZloyQg8I7wVtudpN0GlasZZCpflUeQnezTwqvss=" + "manifest.json": "sha256-3OnnmMpVSx6TFSQGJa2Sy+MQ9nWHNTdwDhFx50SWiCA=" } } }, @@ -25189,18 +25189,18 @@ "copy": { "directory": "copy/empty-state/", "files": { - "runtime/register/empty-state.js": "sha256-U7bwZQNspzXEKbkM+QwrFwH9wCsXZ+UNK2RYEFi+FjI=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/empty-state.js": "sha256-bmsYB/w+TevvaR9K+tvrVuNDGxVPv2PYR4hbTkhw+dU=", - "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", + "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-OdxqAGZuSH7KdWGE58jWJBVQnd4azuJVXLqmIEKf/1k=", + "runtime/chunks/overlays-Bw8SSDKz.js": "sha256-YrX9CL2A48QwI7COQQ5anYJLPOxpKrIeyz+jtfp+T+I=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Mdd72ooxolJDcPYScpT7yUM7Uj1SV5nk9LuG9vP0EeA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-j6rKuP4LmxmaKm47ZcfAqQ0LKMqN7l90HZwvUydHutQ=", "index.html": "sha256-rcFm3dTOVu+pB+gds4jp/elaQrgi/1rGF8xpNTCacL4=", "README.md": "sha256-460PP03z7gtyCcQW1opIbUBVyz/wg3Dv8SyzbynmB2E=", - "manifest.json": "sha256-75nIi6f/Ht0GN4W2P39d86rZv1OvN/aduq/2EcG1HB4=" + "manifest.json": "sha256-A4qwhMTw4YwVgEdLkoA8+YjIxeHsdoa4rDwk9HrftLE=" } } }, @@ -25559,18 +25559,18 @@ "copy": { "directory": "copy/error-state/", "files": { - "runtime/register/error-state.js": "sha256-LIyigSg3KPB01jhmW1+pAsrMoPyf6KtZcmrTenvFCx8=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/error-state.js": "sha256-vgUhuSmkAd9uc2x8r5Oc5k2rjzWbEtFRnrR0smV/YqM=", - "runtime/chunks/overlays-C6nlCHqg.js": "sha256-JtKjtFU2sbObAEtYaA9S+YE40WKP5hX073Xv4lpA67o=", + "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-SjO3330quFN81HjlZH31y/z5f1V4MNQewsgHCYnHvA8=", + "runtime/chunks/overlays-Bw8SSDKz.js": "sha256-YrX9CL2A48QwI7COQQ5anYJLPOxpKrIeyz+jtfp+T+I=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-CdLPhgSZDY0ucB4/nfZpfphuYXcfoqslUTPyuhz2tDw=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-ORjrriOpBHk2VlqSsyeUSEs1medDwB5oaTT4RxrXLFs=", "index.html": "sha256-ypHtxbip0wQwfxcnTK23eRJ0nU1YTWrbBIr8zvdVgzA=", "README.md": "sha256-Dl3lNTMlz4fye9SN1UJc6WVgA6BbWKgqHMIRpH62yOY=", - "manifest.json": "sha256-gv+zrrKBwqknOREXPEz57rKP+7GJco38FRkXeXQqAbU=" + "manifest.json": "sha256-xFn0ldAM/ke5tayuHtg+fqk9nJrMEeaqJCXK8Wpdr+4=" } } }, @@ -26107,18 +26107,18 @@ "copy": { "directory": "copy/code-editor/", "files": { - "runtime/register/code-editor.js": "sha256-agRsxgm8tBPEgLi7nGnYfqB/KOMRnbad/Eph3+YfYnE=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/code-editor.js": "sha256-F0O1Zc5wQaq5NGzIEEBzGXHEfj0hUaCR23D2hnUukLY=", - "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-X9h2Mxr0yLKLoKffZDsC55HBiRmSX+SuRQkjkcxerOo=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-aD+1gDxKB5fijO+A+hjuTqChvHPDv5zp5tK9UPZhwLc=", "index.html": "sha256-Dn2d67XC/1eO3QNVfsBf4pv4f2WuhBmmk1fFbSiGnWY=", "README.md": "sha256-oP4WnaIDAzxwm22ndFvMgchWr7l/DH7YotacPAFZuO8=", - "manifest.json": "sha256-ilcy8XyaIxDvpFx8RrzkFJhHJ6uot99rm2kBpXxBYBI=" + "manifest.json": "sha256-/A+RNxZGcOIo0DFchNAZJ6m84/3M7PzfW3bRO9VFry4=" } } }, @@ -26487,18 +26487,18 @@ "copy": { "directory": "copy/editor-search/", "files": { - "runtime/register/editor-search.js": "sha256-tMpvZf9OrWiyhDzn0EWZnEz8kSJ2SP8tALzQVYqwCws=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/editor-search.js": "sha256-tPLpeyxQ/8Gf/LImxqGBvRraQE6oFXtqIspmI84b8XA=", - "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-M0SrYSnjmhmwR0wfAiNg1VU3bXhEQkYknaGRLw0fWMM=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-d4aAYzdcDHNmdiry3w1Y3xEHMEA6MELYHpoj25fZY7M=", "index.html": "sha256-nzYqIKBlE7peT4onxSzqAj0mwZHNcvHOF2jIuZV5iKo=", "README.md": "sha256-uCiQ7xpaMDEYDoL/7zMcafsbXKeQ+tnAyLmxgCMABh8=", - "manifest.json": "sha256-tzETVZ5wEm/wqmqM6Gu3ONUNlEVtbZUiPneNH2sbPZ8=" + "manifest.json": "sha256-h937qBCyN7f/4/4NbTvjeZNcmsKJzaShOXGOQ6xHnrc=" } } }, @@ -27072,18 +27072,18 @@ "copy": { "directory": "copy/diagnostics/", "files": { - "runtime/register/diagnostics.js": "sha256-lSYtaMuTbe7wtLvNB4chvQ8SOVu0ILi3pFknhy/X/0E=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/diagnostics.js": "sha256-nC94tOw1MCiaCz5hbJRQf8qjWzQDz53K24KiwRwR8ws=", - "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-1uXLsplg978riCNhv/v5p+RvR0hW6fVdRnKgNUo+IYs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-oPPp/R+dnwC1tnH/Td+Hlrs3CRODUkA4Bvq/HK/fAUU=", "index.html": "sha256-Tq03gSM/g1JYQlO5vswlLUOSXHf9l2bEjBuZbLQpK1E=", "README.md": "sha256-zoebnEYS306DsFzwTsEnc2EoKA+8Dm/eyz4eTXdSnAs=", - "manifest.json": "sha256-UpdG5YWwniZZMmaHLoJEtfjfHyOOvfgh9kwW7yzjGME=" + "manifest.json": "sha256-tL7GzLYckJ9GfhEdUi2jnGJqqdrX3eIBHflY5RDP6gs=" } } }, @@ -27605,18 +27605,18 @@ "copy": { "directory": "copy/diff-view/", "files": { - "runtime/register/diff-view.js": "sha256-dfbslff/fV33ePOMN/mGU9l+7RqomLajKxKQdpmW+qQ=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/diff-view.js": "sha256-QfZm092MHlNhP9Vfs6IkWjXkbrGughYsBfHTOCL93cM=", - "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-mibFUolrx0OWHlYNpEFTvfkMI0c6h4CUv7SWJ4eQVns=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-t7cx4Y+4qhIPiwFbRPz+6U12N/CFATPTfG7/iZf85zs=", "index.html": "sha256-EYPYe3QVJkVBz7byssoY6NHiAMZc9tW/oSLut2DPrX4=", "README.md": "sha256-2/6IFU4JJZ25X3ZvCCwHM1P9pvt3nJHAUfxoS/Ubi/0=", - "manifest.json": "sha256-kxUgBrJ5pugX+Rn/YdpdeR3lTLsYCBlHWGv/+4xyeGY=" + "manifest.json": "sha256-5CyVIpdcAcf9a6jxhdb1P7rhVAf7Q2Ge062mNu8e6kM=" } } }, @@ -28158,18 +28158,18 @@ "copy": { "directory": "copy/terminal/", "files": { - "runtime/register/terminal.js": "sha256-HI+Ed6H0sblV3/oR4o14WYg9OG1oLmgIOC/HbV2sFos=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/terminal.js": "sha256-nnvO5VIA3kECyTshxbykc7AqrK88ML0IDEe6bYvfsQs=", - "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-U9mukzoAnquuoQ1KFzbK6bI+fxJdrdrhSiZgfwulwJM=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-WyXNyoxiAXNq3bLZRmrc1qS2XzgHghN+5tO+9HpocVA=", "index.html": "sha256-7nIjP5H9Tnolb/DAw1vtVGkOfqf2/oL9ZxMvSounzKk=", "README.md": "sha256-JMb0MyBFXbZ2TBIQrpRDNUjcH0R6qtmsRDfzwcOAY6o=", - "manifest.json": "sha256-Um+BronLZKEFOHCEpSta1jnlVHpAUaE+SY2iEDpTXgA=" + "manifest.json": "sha256-rbo4awKBVvGKzyDFUb4nwHQFmHGbdDfMwwXzGUdAREA=" } } }, @@ -28992,21 +28992,21 @@ "copy": { "directory": "copy/settings-panel/", "files": { - "runtime/register/settings-panel.js": "sha256-tecYNnB3mOO1ir+NYaorlqzgeTXRhGpkaMeZZ5TKo7k=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/register/switch.js": "sha256-WA0Avt/JJmz7DqxDx8v5Rnw3WCZFaVGJjPdibTQKkSc=", - "runtime/components/switch.js": "sha256-Cad08u/MHjqLKKV0MpUQNKaHz1fLJnvy5dfayoqsjvI=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "runtime/components/settings-panel.js": "sha256-eL+HBTD98ipggaB6cWxKOgb2UXkBgKT50n7xxlWPHn0=", - "runtime/chunks/forms-BT3z7lNC.js": "sha256-Txmae07dWLj1H/FL869U0Kv84TQxzpdFeOg0g8zGK6I=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-bKV+vxJoQcQ+/WSkUADY0AkxpU9pAMAviGj+BrOQK1w=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Z1ZqDdIXySN8gWG0bvhT8iMaa+GaOyHy/vumYpCsYt8=", "index.html": "sha256-jGGdyR2U7IytSpOvqtrVJUJKtnNfW/khN9J+vCUatNM=", "README.md": "sha256-Jbd8VDlivmCdwjmixGLdZrE/QQ9xdJyk+UIIOcLDqZE=", - "manifest.json": "sha256-vLsgXoGOv6Ek2Vt1iEvKgMZAwnYyn2CTBoyAh/wxfJw=" + "manifest.json": "sha256-glxwnegkAvZYJi0GCvPvJPi4IlV8Tczl7pF2VYy/KYc=" } } }, @@ -29921,25 +29921,25 @@ "copy": { "directory": "copy/admin-form/", "files": { - "runtime/register/admin-form.js": "sha256-wbxQ6jG47yRORiZBcV1vZy21o7vLJ0wZWSBjlQ08r5o=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/register/text-field.js": "sha256-DD+ctMlKClOK6B/glshiJwIjKilewzY171GvKtVGf1A=", - "runtime/components/text-field.js": "sha256-6f5tLWwF57IFY+uH5zM0afiU3g09PW3M4772zC7zD4Q=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "runtime/register/textarea.js": "sha256-H+BMjmdgnMxVEA9KvLSSKoOlHTAH91Qy7+pjUiTlgEE=", - "runtime/components/textarea.js": "sha256-qJqDEskuaVeBUFjefVF+KSbJV3s6vpaKCtd4aQ4QtoY=", - "runtime/register/select.js": "sha256-zXXuJRnrp9EVnk1A8VpgUzF/JPShcAImY9zRc6nQasQ=", - "runtime/components/select.js": "sha256-yyq0jsJOysQGTPpFoA1C1aRWSIukrk+M4Ro2ZwCyWbw=", - "runtime/components/admin-form.js": "sha256-aN07ea+gUj6aAxwJjeILpqJFPUQJ27g3LAIjpHmljNg=", - "runtime/chunks/forms-BT3z7lNC.js": "sha256-Txmae07dWLj1H/FL869U0Kv84TQxzpdFeOg0g8zGK6I=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Of5oLJY6n5Yfqu44/xCAuuJEYRoCg4Kr+YZbVggbwZE=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-TRLraonRxggrZcfXS9jlN+nTIOpRHiXbMKQNm8NbR2A=", "index.html": "sha256-HsmeIqneb7G9ZHVJEuzAqXdP7AYU8OlzG8Rs70uYyBQ=", "README.md": "sha256-bid+/EA6npftuo0cAZQP6rg+96qu7gNC4h/Klx23PF0=", - "manifest.json": "sha256-nYS8jMsuxKEj8F3dOHKvnVCccydqs1Pp3Z6SsTCUoOU=" + "manifest.json": "sha256-SY9yLDIEoubx7vOjX86E6Af/lWOXakcF5RF345H06o0=" } } }, @@ -30701,21 +30701,21 @@ "copy": { "directory": "copy/filterable-table/", "files": { - "runtime/register/filterable-table.js": "sha256-4o9WlQbHlOnAg8mdJws9+tapo3wueOwNMacJhswL7Hg=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/register/search-field.js": "sha256-Z6IeX4+LKGVQJUcQGuyUnCBL6ggQSoevMhrj75zYisw=", - "runtime/components/search-field.js": "sha256-2ODKfrgzC53SjMT+P7oaRa78AgRY37MG12M7HVRwfQU=", - "runtime/chunks/native-CAzZmDKR.js": "sha256-er7tiDPWmSEvPEp+BvRPWpdqnw28ypHQStJng7Dbah4=", - "runtime/components/filterable-table.js": "sha256-1tup9iQXvwHywM5vJL3oiz0gLiDGNw/xjkZ91AA+Sok=", - "runtime/chunks/tables-B25ydUHs.js": "sha256-XqRdyfrSS93rVybWHq6a0WhrmZgaboHi5n8ymgwRbM8=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-ZpN1xEJy4fV/PBDvH91mkuN2CZqhCUo5wpeCs27jREo=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-3PbF9wWtnKy3q07M9x690D730biEbSwu20wHAcvPPEE=", "index.html": "sha256-61p1J3mpIgWTPXP4+wTHI0p/MffdvGq+yeT7j0urEZA=", "README.md": "sha256-eYSWLSbTgjyr+5CUJR+E3qhY267Qh6rmF+5P40UanuU=", - "manifest.json": "sha256-6e9ro37teOmSFrYcAJ7t+PP1FQ9FEb9GhcBjA3Ah5iw=" + "manifest.json": "sha256-vCP76v9Lq2Cjbf3J7rPkteGIiIcCkiscExcfBEdOpqw=" } } }, @@ -31683,19 +31683,19 @@ "copy": { "directory": "copy/i3-window-frame/", "files": { - "runtime/register/i3-window-frame.js": "sha256-T8BESQEwjGZsf7/+P5mPJcokXWquh+9IX+aeYr2odNE=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/components/i3-window-frame.js": "sha256-uqfVHNwkr/11a11fshN7f0r/dXipCi1Vfc0AlLb+i9c=", - "runtime/chunks/compositions-d6BkKTYf.js": "sha256-El5csGAVMeeZWmJ1ztdXW3O3t2AQPrf3YrEOMkGX17c=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-Yk/0tRkcDttUSZKxyg6O6C9kumrEAGehNElFt382jeA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-nNyvwUVLU3Rdy3x0UcZN+IkCA1+Ot5CVwjUB54GDnq8=", "index.html": "sha256-5VNshBKwk0GCY7ID/iL5fiZjb6VRrIZhEdVK/HjtiK0=", "README.md": "sha256-C0hpJoSU0W6E5VFxM/5nRjno1clSop0NLti9ZjvJiO0=", - "manifest.json": "sha256-U0UgHnHKVp5XKkj1fNN5b+MOeYjoFSjDI5MDm6KE5Qw=" + "manifest.json": "sha256-r+5f/+sKy8zad7v6pIzYWu+aS7a5X79zFso6utxNgvw=" } } }, @@ -32160,23 +32160,23 @@ "copy": { "directory": "copy/file-browser/", "files": { - "runtime/register/file-browser.js": "sha256-3aIWKczcdziEiQIR4gWOFhsKDAxyRTBDe0i3ynmVXis=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/register/tree.js": "sha256-xY8jWYnbMM8UlE/rdQJsu3/URGPvdUC06U1QmKsmFZQ=", - "runtime/components/tree.js": "sha256-1wgpPM9BoC1/T0Or37ZhoekuO2YZ3luXp+DpWKVKBcU=", - "runtime/chunks/advanced-DCpe8Ndv.js": "sha256-nr1LFdLYsGeTM4vDyldvuJygRm0F04sYonxatySPu1g=", + "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-mmsIwfdO+8Xy7vrRylWFBDIwAoWKfkgmb8J17rxDHVs=", - "runtime/chunks/compositions-d6BkKTYf.js": "sha256-El5csGAVMeeZWmJ1ztdXW3O3t2AQPrf3YrEOMkGX17c=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-jXsUncF3ZqNTAY54eALB2XHlOFiiumSXp+AnM14Tz1Q=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-TbSmPr7cV31g3WqgPi6LboOGQdmgxz/89Tf/3ld2pfU=", "index.html": "sha256-68VZEF9M4ZFNgI9IZ7yrpktM4/9dA+GR/D6aTo6ocn0=", "README.md": "sha256-pldg7PuzlPHL6J8L3tFRBhM4Mqi8AlcED3V2DXOXZRU=", - "manifest.json": "sha256-dumD1CMdclQzMmPsrLn3Denb28aFPOcd34uk/ZtbEgI=" + "manifest.json": "sha256-p+FD1Fb+C3/mulwIU8cKodFTh7cYo4/fbDxZVVWtLlM=" } } }, @@ -32661,22 +32661,22 @@ "copy": { "directory": "copy/compact-dashboard/", "files": { - "runtime/register/compact-dashboard.js": "sha256-+hjjezkupB41oBwwJyLeQY5FNxI9eXWs5VsP2irSgxY=", - "runtime/chunks/element-C1XeXVYC.js": "sha256-VZkTciWeek3bcBd4h0ngRVGe1X7zMK01xhx5IsNOOQ0=", - "runtime/chunks/choice-Db_w_BOQ.js": "sha256-Zj9PtQyyZKSATrJYBr7lXlddGGJMBDc5FSnZUWPNAiU=", - "runtime/register/chart.js": "sha256-5iBwKSjcyRylARXTeL2emhbuI2FCMQ757IBdPqFnU0U=", - "runtime/components/chart.js": "sha256-J4rkX+ylh8URHbl2DxJ2FtbkHBtan2UOpNGVJIh1LjQ=", - "runtime/chunks/display-dj9YaBfn.js": "sha256-0Y8LcHvfDz2LLz+EWdO8Jr6pfwnXPw03N8x1UcM2pN8=", - "runtime/components/compact-dashboard.js": "sha256-AyJRimILR3ZhpG7LU6Jtut1sQj0LSEFhOC9MT+gVfbQ=", - "runtime/chunks/compositions-d6BkKTYf.js": "sha256-El5csGAVMeeZWmJ1ztdXW3O3t2AQPrf3YrEOMkGX17c=", - "runtime/chunks/navigation-Dt8ap-9J.js": "sha256-7QSC/eQSDSRRy3YqMltwjb6cwbEA0V652cfo+Ng2VqA=", + "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=", "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", "component.css": "sha256-CK9kd2wDntxSLF6J4F4+3SFybCPdr/tSqL7xJpw3hFs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-I++zY2714BqcfCh02WgcXCFwujrwXLK4TwP9wII+QE4=", "index.html": "sha256-3/JWb8Uk24wjHBuQjWRaXDvwfUi9Mp9wjh4uYtdNxQ4=", "README.md": "sha256-6g2tbWoWmdPy5ju9eAR0VdQ5vp0GjEEftnqhmjoP1j4=", - "manifest.json": "sha256-6VcljZV/ScZZHBdlliiCRDKmNJun1WvkMSswT57Yue4=" + "manifest.json": "sha256-HhNyj8t8nMAPYgRrOBgscLpqzSmOmckytD+vDcBJ3rU=" } } } diff --git a/packages/ui/dist/register/admin-form.js b/packages/ui/dist/register/admin-form.js index 611bd32a3..a6ac994bb 100644 --- a/packages/ui/dist/register/admin-form.js +++ b/packages/ui/dist/register/admin-form.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import "./text-field.js"; import "./textarea.js"; import "./select.js"; diff --git a/packages/ui/dist/register/alert.js b/packages/ui/dist/register/alert.js index c0a9872de..4398942dd 100644 --- a/packages/ui/dist/register/alert.js +++ b/packages/ui/dist/register/alert.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Alert } from "../components/alert.js"; //#region .cache/ui-build/entries/register/alert.js var element = registerElement("j3w1-alert", J3w1Alert); diff --git a/packages/ui/dist/register/avatar.js b/packages/ui/dist/register/avatar.js index b2c66d2ae..9367113f3 100644 --- a/packages/ui/dist/register/avatar.js +++ b/packages/ui/dist/register/avatar.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Avatar } from "../components/avatar.js"; //#region .cache/ui-build/entries/register/avatar.js var element = registerElement("j3w1-avatar", J3w1Avatar); diff --git a/packages/ui/dist/register/badge.js b/packages/ui/dist/register/badge.js index 9e0027214..2fe7fff68 100644 --- a/packages/ui/dist/register/badge.js +++ b/packages/ui/dist/register/badge.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Badge } from "../components/badge.js"; //#region .cache/ui-build/entries/register/badge.js var element = registerElement("j3w1-badge", J3w1Badge); diff --git a/packages/ui/dist/register/breadcrumbs.js b/packages/ui/dist/register/breadcrumbs.js index 087fe5e6b..1b41f187d 100644 --- a/packages/ui/dist/register/breadcrumbs.js +++ b/packages/ui/dist/register/breadcrumbs.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Breadcrumbs } from "../components/breadcrumbs.js"; //#region .cache/ui-build/entries/register/breadcrumbs.js var element = registerElement("j3w1-breadcrumbs", J3w1Breadcrumbs); diff --git a/packages/ui/dist/register/button-group.js b/packages/ui/dist/register/button-group.js index 81edee7d1..86bb9c765 100644 --- a/packages/ui/dist/register/button-group.js +++ b/packages/ui/dist/register/button-group.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1ButtonGroup } from "../components/button-group.js"; //#region .cache/ui-build/entries/register/button-group.js var element = registerElement("j3w1-button-group", J3w1ButtonGroup); diff --git a/packages/ui/dist/register/button.js b/packages/ui/dist/register/button.js index 8d63fb5fe..b01aa4dae 100644 --- a/packages/ui/dist/register/button.js +++ b/packages/ui/dist/register/button.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Button } from "../components/button.js"; //#region .cache/ui-build/entries/register/button.js var element = registerElement("j3w1-button", J3w1Button); diff --git a/packages/ui/dist/register/card.js b/packages/ui/dist/register/card.js index 31cc0f59d..2a9535cee 100644 --- a/packages/ui/dist/register/card.js +++ b/packages/ui/dist/register/card.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Card } from "../components/card.js"; //#region .cache/ui-build/entries/register/card.js var element = registerElement("j3w1-card", J3w1Card); diff --git a/packages/ui/dist/register/chart.js b/packages/ui/dist/register/chart.js index 17feb810e..8efbe0a3f 100644 --- a/packages/ui/dist/register/chart.js +++ b/packages/ui/dist/register/chart.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Chart } from "../components/chart.js"; //#region .cache/ui-build/entries/register/chart.js var element = registerElement("j3w1-chart", J3w1Chart); diff --git a/packages/ui/dist/register/checkbox.js b/packages/ui/dist/register/checkbox.js index 0e3541551..70632e2d0 100644 --- a/packages/ui/dist/register/checkbox.js +++ b/packages/ui/dist/register/checkbox.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Checkbox } from "../components/checkbox.js"; //#region .cache/ui-build/entries/register/checkbox.js var element = registerElement("j3w1-checkbox", J3w1Checkbox); diff --git a/packages/ui/dist/register/chip.js b/packages/ui/dist/register/chip.js index 399954b1a..d6b89d151 100644 --- a/packages/ui/dist/register/chip.js +++ b/packages/ui/dist/register/chip.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Chip } from "../components/chip.js"; //#region .cache/ui-build/entries/register/chip.js var element = registerElement("j3w1-chip", J3w1Chip); diff --git a/packages/ui/dist/register/code-editor.js b/packages/ui/dist/register/code-editor.js index ebfebc300..91f3f8d5f 100644 --- a/packages/ui/dist/register/code-editor.js +++ b/packages/ui/dist/register/code-editor.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1CodeEditor } from "../components/code-editor.js"; //#region .cache/ui-build/entries/register/code-editor.js var element = registerElement("j3w1-code-editor", J3w1CodeEditor); diff --git a/packages/ui/dist/register/combobox.js b/packages/ui/dist/register/combobox.js index 7469ac395..0441f87e8 100644 --- a/packages/ui/dist/register/combobox.js +++ b/packages/ui/dist/register/combobox.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Combobox } from "../components/combobox.js"; //#region .cache/ui-build/entries/register/combobox.js var element = registerElement("j3w1-combobox", J3w1Combobox); diff --git a/packages/ui/dist/register/command-palette.js b/packages/ui/dist/register/command-palette.js index 21d0307af..8c4d129ed 100644 --- a/packages/ui/dist/register/command-palette.js +++ b/packages/ui/dist/register/command-palette.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1CommandPalette } from "../components/command-palette.js"; //#region .cache/ui-build/entries/register/command-palette.js var element = registerElement("j3w1-command-palette", J3w1CommandPalette); diff --git a/packages/ui/dist/register/compact-dashboard.js b/packages/ui/dist/register/compact-dashboard.js index 93010f858..6a2980828 100644 --- a/packages/ui/dist/register/compact-dashboard.js +++ b/packages/ui/dist/register/compact-dashboard.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import "./chart.js"; import { J3w1CompactDashboard } from "../components/compact-dashboard.js"; //#region .cache/ui-build/entries/register/compact-dashboard.js diff --git a/packages/ui/dist/register/data-table.js b/packages/ui/dist/register/data-table.js index 9b565eed9..4d622c48b 100644 --- a/packages/ui/dist/register/data-table.js +++ b/packages/ui/dist/register/data-table.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import "./menu.js"; import { J3w1DataTable } from "../components/data-table.js"; //#region .cache/ui-build/entries/register/data-table.js diff --git a/packages/ui/dist/register/date-picker.js b/packages/ui/dist/register/date-picker.js index 24231b7fd..541cd14fa 100644 --- a/packages/ui/dist/register/date-picker.js +++ b/packages/ui/dist/register/date-picker.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1DatePicker } from "../components/date-picker.js"; //#region .cache/ui-build/entries/register/date-picker.js var element = registerElement("j3w1-date-picker", J3w1DatePicker); diff --git a/packages/ui/dist/register/description-list.js b/packages/ui/dist/register/description-list.js index b2341a425..37a62a7a6 100644 --- a/packages/ui/dist/register/description-list.js +++ b/packages/ui/dist/register/description-list.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1DescriptionList } from "../components/description-list.js"; //#region .cache/ui-build/entries/register/description-list.js var element = registerElement("j3w1-description-list", J3w1DescriptionList); diff --git a/packages/ui/dist/register/diagnostics.js b/packages/ui/dist/register/diagnostics.js index e92c83ed2..2d9f84547 100644 --- a/packages/ui/dist/register/diagnostics.js +++ b/packages/ui/dist/register/diagnostics.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Diagnostics } from "../components/diagnostics.js"; //#region .cache/ui-build/entries/register/diagnostics.js var element = registerElement("j3w1-diagnostics", J3w1Diagnostics); diff --git a/packages/ui/dist/register/dialog.js b/packages/ui/dist/register/dialog.js index ee673cb86..bded0a66c 100644 --- a/packages/ui/dist/register/dialog.js +++ b/packages/ui/dist/register/dialog.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Dialog } from "../components/dialog.js"; //#region .cache/ui-build/entries/register/dialog.js var element = registerElement("j3w1-dialog", J3w1Dialog); diff --git a/packages/ui/dist/register/diff-view.js b/packages/ui/dist/register/diff-view.js index 53e4b042d..92fc87c5c 100644 --- a/packages/ui/dist/register/diff-view.js +++ b/packages/ui/dist/register/diff-view.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1DiffView } from "../components/diff-view.js"; //#region .cache/ui-build/entries/register/diff-view.js var element = registerElement("j3w1-diff-view", J3w1DiffView); diff --git a/packages/ui/dist/register/disclosure.js b/packages/ui/dist/register/disclosure.js index 5eff2865e..76f4c204b 100644 --- a/packages/ui/dist/register/disclosure.js +++ b/packages/ui/dist/register/disclosure.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Disclosure } from "../components/disclosure.js"; //#region .cache/ui-build/entries/register/disclosure.js var element = registerElement("j3w1-disclosure", J3w1Disclosure); diff --git a/packages/ui/dist/register/drawer.js b/packages/ui/dist/register/drawer.js index d2101eb9d..3ea076673 100644 --- a/packages/ui/dist/register/drawer.js +++ b/packages/ui/dist/register/drawer.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Drawer } from "../components/drawer.js"; //#region .cache/ui-build/entries/register/drawer.js var element = registerElement("j3w1-drawer", J3w1Drawer); diff --git a/packages/ui/dist/register/editor-search.js b/packages/ui/dist/register/editor-search.js index fa960075d..e0237ca4a 100644 --- a/packages/ui/dist/register/editor-search.js +++ b/packages/ui/dist/register/editor-search.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1EditorSearch } from "../components/editor-search.js"; //#region .cache/ui-build/entries/register/editor-search.js var element = registerElement("j3w1-editor-search", J3w1EditorSearch); diff --git a/packages/ui/dist/register/empty-state.js b/packages/ui/dist/register/empty-state.js index cc2e584c5..a4b9594da 100644 --- a/packages/ui/dist/register/empty-state.js +++ b/packages/ui/dist/register/empty-state.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1EmptyState } from "../components/empty-state.js"; //#region .cache/ui-build/entries/register/empty-state.js var element = registerElement("j3w1-empty-state", J3w1EmptyState); diff --git a/packages/ui/dist/register/error-state.js b/packages/ui/dist/register/error-state.js index 14d6dc937..5e09ece1b 100644 --- a/packages/ui/dist/register/error-state.js +++ b/packages/ui/dist/register/error-state.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1ErrorState } from "../components/error-state.js"; //#region .cache/ui-build/entries/register/error-state.js var element = registerElement("j3w1-error-state", J3w1ErrorState); diff --git a/packages/ui/dist/register/field.js b/packages/ui/dist/register/field.js index 245800b81..875540d71 100644 --- a/packages/ui/dist/register/field.js +++ b/packages/ui/dist/register/field.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Field } from "../components/field.js"; //#region .cache/ui-build/entries/register/field.js var element = registerElement("j3w1-field", J3w1Field); diff --git a/packages/ui/dist/register/fieldset.js b/packages/ui/dist/register/fieldset.js index 23d5cdd65..4ac632e86 100644 --- a/packages/ui/dist/register/fieldset.js +++ b/packages/ui/dist/register/fieldset.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Fieldset } from "../components/fieldset.js"; //#region .cache/ui-build/entries/register/fieldset.js var element = registerElement("j3w1-fieldset", J3w1Fieldset); diff --git a/packages/ui/dist/register/file-browser.js b/packages/ui/dist/register/file-browser.js index 546633566..6d8b76ed5 100644 --- a/packages/ui/dist/register/file-browser.js +++ b/packages/ui/dist/register/file-browser.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import "./tree.js"; import { J3w1FileBrowser } from "../components/file-browser.js"; //#region .cache/ui-build/entries/register/file-browser.js diff --git a/packages/ui/dist/register/file-input.js b/packages/ui/dist/register/file-input.js index e840437d0..33be9dd6d 100644 --- a/packages/ui/dist/register/file-input.js +++ b/packages/ui/dist/register/file-input.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1FileInput } from "../components/file-input.js"; //#region .cache/ui-build/entries/register/file-input.js var element = registerElement("j3w1-file-input", J3w1FileInput); diff --git a/packages/ui/dist/register/filterable-table.js b/packages/ui/dist/register/filterable-table.js index 067befcb7..25aeaaee0 100644 --- a/packages/ui/dist/register/filterable-table.js +++ b/packages/ui/dist/register/filterable-table.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import "./search-field.js"; import { J3w1FilterableTable } from "../components/filterable-table.js"; //#region .cache/ui-build/entries/register/filterable-table.js diff --git a/packages/ui/dist/register/form-builder.js b/packages/ui/dist/register/form-builder.js index 320e671f8..cb2169fa6 100644 --- a/packages/ui/dist/register/form-builder.js +++ b/packages/ui/dist/register/form-builder.js @@ -1,5 +1,5 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; -import { t as J3w1FormBuilder } from "../chunks/form-builder-C6Rhfsz6.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { t as J3w1FormBuilder } from "../chunks/form-builder-C4avSOze.js"; //#region .cache/ui-build/entries/register/form-builder.js var element = registerElement("j3w1-form-builder", J3w1FormBuilder); //#endregion diff --git a/packages/ui/dist/register/i3-window-frame.js b/packages/ui/dist/register/i3-window-frame.js index dd2360632..75e3eb7d6 100644 --- a/packages/ui/dist/register/i3-window-frame.js +++ b/packages/ui/dist/register/i3-window-frame.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1I3WindowFrame } from "../components/i3-window-frame.js"; //#region .cache/ui-build/entries/register/i3-window-frame.js var element = registerElement("j3w1-i3-window-frame", J3w1I3WindowFrame); diff --git a/packages/ui/dist/register/icon-button.js b/packages/ui/dist/register/icon-button.js index 4a1f9ef47..ffdd0ac88 100644 --- a/packages/ui/dist/register/icon-button.js +++ b/packages/ui/dist/register/icon-button.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1IconButton } from "../components/icon-button.js"; //#region .cache/ui-build/entries/register/icon-button.js var element = registerElement("j3w1-icon-button", J3w1IconButton); diff --git a/packages/ui/dist/register/kbd.js b/packages/ui/dist/register/kbd.js index eed420027..6ae12a7fc 100644 --- a/packages/ui/dist/register/kbd.js +++ b/packages/ui/dist/register/kbd.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Kbd } from "../components/kbd.js"; //#region .cache/ui-build/entries/register/kbd.js var element = registerElement("j3w1-kbd", J3w1Kbd); diff --git a/packages/ui/dist/register/link.js b/packages/ui/dist/register/link.js index 1ae8adb9e..669ae18ab 100644 --- a/packages/ui/dist/register/link.js +++ b/packages/ui/dist/register/link.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Link } from "../components/link.js"; //#region .cache/ui-build/entries/register/link.js var element = registerElement("j3w1-link", J3w1Link); diff --git a/packages/ui/dist/register/list.js b/packages/ui/dist/register/list.js index 46d02889b..2642fae97 100644 --- a/packages/ui/dist/register/list.js +++ b/packages/ui/dist/register/list.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1List } from "../components/list.js"; //#region .cache/ui-build/entries/register/list.js var element = registerElement("j3w1-list", J3w1List); diff --git a/packages/ui/dist/register/loading-indicator.js b/packages/ui/dist/register/loading-indicator.js index 20938b029..5e3a0b442 100644 --- a/packages/ui/dist/register/loading-indicator.js +++ b/packages/ui/dist/register/loading-indicator.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1LoadingIndicator } from "../components/loading-indicator.js"; //#region .cache/ui-build/entries/register/loading-indicator.js var element = registerElement("j3w1-loading-indicator", J3w1LoadingIndicator); diff --git a/packages/ui/dist/register/menu.js b/packages/ui/dist/register/menu.js index 734c05e98..655b77a5a 100644 --- a/packages/ui/dist/register/menu.js +++ b/packages/ui/dist/register/menu.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Menu } from "../components/menu.js"; //#region .cache/ui-build/entries/register/menu.js var element = registerElement("j3w1-menu", J3w1Menu); diff --git a/packages/ui/dist/register/multiselect.js b/packages/ui/dist/register/multiselect.js index 8a91da5b0..9183e5e5a 100644 --- a/packages/ui/dist/register/multiselect.js +++ b/packages/ui/dist/register/multiselect.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Multiselect } from "../components/multiselect.js"; //#region .cache/ui-build/entries/register/multiselect.js var element = registerElement("j3w1-multiselect", J3w1Multiselect); diff --git a/packages/ui/dist/register/number-field.js b/packages/ui/dist/register/number-field.js index c8e0e7c36..8553c5a33 100644 --- a/packages/ui/dist/register/number-field.js +++ b/packages/ui/dist/register/number-field.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1NumberField } from "../components/number-field.js"; //#region .cache/ui-build/entries/register/number-field.js var element = registerElement("j3w1-number-field", J3w1NumberField); diff --git a/packages/ui/dist/register/pagination.js b/packages/ui/dist/register/pagination.js index 2dfeec151..26680a048 100644 --- a/packages/ui/dist/register/pagination.js +++ b/packages/ui/dist/register/pagination.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Pagination } from "../components/pagination.js"; //#region .cache/ui-build/entries/register/pagination.js var element = registerElement("j3w1-pagination", J3w1Pagination); diff --git a/packages/ui/dist/register/popover.js b/packages/ui/dist/register/popover.js index 4a5798987..5f801317f 100644 --- a/packages/ui/dist/register/popover.js +++ b/packages/ui/dist/register/popover.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Popover } from "../components/popover.js"; //#region .cache/ui-build/entries/register/popover.js var element = registerElement("j3w1-popover", J3w1Popover); diff --git a/packages/ui/dist/register/progress.js b/packages/ui/dist/register/progress.js index 54bd975e5..29de54fb7 100644 --- a/packages/ui/dist/register/progress.js +++ b/packages/ui/dist/register/progress.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Progress } from "../components/progress.js"; //#region .cache/ui-build/entries/register/progress.js var element = registerElement("j3w1-progress", J3w1Progress); diff --git a/packages/ui/dist/register/radio-group.js b/packages/ui/dist/register/radio-group.js index e40f29b44..a41f213ff 100644 --- a/packages/ui/dist/register/radio-group.js +++ b/packages/ui/dist/register/radio-group.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1RadioGroup } from "../components/radio-group.js"; //#region .cache/ui-build/entries/register/radio-group.js var element = registerElement("j3w1-radio-group", J3w1RadioGroup); diff --git a/packages/ui/dist/register/range.js b/packages/ui/dist/register/range.js index 9711437a7..63b83eab7 100644 --- a/packages/ui/dist/register/range.js +++ b/packages/ui/dist/register/range.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Range } from "../components/range.js"; //#region .cache/ui-build/entries/register/range.js var element = registerElement("j3w1-range", J3w1Range); diff --git a/packages/ui/dist/register/repeater.js b/packages/ui/dist/register/repeater.js index b53fb3ce5..6565442ff 100644 --- a/packages/ui/dist/register/repeater.js +++ b/packages/ui/dist/register/repeater.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Repeater } from "../components/repeater.js"; //#region .cache/ui-build/entries/register/repeater.js var element = registerElement("j3w1-repeater", J3w1Repeater); diff --git a/packages/ui/dist/register/search-field.js b/packages/ui/dist/register/search-field.js index 63da3cd5b..169a29a47 100644 --- a/packages/ui/dist/register/search-field.js +++ b/packages/ui/dist/register/search-field.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1SearchField } from "../components/search-field.js"; //#region .cache/ui-build/entries/register/search-field.js var element = registerElement("j3w1-search-field", J3w1SearchField); diff --git a/packages/ui/dist/register/segmented-control.js b/packages/ui/dist/register/segmented-control.js index 20f7f4d8a..526fd7f71 100644 --- a/packages/ui/dist/register/segmented-control.js +++ b/packages/ui/dist/register/segmented-control.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1SegmentedControl } from "../components/segmented-control.js"; //#region .cache/ui-build/entries/register/segmented-control.js var element = registerElement("j3w1-segmented-control", J3w1SegmentedControl); diff --git a/packages/ui/dist/register/select.js b/packages/ui/dist/register/select.js index b97661d55..6fcd3d855 100644 --- a/packages/ui/dist/register/select.js +++ b/packages/ui/dist/register/select.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Select } from "../components/select.js"; //#region .cache/ui-build/entries/register/select.js var element = registerElement("j3w1-select", J3w1Select); diff --git a/packages/ui/dist/register/settings-panel.js b/packages/ui/dist/register/settings-panel.js index 20c582b67..0067d590e 100644 --- a/packages/ui/dist/register/settings-panel.js +++ b/packages/ui/dist/register/settings-panel.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import "./switch.js"; import { J3w1SettingsPanel } from "../components/settings-panel.js"; //#region .cache/ui-build/entries/register/settings-panel.js diff --git a/packages/ui/dist/register/sidebar-nav.js b/packages/ui/dist/register/sidebar-nav.js index 8f0297afb..59f4cc44a 100644 --- a/packages/ui/dist/register/sidebar-nav.js +++ b/packages/ui/dist/register/sidebar-nav.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1SidebarNav } from "../components/sidebar-nav.js"; //#region .cache/ui-build/entries/register/sidebar-nav.js var element = registerElement("j3w1-sidebar-nav", J3w1SidebarNav); diff --git a/packages/ui/dist/register/skeleton.js b/packages/ui/dist/register/skeleton.js index 71f911e98..ed0ab489a 100644 --- a/packages/ui/dist/register/skeleton.js +++ b/packages/ui/dist/register/skeleton.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Skeleton } from "../components/skeleton.js"; //#region .cache/ui-build/entries/register/skeleton.js var element = registerElement("j3w1-skeleton", J3w1Skeleton); diff --git a/packages/ui/dist/register/skip-link.js b/packages/ui/dist/register/skip-link.js index 24e9f3d0c..7f93eeef8 100644 --- a/packages/ui/dist/register/skip-link.js +++ b/packages/ui/dist/register/skip-link.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1SkipLink } from "../components/skip-link.js"; //#region .cache/ui-build/entries/register/skip-link.js var element = registerElement("j3w1-skip-link", J3w1SkipLink); diff --git a/packages/ui/dist/register/switch.js b/packages/ui/dist/register/switch.js index 05a2f592f..5e227ec0d 100644 --- a/packages/ui/dist/register/switch.js +++ b/packages/ui/dist/register/switch.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Switch } from "../components/switch.js"; //#region .cache/ui-build/entries/register/switch.js var element = registerElement("j3w1-switch", J3w1Switch); diff --git a/packages/ui/dist/register/table.js b/packages/ui/dist/register/table.js index 10a75676a..b8eda4f9d 100644 --- a/packages/ui/dist/register/table.js +++ b/packages/ui/dist/register/table.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Table } from "../components/table.js"; //#region .cache/ui-build/entries/register/table.js var element = registerElement("j3w1-table", J3w1Table); diff --git a/packages/ui/dist/register/tabs.js b/packages/ui/dist/register/tabs.js index d2f3bb53e..218ebc6da 100644 --- a/packages/ui/dist/register/tabs.js +++ b/packages/ui/dist/register/tabs.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Tabs } from "../components/tabs.js"; //#region .cache/ui-build/entries/register/tabs.js var element = registerElement("j3w1-tabs", J3w1Tabs); diff --git a/packages/ui/dist/register/terminal.js b/packages/ui/dist/register/terminal.js index 252927e52..0f41964d0 100644 --- a/packages/ui/dist/register/terminal.js +++ b/packages/ui/dist/register/terminal.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Terminal } from "../components/terminal.js"; //#region .cache/ui-build/entries/register/terminal.js var element = registerElement("j3w1-terminal", J3w1Terminal); diff --git a/packages/ui/dist/register/text-field.js b/packages/ui/dist/register/text-field.js index e3bf71d74..01007e107 100644 --- a/packages/ui/dist/register/text-field.js +++ b/packages/ui/dist/register/text-field.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1TextField } from "../components/text-field.js"; //#region .cache/ui-build/entries/register/text-field.js var element = registerElement("j3w1-text-field", J3w1TextField); diff --git a/packages/ui/dist/register/textarea.js b/packages/ui/dist/register/textarea.js index ea76ce485..2e9a5db69 100644 --- a/packages/ui/dist/register/textarea.js +++ b/packages/ui/dist/register/textarea.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Textarea } from "../components/textarea.js"; //#region .cache/ui-build/entries/register/textarea.js var element = registerElement("j3w1-textarea", J3w1Textarea); diff --git a/packages/ui/dist/register/time-picker.js b/packages/ui/dist/register/time-picker.js index 244c895c6..f69ab0f23 100644 --- a/packages/ui/dist/register/time-picker.js +++ b/packages/ui/dist/register/time-picker.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1TimePicker } from "../components/time-picker.js"; //#region .cache/ui-build/entries/register/time-picker.js var element = registerElement("j3w1-time-picker", J3w1TimePicker); diff --git a/packages/ui/dist/register/timeline.js b/packages/ui/dist/register/timeline.js index 82d652b24..6b8f4b354 100644 --- a/packages/ui/dist/register/timeline.js +++ b/packages/ui/dist/register/timeline.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Timeline } from "../components/timeline.js"; //#region .cache/ui-build/entries/register/timeline.js var element = registerElement("j3w1-timeline", J3w1Timeline); diff --git a/packages/ui/dist/register/toast.js b/packages/ui/dist/register/toast.js index 39672f0fe..55941b8ec 100644 --- a/packages/ui/dist/register/toast.js +++ b/packages/ui/dist/register/toast.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Toast } from "../components/toast.js"; //#region .cache/ui-build/entries/register/toast.js var element = registerElement("j3w1-toast", J3w1Toast); diff --git a/packages/ui/dist/register/toolbar.js b/packages/ui/dist/register/toolbar.js index e39eab7da..0de0d853e 100644 --- a/packages/ui/dist/register/toolbar.js +++ b/packages/ui/dist/register/toolbar.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Toolbar } from "../components/toolbar.js"; import "./menu.js"; //#region .cache/ui-build/entries/register/toolbar.js diff --git a/packages/ui/dist/register/tooltip.js b/packages/ui/dist/register/tooltip.js index b8308dd65..262fbe4be 100644 --- a/packages/ui/dist/register/tooltip.js +++ b/packages/ui/dist/register/tooltip.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Tooltip } from "../components/tooltip.js"; //#region .cache/ui-build/entries/register/tooltip.js var element = registerElement("j3w1-tooltip", J3w1Tooltip); diff --git a/packages/ui/dist/register/tree.js b/packages/ui/dist/register/tree.js index c6b7d3d39..0ecee9bca 100644 --- a/packages/ui/dist/register/tree.js +++ b/packages/ui/dist/register/tree.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Tree } from "../components/tree.js"; //#region .cache/ui-build/entries/register/tree.js var element = registerElement("j3w1-tree", J3w1Tree); diff --git a/packages/ui/dist/register/wizard.js b/packages/ui/dist/register/wizard.js index e78c20e3e..df8a879a1 100644 --- a/packages/ui/dist/register/wizard.js +++ b/packages/ui/dist/register/wizard.js @@ -1,4 +1,4 @@ -import { n as registerElement } from "../chunks/element-C1XeXVYC.js"; +import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; import { J3w1Wizard } from "../components/wizard.js"; //#region .cache/ui-build/entries/register/wizard.js var element = registerElement("j3w1-wizard", J3w1Wizard); From dc0d46181f726f15872dbde26650c3db550beff9 Mon Sep 17 00:00:00 2001 From: j3w1 Date: Wed, 14 Oct 2026 15:40:18 -0500 Subject: [PATCH 07/65] spec: state each component rule once, without hand-written ratios The owner asked for specs without unnecessary verbosity. The 67 component bodies restated frontmatter the site and exports already render (variants, anatomy, tokens, keys, contrast pairs) and quoted contrast ratios by hand, most of them stale since D-026, D-027 and D-033 (button's primary 9.28:1, text-field's placeholder 5.81:1). Bodies now keep purpose, behaviour nuance, precedence, host obligations and non-examples; every heading and States row stays, and every removed fact is traced in the D2 claim ledger. link.md follows accepted D-027: links hover on color.interaction.hover.bg, in the prose, root.bg-hover, the hover stateTokens, the summary and the "ring on the hover fill" contrast pair. text-field.md drops a reason that contradicted D-025. tests/spec-prose.test.js fails when spec prose or a component body names a ratio other than the 3:1, 4.5:1 and 7:1 floors; computed values live in the frontmatter contrast pairs and exports/contrast.md. Co-Authored-By: Claude Opus 5.5 --- spec/components/admin-form.md | 81 +++++++----------- spec/components/alert.md | 58 ++++++------- spec/components/avatar.md | 23 +++--- spec/components/badge.md | 53 +++++------- spec/components/breadcrumbs.md | 57 ++++++------- spec/components/button-group.md | 16 ++-- spec/components/button.md | 68 ++++++--------- spec/components/card.md | 54 +++++------- spec/components/chart.md | 27 +++--- spec/components/checkbox.md | 61 ++++++-------- spec/components/chip.md | 62 ++++++-------- spec/components/code-editor.md | 113 +++++++++++-------------- spec/components/combobox.md | 80 +++++++----------- spec/components/command-palette.md | 33 ++++---- spec/components/compact-dashboard.md | 25 +++--- spec/components/data-table.md | 79 +++++++----------- spec/components/date-picker.md | 50 ++++++----- spec/components/description-list.md | 16 ++-- spec/components/diagnostics.md | 80 ++++++++---------- spec/components/dialog.md | 69 +++++++--------- spec/components/diff-view.md | 100 ++++++++++------------ spec/components/disclosure.md | 12 ++- spec/components/drawer.md | 59 ++++++------- spec/components/editor-search.md | 14 ++-- spec/components/empty-state.md | 47 +++++------ spec/components/error-state.md | 18 ++-- spec/components/field.md | 42 ++++------ spec/components/fieldset.md | 44 +++++----- spec/components/file-browser.md | 21 ++--- spec/components/file-input.md | 68 ++++++--------- spec/components/filterable-table.md | 79 +++++++----------- spec/components/form-builder.md | 65 +++++++-------- spec/components/i3-window-frame.md | 82 ++++++------------ spec/components/icon-button.md | 52 ++++++------ spec/components/kbd.md | 16 ++-- spec/components/link.md | 57 ++++++------- spec/components/list.md | 62 ++++++-------- spec/components/loading-indicator.md | 49 +++++------ spec/components/menu.md | 69 ++++++---------- spec/components/multiselect.md | 20 ++--- spec/components/number-field.md | 49 +++++------ spec/components/pagination.md | 54 +++++------- spec/components/popover.md | 18 ++-- spec/components/progress.md | 49 +++++------ spec/components/radio-group.md | 54 +++++------- spec/components/range.md | 27 +++--- spec/components/repeater.md | 30 +++---- spec/components/search-field.md | 59 ++++++------- spec/components/segmented-control.md | 15 ++-- spec/components/select.md | 71 +++++++--------- spec/components/settings-panel.md | 61 +++++--------- spec/components/sidebar-nav.md | 66 ++++++--------- spec/components/skeleton.md | 26 +++--- spec/components/skip-link.md | 49 +++++------ spec/components/switch.md | 54 ++++++------ spec/components/table.md | 63 ++++++-------- spec/components/tabs.md | 54 +++++------- spec/components/terminal.md | 119 +++++++++++---------------- spec/components/text-field.md | 64 ++++++-------- spec/components/textarea.md | 45 +++++----- spec/components/time-picker.md | 44 ++++++---- spec/components/timeline.md | 14 ++-- spec/components/toast.md | 59 ++++++------- spec/components/toolbar.md | 54 +++++------- spec/components/tooltip.md | 60 ++++++-------- spec/components/tree.md | 16 ++-- spec/components/wizard.md | 66 ++++++--------- tests/spec-prose.test.js | 27 ++++++ 68 files changed, 1463 insertions(+), 1985 deletions(-) create mode 100644 tests/spec-prose.test.js diff --git a/spec/components/admin-form.md b/spec/components/admin-form.md index 84e6541b7..6ab47d24c 100644 --- a/spec/components/admin-form.md +++ b/spec/components/admin-form.md @@ -129,76 +129,55 @@ compact: false ## Purpose -A record screen that proves the advanced form components compose with the -navigation and feedback components: a trail, a heading, a step list, a -notice, a grid of fields and a row of actions, then the same screen at its -review step. It exists to show validation, saving and inertness across a -whole form, not to prescribe a product. +A record screen proving that the advanced form components compose with the +navigation and feedback components, then the same screen at its review step. +It shows validation, saving and inertness across a whole form; it does not +prescribe a product. ## Anatomy -The region landmark; the breadcrumbs (Records / Workstations / New); the h2 -in {color.text.bright}; the wizard step list with the current step on the -2px {color.border.selected-indicator}; an info alert on -{color.status.info.tint}; the form landmark holding the name and hostname -text-fields, the role select, the commissioned-on date-picker, the SSH-key -file-input, the notes textarea with its count and the enable checkbox; the -footer rule and the Back, Save draft and Continue buttons. The review -variant replaces the fields with a table whose row headers are the field -names in {color.text.muted} and whose last column is a tertiary Edit button. -Every part is the component's own markup and classes. +Parts as listed in the anatomy; each is the contained component's own markup +and classes. ## States | State | Visual | Non-colour channel | | --- | --- | --- | -| default | rest tokens of every component on {color.surface.default}; the current step carries the indicator bar, future steps are disabled | `aria-current="step"` | -| invalid | the name and hostname fields take the 2px {color.status.danger.border} and show their ✕ messages; the current step's marker becomes ✕; a danger alert on {color.status.danger.tint} summarising the two fields replaces the notice; the other fields stay at rest | border width 1 → 2px; glyphs; `aria-invalid`; `role="alert"` | -| busy | Continue shows the static ⋯ glyph in {color.action.primary.text}; the form carries `aria-busy`; nothing shrinks or animates | glyph; `aria-busy`; cursor: progress | -| disabled | every control takes its component's disabled treatment ({color.text.disabled}, {color.border.disabled}, {color.interaction.disabled.bg}); labels and review keys dim; no hover anywhere | `disabled` on the wrapping fieldset; cursor: not-allowed; never opacity | +| default | every component's rest tokens on {color.surface.default}; the current step carries the indicator bar, future steps are disabled | `aria-current="step"` | +| invalid | name and hostname take the 2px {color.status.danger.border} and ✕ messages; the current step's marker becomes ✕; a danger summary on {color.status.danger.tint} naming the two fields replaces the notice; other fields stay at rest | border 1 → 2px; glyphs; `aria-invalid`; `role="alert"` | +| busy | Continue shows the static ⋯ in {color.action.primary.text}; nothing shrinks or animates | glyph; `aria-busy` on the form; cursor: progress | +| disabled | every control takes its component's disabled treatment ({color.text.disabled}, {color.border.disabled}, {color.interaction.disabled.bg}); labels and review keys dim; no hover | `disabled` on the wrapping fieldset; cursor: not-allowed; never opacity | -The composed components keep their own hover, focus-visible, required, -placeholder-shown and read-only treatments; this specimen declares only the -states the whole form adds to them. +Contained components keep their own hover, focus-visible, required, +placeholder-shown and read-only states; this table adds only the form-level +ones. ## Keyboard -Landmarks first: the region, the Breadcrumb navigation and the form are -offered by name. Tab walks the trail, the reachable steps, the fields in -reading order and the three buttons; the file-input's hidden native input is -the stop and its visible button label is drawn with the ring. The select and -the date field move with arrows inside one stop. In the review variant the -Edit buttons are ordinary stops inside the table. Nothing traps focus. +The region, the Breadcrumb navigation and the form are offered as landmarks +by name. In the review variant the Edit buttons are ordinary stops inside the +table. Nothing traps focus. ## Accessibility -The region and the form are both named by the h2. Complete steps read ", complete" -through a visually hidden suffix; future steps are disabled, not hidden. -The notice is `role="status"` and the invalid summary is `role="alert"`, so -the summary is announced once on submit while each field's message stays -linked by `aria-describedby`; `aria-invalid` is set only after submit. While -saving the form carries `aria-busy` and, once inert, sits inside a disabled -fieldset so every control reports its state natively. The review table has -a caption, column headers and row headers; each Edit button names its field -through a visually hidden suffix. Contrast: notice title 6.5:1 or better on -its tint, messages 5.26:1 on the panel surface, the invalid boundary 4.69:1 -on the input surface, disabled text 3.24:1 (exempt). +The h2 names both the region and the form. Complete steps read ", complete" +through a visually hidden suffix; future steps are disabled, not hidden. The +summary alert is announced once on submit; each field's message stays linked +by `aria-describedby`. Inside the disabled fieldset every control reports its +state natively. The review table has a caption, column headers and row +headers; each Edit button names its field through a visually hidden suffix. +Text meets 4.5:1 and the invalid boundary 3:1; disabled text is exempt (house +floor 3:1). ## Portability -Landmarks, native controls, one container query and three root hooks -(`data-state-invalid`, `data-state-busy`, `data-state-disabled`); no script -is needed to render any state. Hosts without container queries stack the -footer at the 600px viewport breakpoint. The 56rem reference width and the -two-column field grid are layout of this specimen and not rules; the -specimen proves composition, not a product. Toolkits port each contained +No script is needed to render any state. Toolkits port each contained component through its own mapping. ## Non-examples -A rounded card with a drop shadow around the form. A Material stepper with -circular numbered badges and a connecting line. A red banner across the -whole form instead of the summary alert plus field messages. Fields whose -borders glow red. A spinner replacing the Continue label. Saving while the -fields fade to half opacity. Placing the actions in a sticky footer bar with -a shadow. +A rounded card with a drop shadow. A Material stepper with numbered circles +and a connecting line. A red banner across the whole form instead of the +summary alert plus field messages. Field borders that glow red. A spinner +replacing the Continue label. Fields fading to half opacity while saving. A +sticky footer bar with a shadow. diff --git a/spec/components/alert.md b/spec/components/alert.md index c9128ea41..9edb2012f 100644 --- a/spec/components/alert.md +++ b/spec/components/alert.md @@ -103,62 +103,50 @@ compact: false ## Purpose A status message that belongs to the page or form around it: a failed -submit, a saved draft, a deprecation notice. It stays in flow, is never -timed, and is announced once when it appears. Transient confirmations are -toasts; blocking questions are dialogs. +submit, a saved draft, a deprecation notice. It stays in flow, is never timed, +and is announced once when it appears. Transient confirmations are toasts; +blocking questions are dialogs. ## Anatomy -The block on the status tint behind a 1px status border; the glyph in the -status text colour; the title in the same colour and the message in -{color.text.default}; an optional close button at the end. The five statuses -use their own `tint`, `border` and `text` roles: {color.status.danger.tint}, -{color.status.warning.tint}, {color.status.success.tint}, -{color.status.info.tint} and {color.status.neutral.tint} behind -{color.status.danger.border}, {color.status.warning.border}, -{color.status.success.border}, {color.status.info.border} and -{color.status.neutral.border}. +Parts as listed in the anatomy. Each of the five statuses uses its own +`tint`, `border` and `text` roles. ## States | State | Visual | Non-colour channel | | --- | --- | --- | | default | status tint, 1px status border, glyph and title in the status text colour | the glyph ✕ ! ✓ i · | -| hover | close button background → {color.action.tertiary.hover-bg}; the alert itself does not react | cursor: pointer on the button only | -| focus-visible | ring 1px dashed {color.interaction.focus.ring} at −2px on the close button | the ring | +| hover | close button → {color.action.tertiary.hover-bg}; the alert itself does not react | cursor: pointer on the button only | +| focus-visible | 1px dashed {color.interaction.focus.ring} ring at −2px on the close button | the ring | -The alert has no disabled, selected or loading state; a message that is no -longer true is removed, not greyed. +No disabled, selected or loading state: a message that is no longer true is +removed, not greyed. ## Keyboard -Only the close button is in the tab order. Enter or Space dismisses and -returns focus to where it was, or to the next focusable element after the -alert when that element is gone. Escape does nothing, so a page-level Escape -handler is never swallowed. +As in the key table. Escape does nothing so a page-level Escape handler is +never swallowed. ## Accessibility -Danger uses `role="alert"` (assertive) because it needs attention now; the -other four use `role="status"` (polite). The container exists before its -text is set, so the live region fires; text is never injected together with -the container. The glyph is `aria-hidden` and the title states the status in -words ("Build failed", "Saved"), so nothing depends on colour or on the glyph -alone. The close button is `aria-label="Dismiss"` and at least 24×24 CSS -pixels. Contrast: status text on its tint from 4.88:1 (danger) to 6.59:1 -(warning, info); body text at least 7.56:1 on every tint; borders from 4.07:1 -(neutral) to 6.59:1. +Danger is `role="alert"` (assertive) because it needs attention now; the +other four are `role="status"` (polite). The container exists before its text +is set so the live region fires; never inject text together with the +container. The glyph is `aria-hidden` and the title states the status in +words ("Build failed", "Saved"), so nothing depends on colour or the glyph +alone. The close button is at least 24×24 CSS pixels. Text meets 4.5:1 on +every tint; borders 3:1. ## Portability -Everything is a tint, a 1px border and text; the glyph is a text character, -not an icon font. Toolkits with a native info bar map its type to the five -statuses and keep the glyph in the text; toolkits without a tint draw the -border only and record the deviation. +The glyph is a text character, not an icon font. A toolkit with a native info +bar maps its type to the five statuses and keeps the glyph in the text; one +without a tint draws the border only and records the deviation. ## Non-examples A coloured left stripe with no border. A rounded, shadowed card. A banner that slides in or auto-dismisses. Colour-only status without the glyph and a -worded title. Using `role="alert"` for success messages. A close button that -is an icon with no accessible name. Fixed-position alerts covering content. +worded title. `role="alert"` for success. A close icon with no accessible +name. Fixed-position alerts covering content. diff --git a/spec/components/avatar.md b/spec/components/avatar.md index 32d03068e..3ad70fb33 100644 --- a/spec/components/avatar.md +++ b/spec/components/avatar.md @@ -92,33 +92,34 @@ compact: false ## Purpose -Identify a person or entity with an optional caller-owned image and text fallback. The component ships no image service or assets. Failed images restore the fallback and retain the full accessible name. +Identifies a person or entity; the caller owns the image. ## Anatomy -- **frame:** Square bounded image area with a border. -- **fallback:** Caller-supplied initials, backed by the full accessible name. -- **image:** Optional image; failed loading restores the text fallback. +Parts as listed in the anatomy. ## States -| State | Presentation | Non-colour channel | +| State | Visual | Non-colour channel | | --- | --- | --- | -| default | Initials or loaded image. | Full name on the image container. | -| loading | Fallback remains visible. | No loss of the full accessible name while loading. | -| error | Fallback remains visible. | Image failure does not remove the entity name. | +| default | Initials or the loaded image. | Full name on the image container. | +| loading | Fallback stays visible. | Full accessible name kept. | +| error | Fallback stays visible. | Full accessible name kept. | ## Keyboard -- **Tab:** No additional tab stop. An enclosing link remains native. +As in the key table; nothing is bound. ## Accessibility -Use one full accessible name, avoiding duplicate announcements from image alt and fallback text. Initials alone do not adequately identify a person. A decorative avatar beside an equivalent visible name may be aria-hidden. +One full accessible name, never announced twice by image alt and fallback +text; initials alone do not identify a person. A decorative avatar beside an +equivalent visible name may be `aria-hidden`. ## Portability -Follows the shared component defaults in `spec/portability.md` (section "Shared component defaults"). +Follows the shared component defaults in `spec/portability.md` (section +"Shared component defaults"). ## Non-examples diff --git a/spec/components/badge.md b/spec/components/badge.md index 0af93ce3b..14934f32c 100644 --- a/spec/components/badge.md +++ b/spec/components/badge.md @@ -97,57 +97,46 @@ compact: false ## Purpose Names a status or shows a count next to the thing it describes. A badge is -read-only: it never opens, toggles or removes anything. An interactive -label is a chip; a message with a status is an alert. +read-only: it never opens, toggles or removes anything. An interactive label +is a chip; a message with a status is an alert. ## Anatomy -An inline span in caption type with 2px by 8px padding and square corners. -Status badges fill with `color.status..fill` and use the matching -`on-fill` text, preceded by the status glyph: ✕ danger, ! warning, ✓ success, -i info, · neutral. Outline badges have no fill, the `text` colour and a 1px -`border` in the same status. The count badge is a number on -{color.action.primary.bg} in {color.action.primary.text} with a visually -hidden unit. An empty badge is an 8px square dot in the status fill with a -name. +Parts as listed in the anatomy. The glyphs are ✕ danger, ! warning, ✓ +success, i info and · neutral. ## States | State | Visual | Non-colour channel | | --- | --- | --- | | default | fill, glyph and text for the status; or the outline form | the glyph; the text | -| empty | an 8px square dot in the status fill; the glyph and text visually hidden | `role="img"` with `aria-label`, or the hidden text; the dot's position beside its subject | +| empty | an 8px square dot in the status fill; glyph and text visually hidden | `role="img"` with `aria-label`, or the hidden text; the dot's position beside its subject | -A badge has no hover, focus, pressed or disabled state because it is not a -control. +No hover, focus, pressed or disabled state: a badge is not a control. ## Keyboard -None. A badge is never focusable. When a badge summarises something the -user can act on, the action lives in the neighbouring control and the badge -is part of that control's name or description. +None. When a badge summarises something the user can act on, the action lives +in the neighbouring control and the badge is part of that control's name or +description. ## Accessibility -The glyph is `aria-hidden` and the text carries the meaning, so a screen -reader hears "Failed", not "cross Failed". Count badges include their unit -as visually hidden text ("12 unread"). An empty badge, a dot, carries -`role="img"` and `aria-label` or wraps hidden text; a dot with no name is -decoration and must be `aria-hidden`. Contrast: on-fill text 4.58:1 (danger), -7.54:1 (warning), 7.13:1 (success), 7.08:1 (info), 4.71:1 (neutral); outline -text 5.26:1 to 7.34:1; borders and dots at least 4.04:1 on the panel surface. -Badges are not targets, so no minimum size applies beyond legibility at 11px -caption type. +The text carries the meaning, so a reader hears "Failed", not "cross Failed". +The count's hidden unit reads as "12 unread". An empty badge may wrap hidden +text instead of `aria-label`; a dot with no name is decoration and must be +`aria-hidden`. Text meets 4.5:1; outline borders and dots 3:1 on the panel +surface. Badges are not targets, so no size minimum applies beyond legibility +at 11px caption type. ## Portability -A filled or outlined span with a glyph. Toolkits without background colours -on labels use the outline form. Hosts without the glyph characters use the -nearest available (x, !, check mark, i, bullet) and record it. +Toolkits without background colours on labels use the outline form. Hosts +without the glyph characters use the nearest available (x, !, check mark, i, +bullet) and record it. ## Non-examples -Rounded or pill badges. A badge that is clickable. A status shown by colour -without its glyph. A count badge that hides its unit from assistive -technology. Purple, cyan or magenta statuses. A badge in body type. A badge -whose text wraps. A dot without a name. +Rounded or pill badges. A clickable badge. A status by colour without its +glyph. A count unit hidden from assistive technology. Purple, cyan or magenta +statuses. A badge in body type. Wrapping text. A dot without a name. diff --git a/spec/components/breadcrumbs.md b/spec/components/breadcrumbs.md index 794f2997b..df0389aca 100644 --- a/spec/components/breadcrumbs.md +++ b/spec/components/breadcrumbs.md @@ -79,57 +79,48 @@ compact: false ## Purpose -Shows where the current page sits in a hierarchy and lets the user jump to -any ancestor. Breadcrumbs are secondary navigation: they never replace the -sidebar or the page title, and they are omitted on the root page. +Where the current page sits in a hierarchy, with a jump to any ancestor. +Secondary navigation: never a replacement for the sidebar or page title, and +omitted on the root page. ## Anatomy -A `nav` labelled "Breadcrumb" wrapping an `ol`. Each ancestor is a link in -{color.text.link} with a 1px {color.text.link-underline}; a `/` separator in -{color.text.muted} follows every item but the last; the last item is the -current page in {color.text.bright} with `aria-current="page"`. When the -trail is deeper than the space allows, the middle levels collapse behind an -ellipsis button that names how many levels it hides. +Parts as listed in the anatomy; the separator follows every item but the last. ## States | State | Visual | Non-colour channel | | --- | --- | --- | | default | links {color.text.link}, 1px underline; separators {color.text.muted}; current {color.text.bright} | underline on links; none on the current page | -| hover | link background → {color.interaction.hover.bg-strong}; text → {color.text.link-hover} | underline thickens 1px → 2px; cursor | -| focus-visible | ring 1px dashed {color.interaction.focus.ring} at −2px around the link | the ring | -| current | text {color.text.bright}; no underline; no hover | `aria-current="page"`; no underline | -| truncated | the middle levels are replaced by an `…` button in {color.text.default} | `aria-expanded="false"` on the button; its label counts the hidden levels | +| hover | link → {color.interaction.hover.bg-strong}, text {color.text.link-hover} | underline 1px → 2px; cursor | +| focus-visible | 1px dashed {color.interaction.focus.ring} at −2px around the link | the ring | +| current | {color.text.bright}; no underline; no hover | `aria-current="page"`; no underline | +| truncated | middle levels replaced by an `…` button in {color.text.default} | `aria-expanded="false"`; its label counts the hidden levels | ## Keyboard -Every ancestor link is a tab stop in trail order. The ellipsis button is a tab -stop that discloses the hidden levels in place on Enter or Space and sets its -own `aria-expanded`; focus stays on the button so the newly revealed links are -the next Tab presses. +As in the key table. The ellipsis button discloses the hidden levels in place +on Enter or Space; focus stays on it, so the revealed links are the next Tab +stops. ## Accessibility -`aria-label="Breadcrumb"` on the `nav`, translated. The separator is -`aria-hidden` so nothing voices "slash"; the list structure gives the count. -`aria-current="page"` marks the last item whether or not it is a link. Hidden -levels stay in the DOM under the ellipsis (`hidden` until disclosed) so a -find-in-page still reaches them. Contrast: link text 10.10:1, current -10.10:1, separator 5.66:1, underline 4.57:1 on the panel surface. Each link -is at least 24 CSS pixels tall through its line box and padding. +The `nav` label "Breadcrumb" is translated. The `aria-hidden` separator keeps +"slash" unspoken; the list gives the count. `aria-current="page"` marks the +last item, link or not. Hidden levels stay in the DOM (`hidden` until +disclosed) so find-in-page reaches them. Text meets 4.5:1; underline and ring +3:1. Each link is at least 24 CSS pixels tall through line box and padding. ## Portability -Plain inline links and text; the only requirement is an inline-start margin -on the separator that flips in RTL. Toolkits without an underline draw the -link in the link colour and record the deviation. The ellipsis disclosure is -optional; hosts without it show the full trail and let it wrap. +Plain inline links and text; the separator needs only an inline-start margin +that flips in RTL. Without an underline, a toolkit draws the link in the link +colour and records the deviation. The ellipsis is optional; without it the +full trail shows and wraps. ## Non-examples -Chevrons, arrows or bullets as separators. A trail that ends with the site -name instead of the current page. The current page drawn as a link with an -underline. Automatic truncation by `text-overflow` that hides levels without -a way to reach them. A trail that scrolls horizontally. Uppercase or -letter-spaced items. Separators that are read aloud. +Chevrons, arrows or bullets as separators. A trail ending with the site name +instead of the current page. The current page as an underlined link. +`text-overflow` truncation that hides unreachable levels. A horizontally +scrolling trail. Uppercase or letter-spaced items. Separators read aloud. diff --git a/spec/components/button-group.md b/spec/components/button-group.md index 54746e2f2..3a6af6a5c 100644 --- a/spec/components/button-group.md +++ b/spec/components/button-group.md @@ -98,16 +98,15 @@ compact: false ## Purpose -Group related independent actions without turning them into an exclusive choice. Each button keeps its native type, accessible name and tab stop. Application effects belong to the host. +Groups related, independent actions without making them an exclusive choice. ## Anatomy -- **group:** Labelled group that wraps its buttons. -- **actions:** Independent buttons in source order. +Parts as listed in the anatomy. ## States -| State | Presentation | Non-colour channel | +| State | Visual | Non-colour channel | | --- | --- | --- | | default | Named content on the default surface. | Native text and structure. | | focus-visible | Dashed focus ring. | Native keyboard focus position. | @@ -115,12 +114,12 @@ Group related independent actions without turning them into an exclusive choice. ## Keyboard -- **Tab / Shift+Tab:** Visit each enabled button. -- **Enter / Space:** Activate the focused native button. +As in the key table; no arrow-key navigation is added. ## Accessibility -Use role=group with a visible or accessible label. Buttons retain distinct names and native disabled behavior. A button group does not add arrow-key navigation or selection semantics. +`role=group` with a visible or accessible label. Buttons keep distinct names +and native disabled behaviour; the group adds no selection semantics. ## Portability @@ -128,4 +127,5 @@ Follows the shared component defaults in `spec/portability.md` (section "Shared ## Non-examples -Unlabelled controls, color-only status, drag-only operations, hidden required instructions, stolen focus or an invented service success. +Unlabelled controls, colour-only status, drag-only operations, hidden required +instructions, stolen focus or an invented service success. diff --git a/spec/components/button.md b/spec/components/button.md index ac3fbb894..37912d1ab 100644 --- a/spec/components/button.md +++ b/spec/components/button.md @@ -114,20 +114,16 @@ compact: true ## Purpose -The push button that triggers an action. Four tones and no more: `primary` -is the single filled button in a view, `secondary` is the outline for every -other action, `tertiary` is the ghost for low-emphasis and toolbar actions, -`destructive` is an outline in the danger tone that fills on hover. A -destructive button also requires a confirmation step or an undo affordance; -the colour is not the safeguard. Navigation is a link, not a button. +Triggers an action; navigation is a link. Four tones only, and one `primary` +per view; `secondary` serves every other action, `tertiary` low-emphasis and +toolbar actions. A `destructive` button also needs a confirmation step or an +undo; the colour is not the safeguard. ## Anatomy -A native `
- - -

Open GitHub composer

+ +
+ {fields.map(([name, label]) => )} +
+ + I reviewed this draft for public sharing +
+ Open GitHub composer + + +

diff --git a/site/src/components/Workbench.astro b/site/src/components/Workbench.astro index 8b55c7151..12d85a0f8 100644 --- a/site/src/components/Workbench.astro +++ b/site/src/components/Workbench.astro @@ -1,5 +1,8 @@ --- import IssueDraft from "./IssueDraft.astro"; +import SelectField from "./fields/SelectField.astro"; +import TextField from "./fields/TextField.astro"; +import Checkbox from "./fields/Checkbox.astro"; import { anchorFor } from "../../../scripts/lib/anchors.mjs"; import { renderSpecimenMarkup, stateAttributes } from "../../../scripts/lib/specimen-markup.mjs"; import { withBase } from "../lib/base"; @@ -11,40 +14,46 @@ const key = (name: string) => anchorFor.workbench(c.id, name); const colors = Object.entries(data.tokens.default).filter(([, token]: any) => token.type === "color").map(([path]) => path); ---
-

Component specification · Open isolated preview

+

Controls use maintained specimens. A forced focus ring is a visual simulation; it does not move keyboard focus. Profile previews keep their published approval status. Sample text stays in this page unless explicitly included in a shared link.

{data.revision ? `Actual build: ${data.revision}` : "Actual build: local and unpinned."} Source snapshot: {data.sourceDigest}

-

Machine contract · Report an issue without JavaScript

+

Canonical specimen

JavaScript adds the controls below; the complete specification and this specimen remain available without it.

-
- - - - - - - - {data.bindings.help && } - - - - - + + {c.variants.map((v: any) => )} + {c.states.map((state: string) => )} + {c.sizes.map((size: string) => )} + {data.profiles.map((profile: any) => )} + + + + {data.bindings.help && } + + + + {c.anatomy.map((item: any) => )} +

Live specimen

The iframe has its own viewport. Wide previews scroll inside this inspection region. Resizing is not browser zoom, device emulation, or an accessibility pass. Initial configuration is reproducible; subsequent interactions are temporary.

- + Compare the same specimen in another environment

{data.bindings.motion &&

Static motion endpoints

Default and documented hover backgrounds, available without JavaScript. Property: {data.motion.property}; duration: {data.tokens.default[data.motion.role].css} from {data.motion.role}; easing: {data.motion.easing}. Reduced motion uses instant endpoints.

{["default", "hover"].map((state) =>

{state}

`} />
)}
} diff --git a/site/src/components/fields/Checkbox.astro b/site/src/components/fields/Checkbox.astro new file mode 100644 index 000000000..e2a09172a --- /dev/null +++ b/site/src/components/fields/Checkbox.astro @@ -0,0 +1,24 @@ +--- +/* One canonical checkbox (spec/components/checkbox.md). The label is the + slot; extra attributes go to the input. `option` renders the bare option + for a checkbox group, without the field wrapper. */ +import "../../styles/components/checkbox.css"; + +interface Props { + option?: boolean; + [attribute: string]: unknown; +} + +const { option = false, class: className, ...attributes } = Astro.props; +const Wrapper = option ? Fragment : "div"; +const wrapper = option ? {} : { class: ["checkbox", className].filter(Boolean).join(" ") }; +--- + + + diff --git a/site/src/components/fields/SelectField.astro b/site/src/components/fields/SelectField.astro new file mode 100644 index 000000000..d4764a64c --- /dev/null +++ b/site/src/components/fields/SelectField.astro @@ -0,0 +1,23 @@ +--- +/* Canonical select markup (spec/components/select.md). Options are the slot; + extra attributes go to the native select, which the choice enhancement + renders (D-025). */ +import "../../styles/components/select.css"; +interface Props { + id: string; + label: string; + help?: string; + [attribute: string]: unknown; +} + +const { id, label, help, class: className, ...attributes } = Astro.props; +const describedBy = help ? `${id}-help` : undefined; +--- +
+ +
+ + +
+ {help &&

{help}

} +
diff --git a/site/src/components/fields/TextField.astro b/site/src/components/fields/TextField.astro new file mode 100644 index 000000000..e2d7a6ff0 --- /dev/null +++ b/site/src/components/fields/TextField.astro @@ -0,0 +1,27 @@ +--- +/* Canonical text-field markup (spec/components/text-field.md); a textarea + when `rows` is given (spec/components/textarea.md). Extra attributes go to + the control. */ +import "../../styles/components/text-field.css"; +import "../../styles/components/textarea.css"; +interface Props { + id: string; + label: string; + help?: string; + rows?: number; + [attribute: string]: unknown; +} + +const { id, label, help, rows, class: className, ...attributes } = Astro.props; +const kind = rows ? "textarea" : "text-field"; +const describedBy = help ? `${id}-help` : undefined; +--- +
+ +
+ {rows + ? + : } +
+ {help &&

{help}

} +
diff --git a/site/src/layouts/PortalLayout.astro b/site/src/layouts/PortalLayout.astro deleted file mode 100644 index fff2a1d1c..000000000 --- a/site/src/layouts/PortalLayout.astro +++ /dev/null @@ -1,53 +0,0 @@ ---- -import "../styles/tokens.generated.css"; -import "../styles/base.css"; -import "../styles/hex-swatches.css"; -import "../styles/portal.css"; -import "@j3w1/ui/styles/select.css"; -import "@j3w1/ui/styles/controls.css"; -import { withBase } from "../lib/base"; -import { theme } from "../lib/theme"; -import { anchorFor } from "../../../scripts/lib/anchors.mjs"; -const { title, description, density = "compact" } = Astro.props; -const navigation = [["", "Overview"], ["foundations/", "Foundations"], ["components/", "Components"], ["patterns/", "Patterns"], ["tokens/", "Tokens"], ["tools/", "Tools"], ["implement/", "Implement"], ["agents/", "For agents"], ["ports/", "Ports"], ["releases/", "Releases"]]; -const commands = [...navigation, ["demo/", "Vue application demo"], ["reference/", "Complete UI theme specification"]]; -const id = (name) => anchorFor.uiExample("portal", name); ---- - - - - - - {title} · j3w1 UI Theme Spec - - - - - - - - -
- -
-
j3w1 / {title}Vue · HTML · React · Astro
-

J3W1 / DESIGN SYSTEM

{title}

{description}

- -
-
- -
-

j3w1 / command

-
    {commands.map(([path, label]) =>
  • {path === "demo/" ? "DEMO" : "SPEC"} {label}
  • )}

-
-
-
- - - - diff --git a/site/src/layouts/SiteLayout.astro b/site/src/layouts/SiteLayout.astro new file mode 100644 index 000000000..abe9fb998 --- /dev/null +++ b/site/src/layouts/SiteLayout.astro @@ -0,0 +1,194 @@ +--- +/* The one site shell (docs/ui-architecture.md, "Site chrome"): built from the + components the site documents, at comfortable density. The rail is the + canonical sidebar-nav at 240px; below 900px it becomes the canonical + drawer. Without JavaScript the rail stays in the page above the content. */ +import "../styles/tokens.generated.css"; +import "@j3w1/ui/styles/controls.css"; +import "../styles/base.css"; +import "../styles/hex-swatches.css"; +import "../styles/components/button.css"; +import "../styles/components/link.css"; +import "../styles/components/skip-link.css"; +import "../styles/components/sidebar-nav.css"; +import "../styles/components/breadcrumbs.css"; +import "../styles/components/card.css"; +import "../styles/components/table.css"; +import "../styles/chrome.css"; +import { withBase } from "../lib/base"; +import { theme } from "../lib/theme"; +import { usageRevision } from "../lib/revision"; +import { anchorFor } from "../../../scripts/lib/anchors.mjs"; + +interface Props { + title: string; + description: string; + hero?: boolean; + breadcrumbs?: boolean; + revision?: boolean; +} + +const { title, description, hero = false, breadcrumbs = true, revision = false } = Astro.props; + +/* 16px line icons: 1.5px stroke, currentColor, no fill (spec/foundations.md, Icons). */ +const icons = { + overview: "M2.5 2.5h11v11h-11zM2.5 6.5h11", + foundations: "M2.5 10.5h11v3h-11zM4.5 6.5h7v4h-7zM6.5 2.5h3v4h-3z", + components: "M2.5 2.5h4.5v4.5h-4.5zM9 2.5h4.5v4.5H9zM2.5 9h4.5v4.5h-4.5zM9 9h4.5v4.5H9z", + patterns: "M2.5 2.5h6v6h-6zM7.5 7.5h6v6h-6z", + tokens: "M8 2.5a5.5 5.5 0 1 0 0 11a5.5 5.5 0 1 0 0-11zM8 2.5v11", + tools: "M2.5 4.5h11M2.5 11.5h11M5.5 2.5v4M10.5 9.5v4", + implement: "M6 4L2.5 8L6 12M10 4l3.5 4L10 12", + agents: "M2.5 4.5L6 8l-3.5 3.5M8 12h5.5", + ports: "M3 8h10M9 4l4 4l-4 4", + releases: "M8 2.5a5.5 5.5 0 1 0 0 11a5.5 5.5 0 1 0 0-11zM8 5v3l2 2", + reference: "M3 2.5h10v11H3zM6 2.5v11M8 5.5h3M8 8h3", +}; + +type Entry = { path: string; label: string; icon?: keyof typeof icons; children?: Entry[] }; +const navigation: Entry[] = [ + { path: "", label: "Overview", icon: "overview" }, + { path: "foundations/", label: "Foundations", icon: "foundations" }, + { path: "components/", label: "Components", icon: "components" }, + { path: "patterns/", label: "Patterns", icon: "patterns" }, + { path: "tokens/", label: "Tokens", icon: "tokens" }, + { path: "tools/", label: "Tools", icon: "tools", children: [ + { path: "workbench/", label: "Workbench" }, + { path: "builder/", label: "Form builder" }, + { path: "kit/", label: "Task kit" }, + { path: "recipes/", label: "Recipes" }, + { path: "figma/", label: "Figma bridge" }, + { path: "report/", label: "Report an issue" }, + ] }, + { path: "implement/", label: "Implement", icon: "implement" }, + { path: "agents/", label: "For agents", icon: "agents" }, + { path: "ports/", label: "Ports", icon: "ports" }, + { path: "releases/", label: "Releases", icon: "releases" }, + { path: "reference/", label: "Specification", icon: "reference" }, +]; + +const here = Astro.url.pathname.slice(withBase("").length); +const flat = navigation.flatMap((entry) => [{ ...entry, parent: null as Entry | null }, ...(entry.children ?? []).map((child) => ({ ...child, parent: entry }))]); +const section = flat.filter((entry) => entry.path && here.startsWith(entry.path)).sort((a, b) => b.path.length - a.path.length)[0]; +const trail = section ? [section.parent, section].filter((entry): entry is Entry => !!entry && entry.path !== here) : []; +const crumbs = breadcrumbs && here ? [{ path: "", label: "Overview" }, ...trail] : []; +const open = (entry: Entry) => !!entry.children?.some((child) => here.startsWith(child.path)) || here.startsWith(entry.path) && !!entry.children; +const current = (path: string) => (path === here ? "page" : undefined); + +const commands = [...flat.map(({ path, label }) => [path, label]), ["demo/", "Vue application demo"]]; +const id = (name: string) => anchorFor.uiExample("portal", name); +const canonical = new URL(Astro.url.pathname, Astro.site).href; +--- + + + + + + + + {title} · j3w1 UI Theme Spec + + + + + + + + + + + + + + +
+ + + +
+

j3w1 / theme

+ +
+ +
+
+ j3w1 / theme + {theme.version} + +
+ + +

j3w1 / command

+ + +
    + {commands.map(([path, label]) =>
  • {path === "demo/" ? "DEMO" : "SPEC"} {label}
  • )} +
+

+ +
+
+
+
+
+ +
+
+ {crumbs.length > 0 && } +
+

{title}

+

{description}

+ {revision &&

{usageRevision ? <>Source revision {usageRevision} : "Local build: source locations are relative to this checkout; no published revision is claimed."}

} +
+ +
+ +
+
+ + + + + diff --git a/site/src/layouts/ToolLayout.astro b/site/src/layouts/ToolLayout.astro deleted file mode 100644 index 557f45a09..000000000 --- a/site/src/layouts/ToolLayout.astro +++ /dev/null @@ -1,20 +0,0 @@ ---- -import "../styles/tokens.generated.css"; -import "../styles/base.css"; -import "../styles/site.css"; -import "../styles/hex-swatches.css"; -import "../styles/print.css"; -import "../styles/tools.css"; -import PortalLayout from "./PortalLayout.astro"; -import { withBase } from "../lib/base"; -import { usageRevision } from "../lib/usage"; -const { title, description } = Astro.props; ---- - -
- -

{usageRevision ? <>Source revision {usageRevision} : "Local build: source locations are relative to this checkout; no published revision is claimed."}

-
-
- -
diff --git a/site/src/pages/404.astro b/site/src/pages/404.astro index 40f7ed708..2380650b5 100644 --- a/site/src/pages/404.astro +++ b/site/src/pages/404.astro @@ -1,12 +1,7 @@ --- -import SpecLayout from "../layouts/SpecLayout.astro"; +import SiteLayout from "../layouts/SiteLayout.astro"; import { withBase } from "../lib/base"; --- - - - -
-
+ +

Start from the overview, search with Ctrl K, or open the complete reference and use its contents to find a component by anchor.

+
diff --git a/site/src/pages/agents/index.astro b/site/src/pages/agents/index.astro index 6ad848736..156e42b4e 100644 --- a/site/src/pages/agents/index.astro +++ b/site/src/pages/agents/index.astro @@ -1,27 +1,80 @@ --- -import PortalLayout from "../../layouts/PortalLayout.astro"; +import SiteLayout from "../../layouts/SiteLayout.astro"; +import SelectField from "../../components/fields/SelectField.astro"; import { withBase } from "../../lib/base"; import { theme } from "../../lib/theme"; +import { anchorFor } from "../../../../scripts/lib/anchors.mjs"; import index from "../../../../packages/ui/dist/index.json"; + const command = `j3w1-ui kit --components text-field,button,dialog --out ./vendor/j3w1/task`; +const key = (name: string) => anchorFor.uiExample("agent-kit", name); +const entryPoints = [ + ["Small discovery request", "ui/index.json", true], + ["One implementation/API", "ui/contracts/.json", false], + ["Maintained native markup", "ui/examples/.json", false], + ["Complete copy files and digests", "ui/copy//manifest.json", false], + ["Canonical meaning and eligibility", "exports/components/.json", false], + ["All implementation metadata", "ui/manifest.json", true], +] as const; --- - - -
+ + +

Prepare an agent kit

Select the components your task needs. The installed CLI includes their complete dependency closure, canonical contracts, eligibility disclosures and shared rules.

-
-
- -

Click an entry to toggle it. Use arrow keys to move, Space to select, Shift with arrows for a range, or Ctrl/Command+A to select all. The list uses j3w1 selection colors.

-
+ +
+ + + + + + +
+ + {index.components.map(({ id, name }) => )} + +
+ + +
-
{command}

+
{command}
+

-

A bounded consumption workflow

  1. Pin one release, currently {theme.version}, and record the artifact digest.
  2. Read the canonical consumption contract and compact implementation index.
  3. Select component IDs. Read only their canonical JSON, implementation contract and maintained examples, plus shared accessibility and eligibility rules.
  4. Prefer package mode in compatible web apps. Use complete copy bundles when source ownership is needed. Use the existing mapping workflow for incompatible/native hosts.
  5. Integrate the native markup, CSS and registration closure; bind your application data and actions.
  6. Verify your real form, keyboard, focus and lifecycle behavior. Record actual results separately from implementation availability.
-

Prepare a copy task

{command}

Use the installed binary from the exact package or release tarball. The output contains all selected component closures and refuses to overwrite application files. Full installation and framework guide →

-

Machine entry points

NeedArtifact
Small discovery requestui/index.json
One implementation/APIui/contracts/<id>.json
Maintained native markupui/examples/<id>.json
Complete copy files and digestsui/copy/<id>/manifest.json
Canonical meaning and eligibilityexports/components/<id>.json
All implementation metadataui/manifest.json
-

Site URLs help humans explore the current release. For reproducible agent fetches, use the matching immutable release tag and its published digests. Never combine current-site examples with a different installed version.

Mapping compatibility

The existing canonical task kit, lock format and portability disclosures remain available. An official package dependency is recorded alongside that integration evidence; it does not pretend to be a newly verified native port.

- +
+

A bounded consumption workflow

+
    +
  1. Pin one release, currently {theme.version}, and record the artifact digest.
  2. +
  3. Read the canonical consumption contract and compact implementation index.
  4. +
  5. Select component IDs. Read only their canonical JSON, implementation contract and maintained examples, plus shared accessibility and eligibility rules.
  6. +
  7. Prefer package mode in compatible web apps. Use complete copy bundles when source ownership is needed. Use the existing mapping workflow for incompatible/native hosts.
  8. +
  9. Integrate the native markup, CSS and registration closure; bind your application data and actions.
  10. +
  11. Verify your real form, keyboard, focus and lifecycle behavior. Record actual results separately from implementation availability.
  12. +
+

Prepare a copy task

+
{command}
+

Use the installed binary from the exact package or release tarball. The output contains all selected component closures and refuses to overwrite application files. Full installation and framework guide →

+

Machine entry points

+
+ + + + {entryPoints.map(([need, path, linked]) => + + + )} + +
NeedArtifact
{need}{linked ? {path} : {path}}
+
+

Site URLs help humans explore the current release. For reproducible agent fetches, use the matching immutable release tag and its published digests. Never combine current-site examples with a different installed version.

+

Mapping compatibility

+

The existing canonical task kit, lock format and portability disclosures remain available. An official package dependency is recorded alongside that integration evidence; it does not pretend to be a newly verified native port.

+
+
diff --git a/site/src/pages/builder/index.astro b/site/src/pages/builder/index.astro index 107ad0255..075e1a00f 100644 --- a/site/src/pages/builder/index.astro +++ b/site/src/pages/builder/index.astro @@ -1,5 +1,5 @@ --- -import ToolLayout from "../../layouts/ToolLayout.astro"; +import SiteLayout from "../../layouts/SiteLayout.astro"; import { builderMarkup } from "../../../../packages/ui/src/examples/form-markup.mjs"; import templateExport from "../../../../exports/forms/templates.json"; import "../../styles/form-tools.css"; @@ -8,13 +8,28 @@ import { withBase } from "../../lib/base"; import { anchorFor } from "../../../../scripts/lib/anchors.mjs"; import { renderFields } from "../../../../scripts/lib/form-fields.mjs"; const templates = templateExport.templates; -const sampleFields = ["text", "textarea", "select", "checkbox", "radio"].map(type => ({ id: type, type, label: `Example ${type}`, help: "Static canonical field; no submission.", required: false, options: ["select", "radio"].includes(type) ? [{ id: "one", label: "First option" }, { id: "two", label: "Second option" }] : [] })); +const sampleFields = ["text", "textarea", "select", "checkbox", "radio"].map((type) => ({ + id: type, + type, + label: `Example ${type}`, + help: "Static canonical field; no submission.", + required: false, + options: ["select", "radio"].includes(type) ? [{ id: "one", label: "First option" }, { id: "two", label: "Second option" }] : [], +})); --- - +

Draft reference under proposed D-021. Definitions stay in memory. Import validates every field and the theme content identity before replacing your form. Definition changes clear preview values and errors; Download definition excludes entered values.

-

Component contract · Validation and recovery · Required theme content identity

+
-

Without JavaScript

The editor requires JavaScript. The definition format and representative fields remain readable here. A text field has a stable ID, label, help and required flag. A select or radio field also has stable option IDs and labels. Checkboxes hold a boolean preview value. No preview values belong in an exported definition.

Download the static component contract. Existing text-field, textarea, select, checkbox and radio-group rules remain authoritative. This is not a production backend or native port.

+
+

Without JavaScript

+

The editor requires JavaScript. The definition format and representative fields remain readable here. A text field has a stable ID, label, help and required flag. A select or radio field also has stable option IDs and labels. Checkboxes hold a boolean preview value. No preview values belong in an exported definition.

+

Download the static component contract. Existing text-field, textarea, select, checkbox and radio-group rules remain authoritative. This is not a production backend or native port.

+
- + diff --git a/site/src/pages/components/[id].astro b/site/src/pages/components/[id].astro index 7f69f1f5a..e9fa8376d 100644 --- a/site/src/pages/components/[id].astro +++ b/site/src/pages/components/[id].astro @@ -1,29 +1,86 @@ --- import { getCollection, render } from "astro:content"; -import PortalLayout from "../../layouts/PortalLayout.astro"; +import SiteLayout from "../../layouts/SiteLayout.astro"; import { withBase } from "../../lib/base"; import { anchorFor } from "../../../../scripts/lib/anchors.mjs"; import implementations from "../../../../packages/ui/dist/manifest.json"; import examples from "../../../../packages/ui/dist/examples.json"; -export async function getStaticPaths() { return (await getCollection("components")).map(entry => ({ params: { id: entry.id }, props: { entry } })); } + +export async function getStaticPaths() { + return (await getCollection("components")).map((entry) => ({ params: { id: entry.id }, props: { entry } })); +} + const { entry } = Astro.props; -const id = entry.id, item = implementations.components.find(c => c.id === id)!; +const id = entry.id; +const item = implementations.components.find((c) => c.id === id)!; const { Content } = await render(entry); const variants = examples[id]; const imports = `import '@j3w1/ui/tokens.css';\nimport '@j3w1/ui/styles/${id}.css';\nimport '@j3w1/ui/register/${id}';`; const install = `npm install --save-exact @j3w1/ui@${item.version}`; const copy = `npx --package=@j3w1/ui@${item.version} j3w1-ui copy ${id} --out ./vendor/j3w1/${id}`; +const links = [ + [`ui/copy/${id}/index.html`, "Standalone example ↗"], + [`ui/copy/${id}/manifest.json`, "Copy file manifest"], + [`exports/components/${id}.json`, "Canonical JSON"], + [`demo/#/components/${id}`, "Vue gallery ↗"], + [`agents/?component=${id}`, "Prepare an agent kit →"], +]; --- - + -

{entry.data.maturity} · LIGHT DOM · {item.version}

-

{item.domReason} {id === "form-builder" && "The bounded form-builder contract remains draft; D-021 has not been promoted."}

- -

Live variants

{Object.entries(variants).map(([variant, markup]) =>

{variant}

{markup}
)}
-

Install and register

Use the exact version. If npm publication is pending, install the release tarball from the installation guide.

{install}
{imports}

Insert the maintained markup above after loading these imports. Its native children provide accessible names and form behavior; the empty custom tag alone does not create a control.

Vue SFC, React, Astro and plain HTML integration →

-

Copy the complete implementation

{copy}

The CLI verifies every file before writing and refuses overwrites. Serve the output over HTTP and open index.html. Keep its modules, CSS, tokens and licence notices together.

-

Public API

{["attributes", "properties", "methods", "events"].map(kind => <>

{kind}

{(item.api[kind] ?? []).map(row => )}
NameType / signatureMeaning
{row.name}{row.type ?? row.signature ?? "CustomEvent"}{row.description ?? row.detail ?? "See the canonical interaction contract below."}{row.readonly && " Read only."}
)}
-

Dependencies and verification

Registered components: {item.dependencies.length ? item.dependencies.join(", ") : "none"}. Style dependencies: {item.styleDependencies.length ? item.styleDependencies.join(", ") : "none"}.

Package presence establishes an available implementation. Actual passes depend on the tested artifact and environment. Read specification execution evidence; read packed-consumer evidence; inspect the complete state matrix.

Full implementation manifest, API and token dependency closure

-

Canonical specification

+

{entry.data.maturity} · light DOM · {item.version}. {item.domReason} {id === "form-builder" && "The bounded form-builder contract remains draft; D-021 has not been promoted."}

+
+ {links.map(([path, label]) => {label})} +
+
+

Live variants

+ {Object.entries(variants).map(([variant, markup]) =>
+

{variant}

+
+
+
{markup}
+
)} +
+
+

Install and register

+

Use the exact version. If npm publication is pending, install the release tarball from the installation guide.

+
{install}
+
{imports}
+

Insert the maintained markup above after loading these imports. Its native children provide accessible names and form behavior; the empty custom tag alone does not create a control.

+

Vue SFC, React, Astro and plain HTML integration →

+
+
+

Copy the complete implementation

+
{copy}
+

The CLI verifies every file before writing and refuses overwrites. Serve the output over HTTP and open index.html. Keep its modules, CSS, tokens and licence notices together.

+
+
+

Public API

+ {["attributes", "properties", "methods", "events"].map((kind) => <> +

{kind}

+
+ + + + {(item.api[kind] ?? []).map((row) => + + + + )} + +
NameType / signatureMeaning
{row.name}{row.type ?? row.signature ?? "CustomEvent"}{row.description ?? row.detail ?? "See the canonical interaction contract below."}{row.readonly && " Read only."}
+
+ )} +
+
+

Dependencies and verification

+

Registered components: {item.dependencies.length ? item.dependencies.join(", ") : "none"}. Style dependencies: {item.styleDependencies.length ? item.styleDependencies.join(", ") : "none"}.

+

Package presence establishes an available implementation. Actual passes depend on the tested artifact and environment. Read specification execution evidence; read packed-consumer evidence; inspect the complete state matrix.

+

Full implementation manifest, API and token dependency closure

+
+
+

Canonical specification

+ +
-
+ diff --git a/site/src/pages/components/index.astro b/site/src/pages/components/index.astro index b2de6187f..cf36158ff 100644 --- a/site/src/pages/components/index.astro +++ b/site/src/pages/components/index.astro @@ -1,10 +1,20 @@ --- -import PortalLayout from "../../layouts/PortalLayout.astro"; -import { withBase } from "../../lib/base"; import { getCollection } from "astro:content"; +import SiteLayout from "../../layouts/SiteLayout.astro"; +import { withBase } from "../../lib/base"; import families from "../../../../spec/families.json"; -const components = (await getCollection("components")).sort((a,b) => a.data.order - b.data.order); + +const components = (await getCollection("components")).sort((a, b) => a.data.order - b.data.order); --- - - {families.filter(f => components.some(c => c.data.family === f.id)).map(family =>

{family.title}

{components.filter(c => c.data.family === family.id).map(c =>

{c.data.maturity} / {c.id}

{c.data.name} →

{c.data.summary}

)}
)} -
+ + {families.filter((f) => components.some((c) => c.data.family === f.id)).map((family) =>
+

{family.title}

+
+ {components.filter((c) => c.data.family === family.id).map((c) => + {c.data.name} → + {c.data.summary} + {c.data.maturity} · {c.id} + )} +
+
)} +
diff --git a/site/src/pages/figma/index.astro b/site/src/pages/figma/index.astro index a48125128..c80e76199 100644 --- a/site/src/pages/figma/index.astro +++ b/site/src/pages/figma/index.astro @@ -1,12 +1,18 @@ --- -import ToolLayout from "../../layouts/ToolLayout.astro"; import { getCollection, render } from "astro:content"; +import SiteLayout from "../../layouts/SiteLayout.astro"; import { withBase } from "../../lib/base"; -const entry = (await getCollection("docs")).find(item => item.data.id === "figma-bridge"); + +const entry = (await getCollection("docs")).find((item) => item.data.id === "figma-bridge"); const { Content } = await render(entry); --- - -

Download the actual Variables adapter · Import verification evidence

-

Mapping, operation and evidence

- -
+ + +
+

Mapping, operation and evidence

+ +
+
diff --git a/site/src/pages/foundations/index.astro b/site/src/pages/foundations/index.astro index 67d1be2b3..a09494cd7 100644 --- a/site/src/pages/foundations/index.astro +++ b/site/src/pages/foundations/index.astro @@ -1,7 +1,12 @@ --- import { getCollection } from "astro:content"; -import PortalLayout from "../../layouts/PortalLayout.astro"; +import SiteLayout from "../../layouts/SiteLayout.astro"; import DocSection from "../../components/DocSection.astro"; + const docs = await getCollection("docs"); --- -
{["identity", "foundations", "accessibility"].map(id => doc.data.id === id)} />)}
+ +
+ {["identity", "foundations", "accessibility"].map((id) => doc.data.id === id)} />)} +
+
diff --git a/site/src/pages/implement/index.astro b/site/src/pages/implement/index.astro index deedd111b..3c2f458e8 100644 --- a/site/src/pages/implement/index.astro +++ b/site/src/pages/implement/index.astro @@ -1,12 +1,29 @@ --- -import PortalLayout from "../../layouts/PortalLayout.astro"; +import SiteLayout from "../../layouts/SiteLayout.astro"; import Guide from "../../../../docs/ui-consumption.md"; import { withBase } from "../../lib/base"; import { theme } from "../../lib/theme"; import { consumerExamples } from "../../../../scripts/lib/ui-consumer-examples.mjs"; + const files = await consumerExamples(); const frameworkFiles = ["html/index.html", "html/main.js", "vue/App.vue", "vue/main.js", "vite.config.js", "react/main.js", "astro/src/pages/index.astro", "astro.config.mjs"]; --- -
-

Maintained framework examples

These exact source files are compiled and exercised against the packed artifact in isolated HTML, Vue, React and Astro fixtures. They demonstrate native submission, validation, reset and disabled fieldsets. Use the component pages for the native markup and API of other controls.

{frameworkFiles.map(file =>

{file}

Download source

{files.get(file)}
)}
-
+ + +
+
+

Maintained framework examples

+

These exact source files are compiled and exercised against the packed artifact in isolated HTML, Vue, React and Astro fixtures. They demonstrate native submission, validation, reset and disabled fieldsets. Use the component pages for the native markup and API of other controls.

+ {frameworkFiles.map((file) =>
+

{file}

+
+ Download source + +
+
{files.get(file)}
+
)} +
+
diff --git a/site/src/pages/index.astro b/site/src/pages/index.astro index f1df47fc2..644a33b5f 100644 --- a/site/src/pages/index.astro +++ b/site/src/pages/index.astro @@ -1,15 +1,55 @@ --- -import PortalLayout from "../layouts/PortalLayout.astro"; +import SiteLayout from "../layouts/SiteLayout.astro"; import { withBase } from "../lib/base"; -import { defaultTokens, theme } from "../lib/theme"; +import { cssVar, defaultTokens, theme } from "../lib/theme"; import inventory from "../../../spec/inventory.json"; + const roles = ["color.surface.canvas", "color.surface.chrome", "color.surface.default", "color.text.default", "color.text.bright", "color.action.primary.bg"]; +const metrics = [ + ["Canonical foundation", theme.version, "Versioned tokens, contracts and migration guidance."], + ["Consumable inventory", inventory.components.length, "Elements, components and application compositions."], + ["Integration routes", "03", "Install a package. Copy complete source. Map to your host."], +]; +const routes = [ + ["components/", "Build with native semantics →", "Typed properties, native forms, keyboard behavior, live variants and complete dependency lists."], + ["demo/", "See the system at work ↗", "A Vue workspace with dashboards, records, productivity tools and realistic local workflows."], + ["agents/", "Give your agent the exact inputs →", "Pinned machine contracts, per-component imports and verified copy bundles. No screenshot interpretation required."], + ["reference/", "Read the complete specification →", "Every normative document, token, state matrix, accessibility rule and decision in one static reference."], +]; --- - - -

CANONICAL FOUNDATION

{theme.version}

Versioned tokens, contracts and migration guidance.

CONSUMABLE INVENTORY

{inventory.components.length}

Elements, components and application compositions.

INTEGRATION ROUTES

03

Install a package. Copy complete source. Map to your host.

-

The foundation, in exact values.

{roles.map(role =>
{defaultTokens[role].css}

{role.replace("color.", "")}

)}

Typography, spacing, density and accessibility rules →

-

From a single control to a complete application.

{[["components/", "Build with native semantics", "Typed properties, native forms, keyboard behavior, live variants and complete dependency lists."], ["demo/", "See the system at work", "A Vue workspace with dashboards, records, productivity tools and realistic local workflows."], ["agents/", "Give your agent the exact inputs", "Pinned machine contracts, per-component imports and verified copy bundles. No screenshot interpretation required."], ["reference/", "Read the complete specification", "Every normative document, token, state matrix, accessibility rule and decision in one static reference."]].map(([url, title, text]) =>

{title} ↗

{text}

)}
-

Looking for an older bookmark? The full reference preserves existing anchors. Visits to a legacy homepage hash go there automatically when JavaScript is available.

+ + +
+ {metrics.map(([label, value, text]) =>
+

{label}

+ {value} +

{text}

+
)} +
+
+

The foundation, in exact values

+
+ {roles.map((role) =>
+
+ {defaultTokens[role].css} +

{role.replace("color.", "")}

+
)} +
+ +
+
+

From a single control to a complete application

+
+ {routes.map(([url, title, text]) => + {title} + {text} + )} +
+
+

Looking for an older bookmark? The full reference preserves existing anchors. Visits to a legacy homepage hash go there automatically when JavaScript is available.

-
+ diff --git a/site/src/pages/kit/index.astro b/site/src/pages/kit/index.astro index 3143116dc..f5dd38f04 100644 --- a/site/src/pages/kit/index.astro +++ b/site/src/pages/kit/index.astro @@ -1,6 +1,9 @@ --- import { execFileSync } from "node:child_process"; -import ToolLayout from "../../layouts/ToolLayout.astro"; +import SiteLayout from "../../layouts/SiteLayout.astro"; +import TextField from "../../components/fields/TextField.astro"; +import SelectField from "../../components/fields/SelectField.astro"; +import Checkbox from "../../components/fields/Checkbox.astro"; import { withBase } from "../../lib/base"; import { usageRevision } from "../../lib/usage"; import { anchorFor } from "../../../../scripts/lib/anchors.mjs"; @@ -14,39 +17,56 @@ if (usageRevision) { source = { revision: usageRevision, resolvedAt: new Date(seconds * 1000).toISOString() }; } --- - +

The kit contains selected specifications, shared rules, required tokens, source digests, a lock file and a bounded task prompt. Task text stays in this page; generation needs no account or model service.

Standard includes available recipes. Minimal omits only optional recipes; both retain all required contracts and rules. The legacy single-component --strict reconstruction command remains separate.

{!source &&

This local build has no committed source pin. Commit generated inputs and build with GITHUB_SHA set to that full commit to enable packaging, or use the CLI at a committed revision.

} - -
-
Component selection -

-
{Object.entries(index.components).map(([id, entry]) => )}
+ + +
+ Component selection +
+ + +
+
+ {Object.entries(index.components).map(([id, entry]) => {entry.title})} +
- -

+Admin form · j3w1

Project details

Review the local values before passing them to your app.

Project information

diff --git a/packages/ui/dist/copy/admin-form/manifest.json b/packages/ui/dist/copy/admin-form/manifest.json index c193389a4..11e60154b 100644 --- a/packages/ui/dist/copy/admin-form/manifest.json +++ b/packages/ui/dist/copy/admin-form/manifest.json @@ -30,11 +30,11 @@ "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=", - "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", + "tokens.css": "sha256-7A9Xv87HbmuVumnQtzllDxHGc2CPnurdpWWuBpEStJg=", "component.css": "sha256-Of5oLJY6n5Yfqu44/xCAuuJEYRoCg4Kr+YZbVggbwZE=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-TRLraonRxggrZcfXS9jlN+nTIOpRHiXbMKQNm8NbR2A=", - "index.html": "sha256-HsmeIqneb7G9ZHVJEuzAqXdP7AYU8OlzG8Rs70uYyBQ=", + "index.html": "sha256-fCyv1GPEoas5phPBo4T3EhrTQ5U3/15ks0AZJQawjDc=", "README.md": "sha256-bid+/EA6npftuo0cAZQP6rg+96qu7gNC4h/Klx23PF0=" } } diff --git a/packages/ui/dist/copy/admin-form/tokens.css b/packages/ui/dist/copy/admin-form/tokens.css index b7acac46b..ff49a74ad 100644 --- a/packages/ui/dist/copy/admin-form/tokens.css +++ b/packages/ui/dist/copy/admin-form/tokens.css @@ -360,7 +360,7 @@ --z-toast: 40; --z-skip-link: 1000; } -[data-density="compact"] { +:root, [data-density="compact"] { --density-control-height: 24px; --density-row-height: 28px; --density-control-padding-x: 8px; diff --git a/packages/ui/dist/copy/alert/index.html b/packages/ui/dist/copy/alert/index.html index ee1cadfec..6e4f82dea 100644 --- a/packages/ui/dist/copy/alert/index.html +++ b/packages/ui/dist/copy/alert/index.html @@ -1,5 +1,5 @@ -Alert · j3w1
+File browser · j3w1
  • All files
  • Source
Local file examples
NameKindSize
Vue component4 KB
Documentation2 KB

2 files

diff --git a/packages/ui/dist/copy/file-browser/manifest.json b/packages/ui/dist/copy/file-browser/manifest.json index 95fe580b9..8da4f057d 100644 --- a/packages/ui/dist/copy/file-browser/manifest.json +++ b/packages/ui/dist/copy/file-browser/manifest.json @@ -26,11 +26,11 @@ "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=", - "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", + "tokens.css": "sha256-7A9Xv87HbmuVumnQtzllDxHGc2CPnurdpWWuBpEStJg=", "component.css": "sha256-jXsUncF3ZqNTAY54eALB2XHlOFiiumSXp+AnM14Tz1Q=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-TbSmPr7cV31g3WqgPi6LboOGQdmgxz/89Tf/3ld2pfU=", - "index.html": "sha256-68VZEF9M4ZFNgI9IZ7yrpktM4/9dA+GR/D6aTo6ocn0=", + "index.html": "sha256-ghy6Hidly07DbSb9oIl+42dgKaIRi5V0gVlW8uwsoYs=", "README.md": "sha256-pldg7PuzlPHL6J8L3tFRBhM4Mqi8AlcED3V2DXOXZRU=" } } diff --git a/packages/ui/dist/copy/file-browser/tokens.css b/packages/ui/dist/copy/file-browser/tokens.css index b7acac46b..ff49a74ad 100644 --- a/packages/ui/dist/copy/file-browser/tokens.css +++ b/packages/ui/dist/copy/file-browser/tokens.css @@ -360,7 +360,7 @@ --z-toast: 40; --z-skip-link: 1000; } -[data-density="compact"] { +:root, [data-density="compact"] { --density-control-height: 24px; --density-row-height: 28px; --density-control-padding-x: 8px; diff --git a/packages/ui/dist/copy/file-input/index.html b/packages/ui/dist/copy/file-input/index.html index a24e5b377..fa847e818 100644 --- a/packages/ui/dist/copy/file-input/index.html +++ b/packages/ui/dist/copy/file-input/index.html @@ -1,5 +1,5 @@ -File input · j3w1
+File input · j3w1
diff --git a/packages/ui/dist/copy/file-input/manifest.json b/packages/ui/dist/copy/file-input/manifest.json index cb7afba97..4c81efeb5 100644 --- a/packages/ui/dist/copy/file-input/manifest.json +++ b/packages/ui/dist/copy/file-input/manifest.json @@ -16,11 +16,11 @@ "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=", - "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", + "tokens.css": "sha256-7A9Xv87HbmuVumnQtzllDxHGc2CPnurdpWWuBpEStJg=", "component.css": "sha256-ezg9wydBGR6KpQziZgvoKiTXURNTPkh+aD9h3vFuuW4=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-3MysNuXXyX6HzlWv0wFhnto4CU9Q/n0JHK2wx1ufwbE=", - "index.html": "sha256-fBkoQQjmYl2pS2ZhIJZ6zX3QXl6l6HTDfKsrsy4jmb8=", + "index.html": "sha256-Mruf4SRnwaZ2RK7LaKRse5q9c4QKhDHgEgCAG4hyL7s=", "README.md": "sha256-fT5UasqXVH/Um8vNgVGEXNG0Pk7WZ4Aq+K44FBlAdpk=" } } diff --git a/packages/ui/dist/copy/file-input/tokens.css b/packages/ui/dist/copy/file-input/tokens.css index b7acac46b..ff49a74ad 100644 --- a/packages/ui/dist/copy/file-input/tokens.css +++ b/packages/ui/dist/copy/file-input/tokens.css @@ -360,7 +360,7 @@ --z-toast: 40; --z-skip-link: 1000; } -[data-density="compact"] { +:root, [data-density="compact"] { --density-control-height: 24px; --density-row-height: 28px; --density-control-padding-x: 8px; diff --git a/packages/ui/dist/copy/filterable-table/index.html b/packages/ui/dist/copy/filterable-table/index.html index e2c584101..0a513c1d0 100644 --- a/packages/ui/dist/copy/filterable-table/index.html +++ b/packages/ui/dist/copy/filterable-table/index.html @@ -1,2 +1,2 @@ -Filterable table · j3w1
Project records · synthetic fixture
Atlas libraryAvery KimReady24
Orion workspaceJordan LeeIn progress12
Field notesMorgan NoorReady38
Signal monitorRiley StoneReview6

+Filterable table · j3w1
Project records · synthetic fixture
Atlas libraryAvery KimReady24
Orion workspaceJordan LeeIn progress12
Field notesMorgan NoorReady38
Signal monitorRiley StoneReview6

diff --git a/packages/ui/dist/copy/filterable-table/manifest.json b/packages/ui/dist/copy/filterable-table/manifest.json index eccd1560f..45ad7d006 100644 --- a/packages/ui/dist/copy/filterable-table/manifest.json +++ b/packages/ui/dist/copy/filterable-table/manifest.json @@ -22,11 +22,11 @@ "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=", - "tokens.css": "sha256-ATbK8VSmfG5bBZGy+4CWrV8kyfaHrk3f4wtV/sI2Vdw=", + "tokens.css": "sha256-7A9Xv87HbmuVumnQtzllDxHGc2CPnurdpWWuBpEStJg=", "component.css": "sha256-ZpN1xEJy4fV/PBDvH91mkuN2CZqhCUo5wpeCs27jREo=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-3PbF9wWtnKy3q07M9x690D730biEbSwu20wHAcvPPEE=", - "index.html": "sha256-61p1J3mpIgWTPXP4+wTHI0p/MffdvGq+yeT7j0urEZA=", + "index.html": "sha256-L9dRgFL5Tl9EFw9DuTPQaPstK4H0R/A/bzroaL7tvHk=", "README.md": "sha256-eYSWLSbTgjyr+5CUJR+E3qhY267Qh6rmF+5P40UanuU=" } } diff --git a/packages/ui/dist/copy/filterable-table/tokens.css b/packages/ui/dist/copy/filterable-table/tokens.css index b7acac46b..ff49a74ad 100644 --- a/packages/ui/dist/copy/filterable-table/tokens.css +++ b/packages/ui/dist/copy/filterable-table/tokens.css @@ -360,7 +360,7 @@ --z-toast: 40; --z-skip-link: 1000; } -[data-density="compact"] { +:root, [data-density="compact"] { --density-control-height: 24px; --density-row-height: 28px; --density-control-padding-x: 8px; diff --git a/packages/ui/dist/copy/form-builder/index.html b/packages/ui/dist/copy/form-builder/index.html index bba366e68..4a3146923 100644 --- a/packages/ui/dist/copy/form-builder/index.html +++ b/packages/ui/dist/copy/form-builder/index.html @@ -1,5 +1,5 @@ -Form builder · j3w1

Install and register

Use the exact version. If npm publication is pending, install the release tarball from the installation guide.

-
{install}
-
{imports}
+
{install}
+
{imports}

Insert the maintained markup above after loading these imports. Its native children provide accessible names and form behavior; the empty custom tag alone does not create a control.

Vue SFC, React, Astro and plain HTML integration →

Copy the complete implementation

-
{copy}
+
{copy}

The CLI verifies every file before writing and refuses overwrites. Serve the output over HTTP and open index.html. Keep its modules, CSS, tokens and licence notices together.

Public API

{["attributes", "properties", "methods", "events"].map((kind) => <>

{kind}

-
+
diff --git a/site/src/styles/components/code-editor.css b/site/src/styles/components/code-editor.css index 6074358d3..3818206f4 100644 --- a/site/src/styles/components/code-editor.css +++ b/site/src/styles/components/code-editor.css @@ -66,6 +66,10 @@ color: var(--color-code-whitespace); } +.code-editor-ws::before { + content: attr(data-whitespace); +} + .code-editor-fold { display: inline-block; padding: 0 var(--space-4); diff --git a/tests/browser/page.spec.js b/tests/browser/page.spec.js index 48ec6b587..6b2373735 100644 --- a/tests/browser/page.spec.js +++ b/tests/browser/page.spec.js @@ -6,6 +6,9 @@ import { promises as fs } from "node:fs"; import { openSpec, only, rgbToHex } from "./helpers.mjs"; +const referenceInventory = JSON.parse(await fs.readFile("spec/inventory.json", "utf8")); +const referenceRoutes = ["reference/", ...referenceInventory.components.map(({ id }) => `components/${id}/`), "reference/contrast/", "reference/decisions/", "reference/fixtures/", "tokens/"]; + /* The page's own selects are themed, so the native control is hidden and the visible combobox is what a reader operates. Driven by keyboard: it is a real user path, and it does not depend on a control handle staying valid across @@ -84,10 +87,8 @@ test.describe("the specification page", () => { const all = await tagRules(page); expect(all).toContain("color-contrast"); const rules = all.filter(pick); - const inventory = JSON.parse(await fs.readFile("spec/inventory.json", "utf8")); - const routes = ["reference/", ...inventory.components.map(({ id }) => `components/${id}/`), "reference/contrast/", "reference/decisions/", "reference/fixtures/", "tokens/"]; await fs.mkdir("test-results", { recursive: true }); - for (const route of routes) { + for (const route of referenceRoutes) { if (route !== "reference/") await page.goto(route, { waitUntil: "networkidle" }); // The former reference displayed every profile together. Scan all of // those static tables, including the profiles the explorer filters. @@ -106,28 +107,34 @@ test.describe("the specification page", () => { test("reflow: no horizontal page scroll at 360px and at 200% text zoom", verification({component: "page", category: "reflow", states: [], variants: [], note: "Only the assertions in this named test; no comprehensive state or variant coverage claim. Profile and density record the initial configuration; any switches are described by the test."}), async ({ page }, testInfo) => { test.skip(!only(testInfo, "narrow", "zoom200"), "reflow projects only"); + test.setTimeout(180_000); // Complete the split reference; each navigation retains its own timeout. await openSpec(page); - const overflow = await page.evaluate(() => document.documentElement.scrollWidth - document.documentElement.clientWidth); - expect(overflow).toBeLessThanOrEqual(0); - await page.evaluate(() => { - document.documentElement.style.fontSize = "200%"; - }); - await page.waitForTimeout(50); - const zoomed = await page.evaluate(() => document.documentElement.scrollWidth - document.documentElement.clientWidth); - expect(zoomed).toBeLessThanOrEqual(0); + for (const route of referenceRoutes) { + if (route !== "reference/") await page.goto(route, { waitUntil: "networkidle" }); + const overflow = await page.evaluate(() => document.documentElement.scrollWidth - document.documentElement.clientWidth); + expect(overflow, route).toBeLessThanOrEqual(0); + await page.evaluate(() => { document.documentElement.style.fontSize = "200%"; }); + await page.waitForTimeout(50); + const zoomed = await page.evaluate(() => document.documentElement.scrollWidth - document.documentElement.clientWidth); + expect(zoomed, route).toBeLessThanOrEqual(0); + } }); test("reduced motion: every transition and animation is effectively instant", verification({component: "page", category: "motion", states: [], variants: [], note: "Only the assertions in this named test; no comprehensive state or variant coverage claim. Profile and density record the initial configuration; any switches are described by the test."}), async ({ page }, testInfo) => { test.skip(!only(testInfo, "desktop"), "one check is enough"); await page.emulateMedia({ reducedMotion: "reduce" }); + test.setTimeout(180_000); // Every moved component and document is still covered. await openSpec(page); - const slow = await page.evaluate(() => - [...document.querySelectorAll("main *")] - .map((el) => getComputedStyle(el)) - .filter((s) => s.transitionDuration.split(",").some((d) => parseFloat(d) > 0.01) || s.animationDuration.split(",").some((d) => parseFloat(d) > 0.01)) - .length, - ); - expect(slow).toBe(0); + for (const route of referenceRoutes) { + if (route !== "reference/") await page.goto(route, { waitUntil: "networkidle" }); + const slow = await page.evaluate(() => + [...document.querySelectorAll("main *")] + .map((el) => getComputedStyle(el)) + .filter((s) => s.transitionDuration.split(",").some((d) => parseFloat(d) > 0.01) || s.animationDuration.split(",").some((d) => parseFloat(d) > 0.01)) + .length, + ); + expect(slow, route).toBe(0); + } }); test("enhancements: search narrows the contents, family filter hides sections, density and profile persist, reset clears", verification({component: "page", category: "enhancements", states: [], variants: [], note: "Only the assertions in this named test; no comprehensive state or variant coverage claim. Profile and density record the initial configuration; any switches are described by the test."}), async ({ page }, testInfo) => { diff --git a/tests/browser/reference-hub.spec.js b/tests/browser/reference-hub.spec.js index fa2ff9e17..3ae82fa3c 100644 --- a/tests/browser/reference-hub.spec.js +++ b/tests/browser/reference-hub.spec.js @@ -80,3 +80,18 @@ test("matrix forcing stays scoped and chrome stays compact when specimens change await expect(page.locator("html")).toHaveAttribute("data-density", "compact"); await expect(page.locator("#button-states")).toHaveAttribute("data-density", "comfortable"); }); + +test("code-editor package and matrix render the same decorative whitespace glyphs", scope, async ({ page }) => { + await page.goto("components/code-editor/"); + const shape = (locator) => locator.evaluate((el) => { + const style = getComputedStyle(el, "::before"), rect = el.getBoundingClientRect(); + return { glyphs: style.content, color: style.color, width: rect.width, height: rect.height, text: el.textContent }; + }); + const live = page.locator("j3w1-code-editor .code-editor-ws").first(); + const matrix = page.locator('#code-editor-states [data-state="default"] .code-editor-ws').first(); + const specimen = await shape(live); + expect(specimen.text).toBe(""); + expect(specimen.glyphs).toBe('"··"'); + expect(specimen.width).toBeGreaterThan(0); + expect(await shape(matrix)).toEqual(specimen); +}); diff --git a/tests/site-source.test.js b/tests/site-source.test.js index 2e3ecabfc..d3ef1cd4f 100644 --- a/tests/site-source.test.js +++ b/tests/site-source.test.js @@ -65,3 +65,10 @@ test("demonstration fragments resolve locally while historical records and stric assert.doesNotMatch(historical, /id="demo-record"/); assert.throws(() => namespaceMarkup(parseFragment(''), (id) => id), /Unresolved markup ID reference/); }); + +test("code-editor whitespace remains decorative while historical bytes stay exact", async () => { + const { renderSpecimenMarkup } = await import("../scripts/lib/specimen-markup.mjs"); + const source = ''; + assert.equal(renderSpecimenMarkup(source, "graphic"), ''); + assert.equal(renderSpecimenMarkup(source, "record", { decorations: false }), source); +}); From 86e527af9c305d70932fd68ee66f0f29f37e0be4 Mon Sep 17 00:00:00 2001 From: j3w1 Date: Wed, 14 Oct 2026 17:45:37 -0500 Subject: [PATCH 54/65] chore: regenerate Co-Authored-By: Claude Opus 5.5 --- exports/digests.json | 16 ++++++++-------- exports/recipes/button/README.md | 2 +- exports/recipes/button/manifest.json | 6 +++--- exports/recipes/dialog/README.md | 2 +- exports/recipes/dialog/manifest.json | 6 +++--- exports/recipes/index.json | 6 +++--- exports/recipes/text-field/README.md | 2 +- exports/recipes/text-field/manifest.json | 6 +++--- exports/task-inputs.json | 12 ++++++------ packages/ui/dist/contracts/code-editor.json | 2 +- packages/ui/dist/contracts/i3-window-frame.json | 2 +- packages/ui/dist/copy/code-editor/component.css | 4 ++++ packages/ui/dist/copy/code-editor/element.html | 2 +- packages/ui/dist/copy/code-editor/index.html | 2 +- packages/ui/dist/copy/code-editor/manifest.json | 6 +++--- .../ui/dist/copy/i3-window-frame/component.css | 4 ++++ .../ui/dist/copy/i3-window-frame/element.html | 2 +- packages/ui/dist/copy/i3-window-frame/index.html | 2 +- .../ui/dist/copy/i3-window-frame/manifest.json | 6 +++--- packages/ui/dist/examples.json | 12 ++++++------ packages/ui/dist/examples/code-editor.json | 6 +++--- packages/ui/dist/examples/i3-window-frame.json | 6 +++--- packages/ui/dist/manifest.json | 16 ++++++++-------- packages/ui/dist/styles/code-editor.css | 4 ++++ packages/ui/dist/styles/i3-window-frame.css | 4 ++++ 25 files changed, 77 insertions(+), 61 deletions(-) diff --git a/exports/digests.json b/exports/digests.json index a3c67ae81..9575b18c7 100644 --- a/exports/digests.json +++ b/exports/digests.json @@ -148,37 +148,37 @@ "exports/patterns/validation-recovery.json": "sha256-b95jcFXXQwDfEeAmRXyixmv4/1iYt0I17C0bwc+HaFA=", "exports/port-capabilities.json": "sha256-6u3M0mXA+lN5FLjtOJvRkLpcFNePSv8ZUMpIiVohxVQ=", "exports/recipes/button/LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "exports/recipes/button/README.md": "sha256-oyfdexEjuoH/PSZ5+B4ixdnllm5G0d2vghtrkmGw6WI=", + "exports/recipes/button/README.md": "sha256-x4lEz+IoqPMXycbNllyu5pCAUoYYeQE2sYbSC92rhf8=", "exports/recipes/button/component.css": "sha256-fO1HSQ+wy0Zku8pqVotCypnOH+iDz8SAX9GxMspxA8U=", "exports/recipes/button/example.html": "sha256-6Jd+ynSweVG+DO3EUHUbEUNSEbj5+6+iBzqXU4YLtIs=", "exports/recipes/button/foundation.css": "sha256-jm66ZdmdAhTyMVQIMKhzVZZm/NhB5ZbLq8g3UASzy98=", - "exports/recipes/button/manifest.json": "sha256-9ie8A2kN/P8gMaNTRepTnofOfNFup1TDw+8NXnkAZjQ=", + "exports/recipes/button/manifest.json": "sha256-T+ORb639g4LcVI1Fway8juU9VnI7vAluofAwYHfhmZ0=", "exports/recipes/button/markup.html": "sha256-be2Beb08aKEqIKaDsxTq8IJdSdfNPJyWS2M5aav7R7k=", "exports/recipes/button/template.html": "sha256-FfylFZ+qzMUFxQKnIdqJiYmC8p4F+cNxK8BJSTo8XU8=", "exports/recipes/button/tokens.css": "sha256-AJa/NV2e+fHrwjzGqedaXaFmM54azgP/b9wytMJiVCs=", "exports/recipes/button/two-instances.html": "sha256-HrqWaokDwmbQXfgRiFeyWToB617qs6c+t/UQLJs0Blk=", "exports/recipes/dialog/LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "exports/recipes/dialog/README.md": "sha256-OWevdpZaBLr9ULIZqwjPZCv28ITIwNlANgF9rmhbbUE=", + "exports/recipes/dialog/README.md": "sha256-iITsstYFBhavmX3lAq6PJwIpTQ0p6+Z/W0yd5s4gWyM=", "exports/recipes/dialog/component.css": "sha256-4rB4zaZ85zCcwBibahNlsmkeHocfBbSHfwT9xY/jwE8=", "exports/recipes/dialog/example.html": "sha256-NfEbyJuZuMeGI56eQN6PW+EXPWfv8OjpngN0eMztvPQ=", "exports/recipes/dialog/foundation.css": "sha256-jm66ZdmdAhTyMVQIMKhzVZZm/NhB5ZbLq8g3UASzy98=", - "exports/recipes/dialog/manifest.json": "sha256-G8xBW6v6i6hyS6H4ULMX4/o87yEdACO7ffQCHltcsng=", + "exports/recipes/dialog/manifest.json": "sha256-GrSBrC8OCOwg2lc97fYWgzYyyn6+gyGWuNbgY0N2GFQ=", "exports/recipes/dialog/markup.html": "sha256-3KkpFAZ9Id+n/Pmpuu4Os4Wea88fXD39tHcFoCINEDQ=", "exports/recipes/dialog/template.html": "sha256-ekYfQWlHu6z/dh7Wi1W3GZayMjEjxB5ru5nU7CKIqMg=", "exports/recipes/dialog/tokens.css": "sha256-8v2razLbiqxJ36LPLf8rHQG219Ns6nFnyRGKJqh/evs=", "exports/recipes/dialog/two-instances.html": "sha256-g3casyVMkw4tWfmMAkD3Aq9kp+I7vebgRqjir2H/52c=", - "exports/recipes/index.json": "sha256-eI8M77oJ6iU8uDVh+T2j7QOZD64aDG3aoUBXsrAqbBA=", + "exports/recipes/index.json": "sha256-0B940Z9KzoAxKcO3Z7CLEO7qHVC85z0EZxCfhRyDOD4=", "exports/recipes/text-field/LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "exports/recipes/text-field/README.md": "sha256-FYLJ5EmjSpTH+Qzqaot4CTkkrEHK3yf/+S4o94S1ONg=", + "exports/recipes/text-field/README.md": "sha256-KmuLUt01kHbIBh0UYCjAYtDpROlIwWSTuP1GGiLEAUI=", "exports/recipes/text-field/component.css": "sha256-Oz8HGS0K4usbEkFFSKi93G9yUBnUass/Z8uQbOJZXNc=", "exports/recipes/text-field/example.html": "sha256-bgWf7wJ491bEm4esZkZzyuL263quAotSfoygX24ZkFU=", "exports/recipes/text-field/foundation.css": "sha256-jm66ZdmdAhTyMVQIMKhzVZZm/NhB5ZbLq8g3UASzy98=", - "exports/recipes/text-field/manifest.json": "sha256-dQ772OHR9NZA7ImYFxQTbq+iSuCvsFlCwgR1MCX11xc=", + "exports/recipes/text-field/manifest.json": "sha256-ESM9BjhZPM6ry1Qb2TIIFeSqbfnc4no4HU6IF0AfAfk=", "exports/recipes/text-field/markup.html": "sha256-wARfGY6V60eMUhV8JNGMhY+EnikQvcPlSqkD5WPOULo=", "exports/recipes/text-field/template.html": "sha256-IlSlLS7sPC3MLqIdxMRQUP4sFnn/58lwM3AFALtdY3c=", "exports/recipes/text-field/tokens.css": "sha256-Z7C9Hx+UzJAtRTBN08cB9BRDeTuCjEQr3xZyD2i0vgU=", "exports/recipes/text-field/two-instances.html": "sha256-JIl9HQHQPYXg+r8lkFfC0x50KKiLyNWAwYm9mdQXGGw=", - "exports/task-inputs.json": "sha256-1fpuwiowwIkGlhEkHYQORPRcuUeuE4Pe6MTTxOG5OKg=", + "exports/task-inputs.json": "sha256-9DYRnfyuUASZDqPmD3BuJ91I914+0REFirf3ygui5Wo=", "exports/theme.compact.md": "sha256-QyPWc0W2dQcJgzifdT+JJWZ0dCKNcS56+p7SYogxShc=", "exports/theme.full.md": "sha256-mtmdZ2yV3SFr1fldtmVPCMwLitps18AG8KOZmPuO3Vk=", "exports/token-usage.json": "sha256-2zZkZAezj2qzczffMftBaaz7UmIqu/sEodle7PsbZeE=", diff --git a/exports/recipes/button/README.md b/exports/recipes/button/README.md index 5543da348..4be93350e 100644 --- a/exports/recipes/button/README.md +++ b/exports/recipes/button/README.md @@ -2,7 +2,7 @@ j3w1 theme 4.0.0. Markup adapted from j3w1 UI Theme Spec, https://github.com/j3w1/theme, CC BY 4.0: https://creativecommons.org/licenses/by/4.0/. Changes: scoped instance IDs and documentation-only content removed. CSS and generator: MIT; see LICENSE.md. -Version 4.0.0; profile default; source digest sha256-s8vilf8bQhVdIriDoQQI4S9vs4++h3XSLTpdhFfvnVo=. Pin the supplying commit and verify manifest source/file digests; the version alone does not identify a revision. +Version 4.0.0; profile default; source digest sha256-jqI8zaZ81RGcctD+DChg5sslYOz31mbBMLbNs8+i38w=. Pin the supplying commit and verify manifest source/file digests; the version alone does not identify a revision. Open example.html directly, without Astro, network assets or a build step. two-instances.html demonstrates independent IDs. For integration, include tokens.css, foundation.css and component.css in that order, then markup.html. Keep .j3w1-recipe and data-density on the wrapper. The source viewer can make a fresh instance prefix; use a unique prefix for every copy and rewrite all ID references together. diff --git a/exports/recipes/button/manifest.json b/exports/recipes/button/manifest.json index 12c5834ec..099a3cb7d 100644 --- a/exports/recipes/button/manifest.json +++ b/exports/recipes/button/manifest.json @@ -13,7 +13,7 @@ "scripts/lib/recipe-generator.mjs": "sha256-5S+XICgFhQB5rLt4NT4OkreWnnLEl02dJVg4gfn0+0o=", "scripts/lib/recipe-css.mjs": "sha256-pYVBZWuIylisk1RECCR78awarge02KZZwVi9+nyBwlw=", "scripts/lib/recipe-markup.mjs": "sha256-pxTFKTEWI1f86ScNw0e2ZfSFkdba5Zs6a7GhmMbIUUQ=", - "scripts/lib/markup.mjs": "sha256-IQdQECNHUm1asmxn5+msWF4XKTUUZHE5j7f/V/fvMSQ=", + "scripts/lib/markup.mjs": "sha256-VbP1LaVzZwTrklUjCiwB7kN/feI9Zg29+Nt1ANkDF0k=", "spec/components/button.md": "sha256-DBraPQbwdT8+fLvS1stg8q/PQVu+wu9nj4S8QFNOf0o=", "spec/components/button.demo.html": "sha256-imCfWDUkqdDOF6H8KEdGAw0qejBcHrtPrnyTMxXvpnI=", "site/src/styles/recipe-foundation.css": "sha256-SUmvPxZ7TNZA79xx7u87QonwpwCDBRcRzTnrTOfV8k8=", @@ -24,7 +24,7 @@ "tokens/semantic.tokens.json": "sha256-jbrikW294TIEdB7rAiqlLPAiLUy2CMyLT/opZiVe/E0=", "tokens/foundations.tokens.json": "sha256-e5OLoStuVryktzLt5O1yFmTb1CR3DcgqccWy5SdB2fw=" }, - "digest": "sha256-s8vilf8bQhVdIriDoQQI4S9vs4++h3XSLTpdhFfvnVo=", + "digest": "sha256-jqI8zaZ81RGcctD+DChg5sslYOz31mbBMLbNs8+i38w=", "revisionPolicy": "Resolve these paths at the same pinned commit as this manifest. The hosted source viewer identifies its supplying commit; generated source files contain content digests, never a floating revision claim." }, "dependencies": { @@ -395,6 +395,6 @@ "example.html": "sha256-6Jd+ynSweVG+DO3EUHUbEUNSEbj5+6+iBzqXU4YLtIs=", "two-instances.html": "sha256-HrqWaokDwmbQXfgRiFeyWToB617qs6c+t/UQLJs0Blk=", "LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "README.md": "sha256-oyfdexEjuoH/PSZ5+B4ixdnllm5G0d2vghtrkmGw6WI=" + "README.md": "sha256-x4lEz+IoqPMXycbNllyu5pCAUoYYeQE2sYbSC92rhf8=" } } diff --git a/exports/recipes/dialog/README.md b/exports/recipes/dialog/README.md index 365b24d18..0d775c781 100644 --- a/exports/recipes/dialog/README.md +++ b/exports/recipes/dialog/README.md @@ -2,7 +2,7 @@ j3w1 theme 4.0.0. Markup adapted from j3w1 UI Theme Spec, https://github.com/j3w1/theme, CC BY 4.0: https://creativecommons.org/licenses/by/4.0/. Changes: scoped instance IDs and documentation-only content removed. CSS and generator: MIT; see LICENSE.md. -Version 4.0.0; profile default; source digest sha256-ME3N1KmEZpPqGQVGC59MeaQuAEpujF9gfP4y/3RlJxE=. Pin the supplying commit and verify manifest source/file digests; the version alone does not identify a revision. +Version 4.0.0; profile default; source digest sha256-U1R7uoflgOe1/2Z85P+ZftJOYXUm9uhi9BPzHoABtfs=. Pin the supplying commit and verify manifest source/file digests; the version alone does not identify a revision. Open example.html directly, without Astro, network assets or a build step. two-instances.html demonstrates independent IDs. For integration, include tokens.css, foundation.css and component.css in that order, then markup.html. Keep .j3w1-recipe and data-density on the wrapper. The source viewer can make a fresh instance prefix; use a unique prefix for every copy and rewrite all ID references together. diff --git a/exports/recipes/dialog/manifest.json b/exports/recipes/dialog/manifest.json index 5c7e0875f..5726b57b7 100644 --- a/exports/recipes/dialog/manifest.json +++ b/exports/recipes/dialog/manifest.json @@ -13,7 +13,7 @@ "scripts/lib/recipe-generator.mjs": "sha256-5S+XICgFhQB5rLt4NT4OkreWnnLEl02dJVg4gfn0+0o=", "scripts/lib/recipe-css.mjs": "sha256-pYVBZWuIylisk1RECCR78awarge02KZZwVi9+nyBwlw=", "scripts/lib/recipe-markup.mjs": "sha256-pxTFKTEWI1f86ScNw0e2ZfSFkdba5Zs6a7GhmMbIUUQ=", - "scripts/lib/markup.mjs": "sha256-IQdQECNHUm1asmxn5+msWF4XKTUUZHE5j7f/V/fvMSQ=", + "scripts/lib/markup.mjs": "sha256-VbP1LaVzZwTrklUjCiwB7kN/feI9Zg29+Nt1ANkDF0k=", "spec/components/dialog.md": "sha256-b2BJ7XMfsSQhSxJZxHIyIrj+hdFOaPEoaAHbQBWKOpQ=", "spec/components/dialog.demo.html": "sha256-m9m1JcXKJ5j3f0rxR1fojmkYvtgzUnhgWBPA0iI6cSM=", "site/src/styles/recipe-foundation.css": "sha256-SUmvPxZ7TNZA79xx7u87QonwpwCDBRcRzTnrTOfV8k8=", @@ -25,7 +25,7 @@ "tokens/semantic.tokens.json": "sha256-jbrikW294TIEdB7rAiqlLPAiLUy2CMyLT/opZiVe/E0=", "tokens/foundations.tokens.json": "sha256-e5OLoStuVryktzLt5O1yFmTb1CR3DcgqccWy5SdB2fw=" }, - "digest": "sha256-ME3N1KmEZpPqGQVGC59MeaQuAEpujF9gfP4y/3RlJxE=", + "digest": "sha256-U1R7uoflgOe1/2Z85P+ZftJOYXUm9uhi9BPzHoABtfs=", "revisionPolicy": "Resolve these paths at the same pinned commit as this manifest. The hosted source viewer identifies its supplying commit; generated source files contain content digests, never a floating revision claim." }, "dependencies": { @@ -559,6 +559,6 @@ "example.html": "sha256-NfEbyJuZuMeGI56eQN6PW+EXPWfv8OjpngN0eMztvPQ=", "two-instances.html": "sha256-g3casyVMkw4tWfmMAkD3Aq9kp+I7vebgRqjir2H/52c=", "LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "README.md": "sha256-OWevdpZaBLr9ULIZqwjPZCv28ITIwNlANgF9rmhbbUE=" + "README.md": "sha256-iITsstYFBhavmX3lAq6PJwIpTQ0p6+Z/W0yd5s4gWyM=" } } diff --git a/exports/recipes/index.json b/exports/recipes/index.json index 1060b79b4..7fb963d6c 100644 --- a/exports/recipes/index.json +++ b/exports/recipes/index.json @@ -7,7 +7,7 @@ "id": "button", "variant": "default", "manifest": "exports/recipes/button/manifest.json", - "sourceDigest": "sha256-s8vilf8bQhVdIriDoQQI4S9vs4++h3XSLTpdhFfvnVo=", + "sourceDigest": "sha256-jqI8zaZ81RGcctD+DChg5sslYOz31mbBMLbNs8+i38w=", "limitations": [ "Native button activation only; application actions are supplied by the host.", "aria-busy supplies the loading appearance; the host must suppress repeated activation while busy." @@ -17,7 +17,7 @@ "id": "text-field", "variant": "default", "manifest": "exports/recipes/text-field/manifest.json", - "sourceDigest": "sha256-1KK1g5jWgt2cOFNs+S+XugFlLROTfPQ3ZQkNFIxLQlE=", + "sourceDigest": "sha256-G3nqlqIplVGQ9sRNsv9rd07TPA0UImNBS846/Nt4/ms=", "limitations": [ "Native text editing only; validation messages and aria-invalid are managed by the host.", "The default text variant is packaged. Password reveal, search clearing and number steppers are not implemented." @@ -27,7 +27,7 @@ "id": "dialog", "variant": "default", "manifest": "exports/recipes/dialog/manifest.json", - "sourceDigest": "sha256-ME3N1KmEZpPqGQVGC59MeaQuAEpujF9gfP4y/3RlJxE=", + "sourceDigest": "sha256-U1R7uoflgOe1/2Z85P+ZftJOYXUm9uhi9BPzHoABtfs=", "limitations": [ "Visual-only: the native dialog is open in normal flow with a simulated backdrop.", "No showModal, focus trap, Escape handling, close actions or focus return is supplied. The host owns the complete modal lifecycle and positioning.", diff --git a/exports/recipes/text-field/README.md b/exports/recipes/text-field/README.md index 947c6e9ae..ce6df5bb2 100644 --- a/exports/recipes/text-field/README.md +++ b/exports/recipes/text-field/README.md @@ -2,7 +2,7 @@ j3w1 theme 4.0.0. Markup adapted from j3w1 UI Theme Spec, https://github.com/j3w1/theme, CC BY 4.0: https://creativecommons.org/licenses/by/4.0/. Changes: scoped instance IDs and documentation-only content removed. CSS and generator: MIT; see LICENSE.md. -Version 4.0.0; profile default; source digest sha256-1KK1g5jWgt2cOFNs+S+XugFlLROTfPQ3ZQkNFIxLQlE=. Pin the supplying commit and verify manifest source/file digests; the version alone does not identify a revision. +Version 4.0.0; profile default; source digest sha256-G3nqlqIplVGQ9sRNsv9rd07TPA0UImNBS846/Nt4/ms=. Pin the supplying commit and verify manifest source/file digests; the version alone does not identify a revision. Open example.html directly, without Astro, network assets or a build step. two-instances.html demonstrates independent IDs. For integration, include tokens.css, foundation.css and component.css in that order, then markup.html. Keep .j3w1-recipe and data-density on the wrapper. The source viewer can make a fresh instance prefix; use a unique prefix for every copy and rewrite all ID references together. diff --git a/exports/recipes/text-field/manifest.json b/exports/recipes/text-field/manifest.json index 53cd17da6..2f70e74e1 100644 --- a/exports/recipes/text-field/manifest.json +++ b/exports/recipes/text-field/manifest.json @@ -13,7 +13,7 @@ "scripts/lib/recipe-generator.mjs": "sha256-5S+XICgFhQB5rLt4NT4OkreWnnLEl02dJVg4gfn0+0o=", "scripts/lib/recipe-css.mjs": "sha256-pYVBZWuIylisk1RECCR78awarge02KZZwVi9+nyBwlw=", "scripts/lib/recipe-markup.mjs": "sha256-pxTFKTEWI1f86ScNw0e2ZfSFkdba5Zs6a7GhmMbIUUQ=", - "scripts/lib/markup.mjs": "sha256-IQdQECNHUm1asmxn5+msWF4XKTUUZHE5j7f/V/fvMSQ=", + "scripts/lib/markup.mjs": "sha256-VbP1LaVzZwTrklUjCiwB7kN/feI9Zg29+Nt1ANkDF0k=", "spec/components/text-field.md": "sha256-iLHCdTuJlbSfqRTnHiZJ8P6xV4HrD4S5Bzt5SBP6zP4=", "spec/components/text-field.demo.html": "sha256-ZB5xDObbSUC3QCuqccJpd3EmQ5YJQhJ74BCTur+xwa4=", "site/src/styles/recipe-foundation.css": "sha256-SUmvPxZ7TNZA79xx7u87QonwpwCDBRcRzTnrTOfV8k8=", @@ -24,7 +24,7 @@ "tokens/semantic.tokens.json": "sha256-jbrikW294TIEdB7rAiqlLPAiLUy2CMyLT/opZiVe/E0=", "tokens/foundations.tokens.json": "sha256-e5OLoStuVryktzLt5O1yFmTb1CR3DcgqccWy5SdB2fw=" }, - "digest": "sha256-1KK1g5jWgt2cOFNs+S+XugFlLROTfPQ3ZQkNFIxLQlE=", + "digest": "sha256-G3nqlqIplVGQ9sRNsv9rd07TPA0UImNBS846/Nt4/ms=", "revisionPolicy": "Resolve these paths at the same pinned commit as this manifest. The hosted source viewer identifies its supplying commit; generated source files contain content digests, never a floating revision claim." }, "dependencies": { @@ -360,6 +360,6 @@ "example.html": "sha256-bgWf7wJ491bEm4esZkZzyuL263quAotSfoygX24ZkFU=", "two-instances.html": "sha256-JIl9HQHQPYXg+r8lkFfC0x50KKiLyNWAwYm9mdQXGGw=", "LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "README.md": "sha256-FYLJ5EmjSpTH+Qzqaot4CTkkrEHK3yf/+S4o94S1ONg=" + "README.md": "sha256-KmuLUt01kHbIBh0UYCjAYtDpROlIwWSTuP1GGiLEAUI=" } } diff --git a/exports/task-inputs.json b/exports/task-inputs.json index a1ad60997..eedf3d84d 100644 --- a/exports/task-inputs.json +++ b/exports/task-inputs.json @@ -1076,9 +1076,9 @@ "exports/recipes/button/example.html": "sha256-6Jd+ynSweVG+DO3EUHUbEUNSEbj5+6+iBzqXU4YLtIs=", "exports/recipes/button/foundation.css": "sha256-jm66ZdmdAhTyMVQIMKhzVZZm/NhB5ZbLq8g3UASzy98=", "exports/recipes/button/LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "exports/recipes/button/manifest.json": "sha256-9ie8A2kN/P8gMaNTRepTnofOfNFup1TDw+8NXnkAZjQ=", + "exports/recipes/button/manifest.json": "sha256-T+ORb639g4LcVI1Fway8juU9VnI7vAluofAwYHfhmZ0=", "exports/recipes/button/markup.html": "sha256-be2Beb08aKEqIKaDsxTq8IJdSdfNPJyWS2M5aav7R7k=", - "exports/recipes/button/README.md": "sha256-oyfdexEjuoH/PSZ5+B4ixdnllm5G0d2vghtrkmGw6WI=", + "exports/recipes/button/README.md": "sha256-x4lEz+IoqPMXycbNllyu5pCAUoYYeQE2sYbSC92rhf8=", "exports/recipes/button/template.html": "sha256-FfylFZ+qzMUFxQKnIdqJiYmC8p4F+cNxK8BJSTo8XU8=", "exports/recipes/button/tokens.css": "sha256-AJa/NV2e+fHrwjzGqedaXaFmM54azgP/b9wytMJiVCs=", "exports/recipes/button/two-instances.html": "sha256-HrqWaokDwmbQXfgRiFeyWToB617qs6c+t/UQLJs0Blk=", @@ -1086,9 +1086,9 @@ "exports/recipes/dialog/example.html": "sha256-NfEbyJuZuMeGI56eQN6PW+EXPWfv8OjpngN0eMztvPQ=", "exports/recipes/dialog/foundation.css": "sha256-jm66ZdmdAhTyMVQIMKhzVZZm/NhB5ZbLq8g3UASzy98=", "exports/recipes/dialog/LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "exports/recipes/dialog/manifest.json": "sha256-G8xBW6v6i6hyS6H4ULMX4/o87yEdACO7ffQCHltcsng=", + "exports/recipes/dialog/manifest.json": "sha256-GrSBrC8OCOwg2lc97fYWgzYyyn6+gyGWuNbgY0N2GFQ=", "exports/recipes/dialog/markup.html": "sha256-3KkpFAZ9Id+n/Pmpuu4Os4Wea88fXD39tHcFoCINEDQ=", - "exports/recipes/dialog/README.md": "sha256-OWevdpZaBLr9ULIZqwjPZCv28ITIwNlANgF9rmhbbUE=", + "exports/recipes/dialog/README.md": "sha256-iITsstYFBhavmX3lAq6PJwIpTQ0p6+Z/W0yd5s4gWyM=", "exports/recipes/dialog/template.html": "sha256-ekYfQWlHu6z/dh7Wi1W3GZayMjEjxB5ru5nU7CKIqMg=", "exports/recipes/dialog/tokens.css": "sha256-8v2razLbiqxJ36LPLf8rHQG219Ns6nFnyRGKJqh/evs=", "exports/recipes/dialog/two-instances.html": "sha256-g3casyVMkw4tWfmMAkD3Aq9kp+I7vebgRqjir2H/52c=", @@ -1096,9 +1096,9 @@ "exports/recipes/text-field/example.html": "sha256-bgWf7wJ491bEm4esZkZzyuL263quAotSfoygX24ZkFU=", "exports/recipes/text-field/foundation.css": "sha256-jm66ZdmdAhTyMVQIMKhzVZZm/NhB5ZbLq8g3UASzy98=", "exports/recipes/text-field/LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", - "exports/recipes/text-field/manifest.json": "sha256-dQ772OHR9NZA7ImYFxQTbq+iSuCvsFlCwgR1MCX11xc=", + "exports/recipes/text-field/manifest.json": "sha256-ESM9BjhZPM6ry1Qb2TIIFeSqbfnc4no4HU6IF0AfAfk=", "exports/recipes/text-field/markup.html": "sha256-wARfGY6V60eMUhV8JNGMhY+EnikQvcPlSqkD5WPOULo=", - "exports/recipes/text-field/README.md": "sha256-FYLJ5EmjSpTH+Qzqaot4CTkkrEHK3yf/+S4o94S1ONg=", + "exports/recipes/text-field/README.md": "sha256-KmuLUt01kHbIBh0UYCjAYtDpROlIwWSTuP1GGiLEAUI=", "exports/recipes/text-field/template.html": "sha256-IlSlLS7sPC3MLqIdxMRQUP4sFnn/58lwM3AFALtdY3c=", "exports/recipes/text-field/tokens.css": "sha256-Z7C9Hx+UzJAtRTBN08cB9BRDeTuCjEQr3xZyD2i0vgU=", "exports/recipes/text-field/two-instances.html": "sha256-JIl9HQHQPYXg+r8lkFfC0x50KKiLyNWAwYm9mdQXGGw=", diff --git a/packages/ui/dist/contracts/code-editor.json b/packages/ui/dist/contracts/code-editor.json index 5babdd8ee..ceb72c889 100644 --- a/packages/ui/dist/contracts/code-editor.json +++ b/packages/ui/dist/contracts/code-editor.json @@ -531,6 +531,6 @@ "copy": { "directory": "copy/code-editor/", "manifest": "copy/code-editor/manifest.json", - "digest": "sha256-YW6ytfMdyrqpCbrZD4Z3OZT4SRpTTYbxhqsVf+bdeys=" + "digest": "sha256-34XB9GRIxMUKi/v1n3Xa3EwEByberTg3XfCVREIe3rw=" } } diff --git a/packages/ui/dist/contracts/i3-window-frame.json b/packages/ui/dist/contracts/i3-window-frame.json index 141d31f97..0157ca61f 100644 --- a/packages/ui/dist/contracts/i3-window-frame.json +++ b/packages/ui/dist/contracts/i3-window-frame.json @@ -962,6 +962,6 @@ "copy": { "directory": "copy/i3-window-frame/", "manifest": "copy/i3-window-frame/manifest.json", - "digest": "sha256-34QNQs09okyIve3C/VbLvsCxS9dX0aP441tZNe3h0O0=" + "digest": "sha256-DHerFbvqjcRpd5y/PPXy6ADxs1R+eLxowrnBuzBvRuM=" } } diff --git a/packages/ui/dist/copy/code-editor/component.css b/packages/ui/dist/copy/code-editor/component.css index b3de21be6..070968813 100644 --- a/packages/ui/dist/copy/code-editor/component.css +++ b/packages/ui/dist/copy/code-editor/component.css @@ -85,6 +85,10 @@ j3w1-code-editor .code-editor-ws { color: var(--color-code-whitespace); } +j3w1-code-editor .code-editor-ws::before { + content: attr(data-whitespace); +} + j3w1-code-editor .code-editor-fold { display: inline-block; padding: 0 var(--space-4); diff --git a/packages/ui/dist/copy/code-editor/element.html b/packages/ui/dist/copy/code-editor/element.html index 98b3dcac5..c458ec40c 100644 --- a/packages/ui/dist/copy/code-editor/element.html +++ b/packages/ui/dist/copy/code-editor/element.html @@ -1,7 +1,7 @@
// Compose the window title of the focused container.
 import { Container } from "./tree.js";
-const MAX_LENGTH = 48;
+const MAX_LENGTH = 48;
 export function title(container) {
   const name = container.name ?? "untitled…";
   let label = `${name} (${container.children.length})`;
diff --git a/packages/ui/dist/copy/code-editor/index.html b/packages/ui/dist/copy/code-editor/index.html
index 4509467c0..66bb355b8 100644
--- a/packages/ui/dist/copy/code-editor/index.html
+++ b/packages/ui/dist/copy/code-editor/index.html
@@ -2,7 +2,7 @@
 Code editor · j3w1
// Compose the window title of the focused container.
 import { Container } from "./tree.js";
-const MAX_LENGTH = 48;
+const MAX_LENGTH = 48;
 export function title(container) {
   const name = container.name ?? "untitled…";
   let label = `${name} (${container.children.length})`;
diff --git a/packages/ui/dist/copy/code-editor/manifest.json b/packages/ui/dist/copy/code-editor/manifest.json
index 602a86df3..724ca6b89 100644
--- a/packages/ui/dist/copy/code-editor/manifest.json
+++ b/packages/ui/dist/copy/code-editor/manifest.json
@@ -17,10 +17,10 @@
     "runtime/components/code-editor.js": "sha256-MMz8rm+dJT4XahXmR9ftmU0IhNW1NqLIHW7U3STXDPQ=",
     "runtime/chunks/display-Jm9bAsnb.js": "sha256-qZb1g04piEwY3lfFJwMe+0mXR218ljtVi8mepWxrFv8=",
     "tokens.css": "sha256-7A9Xv87HbmuVumnQtzllDxHGc2CPnurdpWWuBpEStJg=",
-    "component.css": "sha256-4LPA5bI5mlJBawZsawTWYAUm+rgCy7tGXqmR9+dNl4U=",
+    "component.css": "sha256-aa9zAzIlna+IPd+Xivi0WU385o/+RmhG5pRVR1vsE64=",
     "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=",
-    "element.html": "sha256-aD+1gDxKB5fijO+A+hjuTqChvHPDv5zp5tK9UPZhwLc=",
-    "index.html": "sha256-fEiQeV/RgniP8X0ij1CkgNb0LNwR9atyMx9gXge/Sk8=",
+    "element.html": "sha256-yXGoyQ6QC1zx9v7pXmaH1J2StJS/EEc6ZMqWAgdNj6A=",
+    "index.html": "sha256-2pHlO7mTG0Z1FySFL7jnRFIidQEfcMXdM+OtJBsZeXA=",
     "README.md": "sha256-oP4WnaIDAzxwm22ndFvMgchWr7l/DH7YotacPAFZuO8="
   }
 }
diff --git a/packages/ui/dist/copy/i3-window-frame/component.css b/packages/ui/dist/copy/i3-window-frame/component.css
index 592729ae6..ae3d69abc 100644
--- a/packages/ui/dist/copy/i3-window-frame/component.css
+++ b/packages/ui/dist/copy/i3-window-frame/component.css
@@ -523,6 +523,10 @@ j3w1-i3-window-frame .code-editor-ws {
   color: var(--color-code-whitespace);
 }
 
+j3w1-i3-window-frame .code-editor-ws::before {
+  content: attr(data-whitespace);
+}
+
 j3w1-i3-window-frame .code-editor-fold {
   display: inline-block;
   padding: 0 var(--space-4);
diff --git a/packages/ui/dist/copy/i3-window-frame/element.html b/packages/ui/dist/copy/i3-window-frame/element.html
index b3652c670..849c0b872 100644
--- a/packages/ui/dist/copy/i3-window-frame/element.html
+++ b/packages/ui/dist/copy/i3-window-frame/element.html
@@ -33,7 +33,7 @@
 
// Compose the window title of the focused container.
 import { Container } from "./tree.js";
-const MAX_LENGTH = 48;
+const MAX_LENGTH = 48;
 export function title(container) {
   const name = container.name ?? "untitled…";
   let label = `${name} (${container.children.length})`;
diff --git a/packages/ui/dist/copy/i3-window-frame/index.html b/packages/ui/dist/copy/i3-window-frame/index.html
index 9262e91ca..a04ad8722 100644
--- a/packages/ui/dist/copy/i3-window-frame/index.html
+++ b/packages/ui/dist/copy/i3-window-frame/index.html
@@ -34,7 +34,7 @@
 
// Compose the window title of the focused container.
 import { Container } from "./tree.js";
-const MAX_LENGTH = 48;
+const MAX_LENGTH = 48;
 export function title(container) {
   const name = container.name ?? "untitled…";
   let label = `${name} (${container.children.length})`;
diff --git a/packages/ui/dist/copy/i3-window-frame/manifest.json b/packages/ui/dist/copy/i3-window-frame/manifest.json
index 69842497f..4d75e292b 100644
--- a/packages/ui/dist/copy/i3-window-frame/manifest.json
+++ b/packages/ui/dist/copy/i3-window-frame/manifest.json
@@ -19,10 +19,10 @@
     "runtime/chunks/compositions-D57dCsBz.js": "sha256-PEpI/vGgdD+LSznUd0iedSxxVE+5QxIO7BGKeQnCRjo=",
     "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=",
     "tokens.css": "sha256-7A9Xv87HbmuVumnQtzllDxHGc2CPnurdpWWuBpEStJg=",
-    "component.css": "sha256-flESdDVMoLb/4QOaPquO0Wn4iBig+NKOGV5Snjkhz8A=",
+    "component.css": "sha256-qnsF12iIL9s2blKkBo1Cq0iJ7btji7uOmjqmQId+1pY=",
     "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=",
-    "element.html": "sha256-nNyvwUVLU3Rdy3x0UcZN+IkCA1+Ot5CVwjUB54GDnq8=",
-    "index.html": "sha256-5dYSTEhCTMSvtWC0ppGMuIR1wTY6xcAn1B4t+8ERTy8=",
+    "element.html": "sha256-r16RBHw/9BhmfwHsOtPnFIkDRIuIAmlN+RpR9z4LXMU=",
+    "index.html": "sha256-vsi84+uGu4rv5NlM/V/to85JQlSDYVg0XKREuwBARII=",
     "README.md": "sha256-C0hpJoSU0W6E5VFxM/5nRjno1clSop0NLti9ZjvJiO0="
   }
 }
diff --git a/packages/ui/dist/examples.json b/packages/ui/dist/examples.json
index 4589aa688..c369a2602 100644
--- a/packages/ui/dist/examples.json
+++ b/packages/ui/dist/examples.json
@@ -228,9 +228,9 @@
     "default": "

✕ Project list unavailable

The demonstration request failed. Retry to load the local example records.

" }, "code-editor": { - "default": "
\n
1// Compose the window title of the focused container.\n2import { Container } from \"./tree.js\";\n3const MAX_LENGTH = 48;··\n4export function title(container) {\n5  const name = container.name ?? \"untitled…\";\n6  let label = `${name} (${container.children.length})`;\n7  if (label.length > MAX_LENGTH) {\n8    label = label.slice(0, MAX_LENGTH) + \"…\";\n9  }\n10  return escape(label); /* escape() is deprecated */\n11}\n12const broken = 0x1G;
\n
", - "markup": "
\n
1<!doctype html>\n2<!-- window frame specimen -->\n3<html lang=\"en\">\n4  <head>\n5    <title>j3w1 &mdash; theme</title>\n6  </head>\n7  <body class=\"frame\" data-density=\"compact\">\n8    <h1>Window frame</h1>\n9    <marquee>obsolete</marquee>\n10    <p>Focus is a ring; selection is a fill.</p>\n11  </body>·\n12</html><
\n
", - "folded": "
\n
4export function title(container) {\n5  const name = container.name ?? \"untitled\";\n›7  if (label.length > MAX_LENGTH) { ⋯ }\n10  return escape(label); /* escape() is deprecated */\n11}·
\n
" + "default": "
\n
1// Compose the window title of the focused container.\n2import { Container } from \"./tree.js\";\n3const MAX_LENGTH = 48;\n4export function title(container) {\n5  const name = container.name ?? \"untitled…\";\n6  let label = `${name} (${container.children.length})`;\n7  if (label.length > MAX_LENGTH) {\n8    label = label.slice(0, MAX_LENGTH) + \"…\";\n9  }\n10  return escape(label); /* escape() is deprecated */\n11}\n12const broken = 0x1G;
\n
", + "markup": "
\n
1<!doctype html>\n2<!-- window frame specimen -->\n3<html lang=\"en\">\n4  <head>\n5    <title>j3w1 &mdash; theme</title>\n6  </head>\n7  <body class=\"frame\" data-density=\"compact\">\n8    <h1>Window frame</h1>\n9    <marquee>obsolete</marquee>\n10    <p>Focus is a ring; selection is a fill.</p>\n11  </body>\n12</html><
\n
", + "folded": "
\n
4export function title(container) {\n5  const name = container.name ?? \"untitled\";\n›7  if (label.length > MAX_LENGTH) { ⋯ }\n10  return escape(label); /* escape() is deprecated */\n11}
\n
" }, "editor-search": { "default": "

Enter text to search.

const theme = 'j3w1';\nconst mode = 'dark';\nexport { theme, mode };
" @@ -264,9 +264,9 @@ "loading": "
NameType / signatureMeaning
Project records · synthetic fixture
Atlas libraryAvery KimReady24
Orion workspaceJordan LeeIn progress12
Field notesMorgan NoorReady38
Signal monitorRiley StoneReview6
⋯ Loading rows

" }, "i3-window-frame": { - "default": "
\n
\n
\n \n \n \n
\n
\n 处理器 12%\n 内存储器 3.1G\n 局域网 up\n 电池 87%\n \n
\n
\n
\n
\n
~/theme — zsh
\n
 ~/theme ▶ main ▶ ls -l ports\ntotal 5\ndrwxr-xr-x  2 j3w1 j3w1  4096 Sep  6 09:12 alacritty\ndrwx------  2 j3w1 j3w1  4096 Sep  6 09:12 gtk\n-rw-r--r--  1 j3w1 j3w1  1180 Sep  6 09:12 README.md\n-rwxr-xr-x  1 j3w1 j3w1   512 Sep  6 09:12 verify.sh\nlrwxrwxrwx  1 j3w1 j3w1    11 Sep  6 09:12 xresources -> ../tokens/\n-rw-r--r--  1 j3w1 j3w1 20480 Sep  6 09:12 evidence.tar.gz\n ~/theme ▶ main ▶ cat ports/gtk/port.json\ncat: ports/gtk/port.json: No such file or directory\n ~/theme ▶ main ▶ npm run validate 
\n
\n
\n
title.js — editor
\n
\n
1// Compose the window title of the focused container.\n2import { Container } from \"./tree.js\";\n3const MAX_LENGTH = 48;··\n4export function title(container) {\n5  const name = container.name ?? \"untitled…\";\n6  let label = `${name} (${container.children.length})`;\n7  if (label.length > MAX_LENGTH) {\n8    label = label.slice(0, MAX_LENGTH) + \"…\";\n9  }\n10  return escape(label); /* escape() is deprecated */\n11}\n12const broken = 0x1G;
\n
\n
\n
\n
", - "tabbed": "
\n
\n
\n \n \n \n
\n
\n 处理器 12%\n 内存储器 3.1G\n 局域网 up\n 电池 87%\n \n
\n
\n
\n
\n
\n \n \n
\n
\n
 ~/theme ▶ main ▶ ls -l ports\ntotal 5\ndrwxr-xr-x  2 j3w1 j3w1  4096 Sep  6 09:12 alacritty\ndrwx------  2 j3w1 j3w1  4096 Sep  6 09:12 gtk\n-rw-r--r--  1 j3w1 j3w1  1180 Sep  6 09:12 README.md\n-rwxr-xr-x  1 j3w1 j3w1   512 Sep  6 09:12 verify.sh\nlrwxrwxrwx  1 j3w1 j3w1    11 Sep  6 09:12 xresources -> ../tokens/\n-rw-r--r--  1 j3w1 j3w1 20480 Sep  6 09:12 evidence.tar.gz\n ~/theme ▶ main ▶ cat ports/gtk/port.json\ncat: ports/gtk/port.json: No such file or directory\n ~/theme ▶ main ▶ npm run validate 
\n
\n \n
\n
\n
", - "floating": "
\n
\n
\n \n \n \n
\n
\n 处理器 12%\n 内存储器 3.1G\n 局域网 up\n 电池 87%\n \n
\n
\n
\n
\n
~/theme — zsh
\n
 ~/theme ▶ main ▶ ls -l ports\ntotal 5\ndrwxr-xr-x  2 j3w1 j3w1  4096 Sep  6 09:12 alacritty\ndrwx------  2 j3w1 j3w1  4096 Sep  6 09:12 gtk\n-rw-r--r--  1 j3w1 j3w1  1180 Sep  6 09:12 README.md\n-rwxr-xr-x  1 j3w1 j3w1   512 Sep  6 09:12 verify.sh\nlrwxrwxrwx  1 j3w1 j3w1    11 Sep  6 09:12 xresources -> ../tokens/\n-rw-r--r--  1 j3w1 j3w1 20480 Sep  6 09:12 evidence.tar.gz\n ~/theme ▶ main ▶ cat ports/gtk/port.json\ncat: ports/gtk/port.json: No such file or directory\n ~/theme ▶ main ▶ npm run validate 
\n
\n
\n
title.js — editor
\n
\n
1// Compose the window title of the focused container.\n2import { Container } from \"./tree.js\";\n3const MAX_LENGTH = 48;··\n4export function title(container) {\n5  const name = container.name ?? \"untitled…\";\n6  let label = `${name} (${container.children.length})`;\n7  if (label.length > MAX_LENGTH) {\n8    label = label.slice(0, MAX_LENGTH) + \"…\";\n9  }\n10  return escape(label); /* escape() is deprecated */\n11}\n12const broken = 0x1G;
\n
\n
\n
\n
" + "default": "
\n
\n
\n \n \n \n
\n
\n 处理器 12%\n 内存储器 3.1G\n 局域网 up\n 电池 87%\n \n
\n
\n
\n
\n
~/theme — zsh
\n
 ~/theme ▶ main ▶ ls -l ports\ntotal 5\ndrwxr-xr-x  2 j3w1 j3w1  4096 Sep  6 09:12 alacritty\ndrwx------  2 j3w1 j3w1  4096 Sep  6 09:12 gtk\n-rw-r--r--  1 j3w1 j3w1  1180 Sep  6 09:12 README.md\n-rwxr-xr-x  1 j3w1 j3w1   512 Sep  6 09:12 verify.sh\nlrwxrwxrwx  1 j3w1 j3w1    11 Sep  6 09:12 xresources -> ../tokens/\n-rw-r--r--  1 j3w1 j3w1 20480 Sep  6 09:12 evidence.tar.gz\n ~/theme ▶ main ▶ cat ports/gtk/port.json\ncat: ports/gtk/port.json: No such file or directory\n ~/theme ▶ main ▶ npm run validate 
\n
\n
\n
title.js — editor
\n
\n
1// Compose the window title of the focused container.\n2import { Container } from \"./tree.js\";\n3const MAX_LENGTH = 48;\n4export function title(container) {\n5  const name = container.name ?? \"untitled…\";\n6  let label = `${name} (${container.children.length})`;\n7  if (label.length > MAX_LENGTH) {\n8    label = label.slice(0, MAX_LENGTH) + \"…\";\n9  }\n10  return escape(label); /* escape() is deprecated */\n11}\n12const broken = 0x1G;
\n
\n
\n
\n
", + "tabbed": "
\n
\n
\n \n \n \n
\n
\n 处理器 12%\n 内存储器 3.1G\n 局域网 up\n 电池 87%\n \n
\n
\n
\n
\n
\n \n \n
\n
\n
 ~/theme ▶ main ▶ ls -l ports\ntotal 5\ndrwxr-xr-x  2 j3w1 j3w1  4096 Sep  6 09:12 alacritty\ndrwx------  2 j3w1 j3w1  4096 Sep  6 09:12 gtk\n-rw-r--r--  1 j3w1 j3w1  1180 Sep  6 09:12 README.md\n-rwxr-xr-x  1 j3w1 j3w1   512 Sep  6 09:12 verify.sh\nlrwxrwxrwx  1 j3w1 j3w1    11 Sep  6 09:12 xresources -> ../tokens/\n-rw-r--r--  1 j3w1 j3w1 20480 Sep  6 09:12 evidence.tar.gz\n ~/theme ▶ main ▶ cat ports/gtk/port.json\ncat: ports/gtk/port.json: No such file or directory\n ~/theme ▶ main ▶ npm run validate 
\n
\n \n
\n
\n
", + "floating": "
\n
\n
\n \n \n \n
\n
\n 处理器 12%\n 内存储器 3.1G\n 局域网 up\n 电池 87%\n \n
\n
\n
\n
\n
~/theme — zsh
\n
 ~/theme ▶ main ▶ ls -l ports\ntotal 5\ndrwxr-xr-x  2 j3w1 j3w1  4096 Sep  6 09:12 alacritty\ndrwx------  2 j3w1 j3w1  4096 Sep  6 09:12 gtk\n-rw-r--r--  1 j3w1 j3w1  1180 Sep  6 09:12 README.md\n-rwxr-xr-x  1 j3w1 j3w1   512 Sep  6 09:12 verify.sh\nlrwxrwxrwx  1 j3w1 j3w1    11 Sep  6 09:12 xresources -> ../tokens/\n-rw-r--r--  1 j3w1 j3w1 20480 Sep  6 09:12 evidence.tar.gz\n ~/theme ▶ main ▶ cat ports/gtk/port.json\ncat: ports/gtk/port.json: No such file or directory\n ~/theme ▶ main ▶ npm run validate 
\n
\n
\n
title.js — editor
\n
\n
1// Compose the window title of the focused container.\n2import { Container } from \"./tree.js\";\n3const MAX_LENGTH = 48;\n4export function title(container) {\n5  const name = container.name ?? \"untitled…\";\n6  let label = `${name} (${container.children.length})`;\n7  if (label.length > MAX_LENGTH) {\n8    label = label.slice(0, MAX_LENGTH) + \"…\";\n9  }\n10  return escape(label); /* escape() is deprecated */\n11}\n12const broken = 0x1G;
\n
\n
\n
\n
" }, "file-browser": { "default": "
  • All files
  • Source
Local file examples
NameKindSize
Vue component4 KB
Documentation2 KB

2 files

" diff --git a/packages/ui/dist/examples/code-editor.json b/packages/ui/dist/examples/code-editor.json index c1636c168..c71c0297a 100644 --- a/packages/ui/dist/examples/code-editor.json +++ b/packages/ui/dist/examples/code-editor.json @@ -1,5 +1,5 @@ { - "default": "
\n
1// Compose the window title of the focused container.\n2import { Container } from \"./tree.js\";\n3const MAX_LENGTH = 48;··\n4export function title(container) {\n5  const name = container.name ?? \"untitled…\";\n6  let label = `${name} (${container.children.length})`;\n7  if (label.length > MAX_LENGTH) {\n8    label = label.slice(0, MAX_LENGTH) + \"…\";\n9  }\n10  return escape(label); /* escape() is deprecated */\n11}\n12const broken = 0x1G;
\n
", - "markup": "
\n
1<!doctype html>\n2<!-- window frame specimen -->\n3<html lang=\"en\">\n4  <head>\n5    <title>j3w1 &mdash; theme</title>\n6  </head>\n7  <body class=\"frame\" data-density=\"compact\">\n8    <h1>Window frame</h1>\n9    <marquee>obsolete</marquee>\n10    <p>Focus is a ring; selection is a fill.</p>\n11  </body>·\n12</html><
\n
", - "folded": "
\n
4export function title(container) {\n5  const name = container.name ?? \"untitled\";\n›7  if (label.length > MAX_LENGTH) { ⋯ }\n10  return escape(label); /* escape() is deprecated */\n11}·
\n
" + "default": "
\n
1// Compose the window title of the focused container.\n2import { Container } from \"./tree.js\";\n3const MAX_LENGTH = 48;\n4export function title(container) {\n5  const name = container.name ?? \"untitled…\";\n6  let label = `${name} (${container.children.length})`;\n7  if (label.length > MAX_LENGTH) {\n8    label = label.slice(0, MAX_LENGTH) + \"…\";\n9  }\n10  return escape(label); /* escape() is deprecated */\n11}\n12const broken = 0x1G;
\n
", + "markup": "
\n
1<!doctype html>\n2<!-- window frame specimen -->\n3<html lang=\"en\">\n4  <head>\n5    <title>j3w1 &mdash; theme</title>\n6  </head>\n7  <body class=\"frame\" data-density=\"compact\">\n8    <h1>Window frame</h1>\n9    <marquee>obsolete</marquee>\n10    <p>Focus is a ring; selection is a fill.</p>\n11  </body>\n12</html><
\n
", + "folded": "
\n
4export function title(container) {\n5  const name = container.name ?? \"untitled\";\n›7  if (label.length > MAX_LENGTH) { ⋯ }\n10  return escape(label); /* escape() is deprecated */\n11}
\n
" } diff --git a/packages/ui/dist/examples/i3-window-frame.json b/packages/ui/dist/examples/i3-window-frame.json index a054224fa..6044682ce 100644 --- a/packages/ui/dist/examples/i3-window-frame.json +++ b/packages/ui/dist/examples/i3-window-frame.json @@ -1,5 +1,5 @@ { - "default": "
\n
\n
\n \n \n \n
\n
\n 处理器 12%\n 内存储器 3.1G\n 局域网 up\n 电池 87%\n \n
\n
\n
\n
\n
~/theme — zsh
\n
 ~/theme ▶ main ▶ ls -l ports\ntotal 5\ndrwxr-xr-x  2 j3w1 j3w1  4096 Sep  6 09:12 alacritty\ndrwx------  2 j3w1 j3w1  4096 Sep  6 09:12 gtk\n-rw-r--r--  1 j3w1 j3w1  1180 Sep  6 09:12 README.md\n-rwxr-xr-x  1 j3w1 j3w1   512 Sep  6 09:12 verify.sh\nlrwxrwxrwx  1 j3w1 j3w1    11 Sep  6 09:12 xresources -> ../tokens/\n-rw-r--r--  1 j3w1 j3w1 20480 Sep  6 09:12 evidence.tar.gz\n ~/theme ▶ main ▶ cat ports/gtk/port.json\ncat: ports/gtk/port.json: No such file or directory\n ~/theme ▶ main ▶ npm run validate 
\n
\n
\n
title.js — editor
\n
\n
1// Compose the window title of the focused container.\n2import { Container } from \"./tree.js\";\n3const MAX_LENGTH = 48;··\n4export function title(container) {\n5  const name = container.name ?? \"untitled…\";\n6  let label = `${name} (${container.children.length})`;\n7  if (label.length > MAX_LENGTH) {\n8    label = label.slice(0, MAX_LENGTH) + \"…\";\n9  }\n10  return escape(label); /* escape() is deprecated */\n11}\n12const broken = 0x1G;
\n
\n
\n
\n
", - "tabbed": "
\n
\n
\n \n \n \n
\n
\n 处理器 12%\n 内存储器 3.1G\n 局域网 up\n 电池 87%\n \n
\n
\n
\n
\n
\n \n \n
\n
\n
 ~/theme ▶ main ▶ ls -l ports\ntotal 5\ndrwxr-xr-x  2 j3w1 j3w1  4096 Sep  6 09:12 alacritty\ndrwx------  2 j3w1 j3w1  4096 Sep  6 09:12 gtk\n-rw-r--r--  1 j3w1 j3w1  1180 Sep  6 09:12 README.md\n-rwxr-xr-x  1 j3w1 j3w1   512 Sep  6 09:12 verify.sh\nlrwxrwxrwx  1 j3w1 j3w1    11 Sep  6 09:12 xresources -> ../tokens/\n-rw-r--r--  1 j3w1 j3w1 20480 Sep  6 09:12 evidence.tar.gz\n ~/theme ▶ main ▶ cat ports/gtk/port.json\ncat: ports/gtk/port.json: No such file or directory\n ~/theme ▶ main ▶ npm run validate 
\n
\n \n
\n
\n
", - "floating": "
\n
\n
\n \n \n \n
\n
\n 处理器 12%\n 内存储器 3.1G\n 局域网 up\n 电池 87%\n \n
\n
\n
\n
\n
~/theme — zsh
\n
 ~/theme ▶ main ▶ ls -l ports\ntotal 5\ndrwxr-xr-x  2 j3w1 j3w1  4096 Sep  6 09:12 alacritty\ndrwx------  2 j3w1 j3w1  4096 Sep  6 09:12 gtk\n-rw-r--r--  1 j3w1 j3w1  1180 Sep  6 09:12 README.md\n-rwxr-xr-x  1 j3w1 j3w1   512 Sep  6 09:12 verify.sh\nlrwxrwxrwx  1 j3w1 j3w1    11 Sep  6 09:12 xresources -> ../tokens/\n-rw-r--r--  1 j3w1 j3w1 20480 Sep  6 09:12 evidence.tar.gz\n ~/theme ▶ main ▶ cat ports/gtk/port.json\ncat: ports/gtk/port.json: No such file or directory\n ~/theme ▶ main ▶ npm run validate 
\n
\n
\n
title.js — editor
\n
\n
1// Compose the window title of the focused container.\n2import { Container } from \"./tree.js\";\n3const MAX_LENGTH = 48;··\n4export function title(container) {\n5  const name = container.name ?? \"untitled…\";\n6  let label = `${name} (${container.children.length})`;\n7  if (label.length > MAX_LENGTH) {\n8    label = label.slice(0, MAX_LENGTH) + \"…\";\n9  }\n10  return escape(label); /* escape() is deprecated */\n11}\n12const broken = 0x1G;
\n
\n
\n
\n
" + "default": "
\n
\n
\n \n \n \n
\n
\n 处理器 12%\n 内存储器 3.1G\n 局域网 up\n 电池 87%\n \n
\n
\n
\n
\n
~/theme — zsh
\n
 ~/theme ▶ main ▶ ls -l ports\ntotal 5\ndrwxr-xr-x  2 j3w1 j3w1  4096 Sep  6 09:12 alacritty\ndrwx------  2 j3w1 j3w1  4096 Sep  6 09:12 gtk\n-rw-r--r--  1 j3w1 j3w1  1180 Sep  6 09:12 README.md\n-rwxr-xr-x  1 j3w1 j3w1   512 Sep  6 09:12 verify.sh\nlrwxrwxrwx  1 j3w1 j3w1    11 Sep  6 09:12 xresources -> ../tokens/\n-rw-r--r--  1 j3w1 j3w1 20480 Sep  6 09:12 evidence.tar.gz\n ~/theme ▶ main ▶ cat ports/gtk/port.json\ncat: ports/gtk/port.json: No such file or directory\n ~/theme ▶ main ▶ npm run validate 
\n
\n
\n
title.js — editor
\n
\n
1// Compose the window title of the focused container.\n2import { Container } from \"./tree.js\";\n3const MAX_LENGTH = 48;\n4export function title(container) {\n5  const name = container.name ?? \"untitled…\";\n6  let label = `${name} (${container.children.length})`;\n7  if (label.length > MAX_LENGTH) {\n8    label = label.slice(0, MAX_LENGTH) + \"…\";\n9  }\n10  return escape(label); /* escape() is deprecated */\n11}\n12const broken = 0x1G;
\n
\n
\n
\n
", + "tabbed": "
\n
\n
\n \n \n \n
\n
\n 处理器 12%\n 内存储器 3.1G\n 局域网 up\n 电池 87%\n \n
\n
\n
\n
\n
\n \n \n
\n
\n
 ~/theme ▶ main ▶ ls -l ports\ntotal 5\ndrwxr-xr-x  2 j3w1 j3w1  4096 Sep  6 09:12 alacritty\ndrwx------  2 j3w1 j3w1  4096 Sep  6 09:12 gtk\n-rw-r--r--  1 j3w1 j3w1  1180 Sep  6 09:12 README.md\n-rwxr-xr-x  1 j3w1 j3w1   512 Sep  6 09:12 verify.sh\nlrwxrwxrwx  1 j3w1 j3w1    11 Sep  6 09:12 xresources -> ../tokens/\n-rw-r--r--  1 j3w1 j3w1 20480 Sep  6 09:12 evidence.tar.gz\n ~/theme ▶ main ▶ cat ports/gtk/port.json\ncat: ports/gtk/port.json: No such file or directory\n ~/theme ▶ main ▶ npm run validate 
\n
\n \n
\n
\n
", + "floating": "
\n
\n
\n \n \n \n
\n
\n 处理器 12%\n 内存储器 3.1G\n 局域网 up\n 电池 87%\n \n
\n
\n
\n
\n
~/theme — zsh
\n
 ~/theme ▶ main ▶ ls -l ports\ntotal 5\ndrwxr-xr-x  2 j3w1 j3w1  4096 Sep  6 09:12 alacritty\ndrwx------  2 j3w1 j3w1  4096 Sep  6 09:12 gtk\n-rw-r--r--  1 j3w1 j3w1  1180 Sep  6 09:12 README.md\n-rwxr-xr-x  1 j3w1 j3w1   512 Sep  6 09:12 verify.sh\nlrwxrwxrwx  1 j3w1 j3w1    11 Sep  6 09:12 xresources -> ../tokens/\n-rw-r--r--  1 j3w1 j3w1 20480 Sep  6 09:12 evidence.tar.gz\n ~/theme ▶ main ▶ cat ports/gtk/port.json\ncat: ports/gtk/port.json: No such file or directory\n ~/theme ▶ main ▶ npm run validate 
\n
\n
\n
title.js — editor
\n
\n
1// Compose the window title of the focused container.\n2import { Container } from \"./tree.js\";\n3const MAX_LENGTH = 48;\n4export function title(container) {\n5  const name = container.name ?? \"untitled…\";\n6  let label = `${name} (${container.children.length})`;\n7  if (label.length > MAX_LENGTH) {\n8    label = label.slice(0, MAX_LENGTH) + \"…\";\n9  }\n10  return escape(label); /* escape() is deprecated */\n11}\n12const broken = 0x1G;
\n
\n
\n
\n
" } diff --git a/packages/ui/dist/manifest.json b/packages/ui/dist/manifest.json index 19e66cbdf..7723a6690 100644 --- a/packages/ui/dist/manifest.json +++ b/packages/ui/dist/manifest.json @@ -27544,12 +27544,12 @@ "runtime/components/code-editor.js": "sha256-MMz8rm+dJT4XahXmR9ftmU0IhNW1NqLIHW7U3STXDPQ=", "runtime/chunks/display-Jm9bAsnb.js": "sha256-qZb1g04piEwY3lfFJwMe+0mXR218ljtVi8mepWxrFv8=", "tokens.css": "sha256-7A9Xv87HbmuVumnQtzllDxHGc2CPnurdpWWuBpEStJg=", - "component.css": "sha256-4LPA5bI5mlJBawZsawTWYAUm+rgCy7tGXqmR9+dNl4U=", + "component.css": "sha256-aa9zAzIlna+IPd+Xivi0WU385o/+RmhG5pRVR1vsE64=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", - "element.html": "sha256-aD+1gDxKB5fijO+A+hjuTqChvHPDv5zp5tK9UPZhwLc=", - "index.html": "sha256-fEiQeV/RgniP8X0ij1CkgNb0LNwR9atyMx9gXge/Sk8=", + "element.html": "sha256-yXGoyQ6QC1zx9v7pXmaH1J2StJS/EEc6ZMqWAgdNj6A=", + "index.html": "sha256-2pHlO7mTG0Z1FySFL7jnRFIidQEfcMXdM+OtJBsZeXA=", "README.md": "sha256-oP4WnaIDAzxwm22ndFvMgchWr7l/DH7YotacPAFZuO8=", - "manifest.json": "sha256-YW6ytfMdyrqpCbrZD4Z3OZT4SRpTTYbxhqsVf+bdeys=" + "manifest.json": "sha256-34XB9GRIxMUKi/v1n3Xa3EwEByberTg3XfCVREIe3rw=" } } }, @@ -33337,12 +33337,12 @@ "runtime/chunks/compositions-D57dCsBz.js": "sha256-PEpI/vGgdD+LSznUd0iedSxxVE+5QxIO7BGKeQnCRjo=", "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", "tokens.css": "sha256-7A9Xv87HbmuVumnQtzllDxHGc2CPnurdpWWuBpEStJg=", - "component.css": "sha256-flESdDVMoLb/4QOaPquO0Wn4iBig+NKOGV5Snjkhz8A=", + "component.css": "sha256-qnsF12iIL9s2blKkBo1Cq0iJ7btji7uOmjqmQId+1pY=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", - "element.html": "sha256-nNyvwUVLU3Rdy3x0UcZN+IkCA1+Ot5CVwjUB54GDnq8=", - "index.html": "sha256-5dYSTEhCTMSvtWC0ppGMuIR1wTY6xcAn1B4t+8ERTy8=", + "element.html": "sha256-r16RBHw/9BhmfwHsOtPnFIkDRIuIAmlN+RpR9z4LXMU=", + "index.html": "sha256-vsi84+uGu4rv5NlM/V/to85JQlSDYVg0XKREuwBARII=", "README.md": "sha256-C0hpJoSU0W6E5VFxM/5nRjno1clSop0NLti9ZjvJiO0=", - "manifest.json": "sha256-34QNQs09okyIve3C/VbLvsCxS9dX0aP441tZNe3h0O0=" + "manifest.json": "sha256-DHerFbvqjcRpd5y/PPXy6ADxs1R+eLxowrnBuzBvRuM=" } } }, diff --git a/packages/ui/dist/styles/code-editor.css b/packages/ui/dist/styles/code-editor.css index b3de21be6..070968813 100644 --- a/packages/ui/dist/styles/code-editor.css +++ b/packages/ui/dist/styles/code-editor.css @@ -85,6 +85,10 @@ j3w1-code-editor .code-editor-ws { color: var(--color-code-whitespace); } +j3w1-code-editor .code-editor-ws::before { + content: attr(data-whitespace); +} + j3w1-code-editor .code-editor-fold { display: inline-block; padding: 0 var(--space-4); diff --git a/packages/ui/dist/styles/i3-window-frame.css b/packages/ui/dist/styles/i3-window-frame.css index 592729ae6..ae3d69abc 100644 --- a/packages/ui/dist/styles/i3-window-frame.css +++ b/packages/ui/dist/styles/i3-window-frame.css @@ -523,6 +523,10 @@ j3w1-i3-window-frame .code-editor-ws { color: var(--color-code-whitespace); } +j3w1-i3-window-frame .code-editor-ws::before { + content: attr(data-whitespace); +} + j3w1-i3-window-frame .code-editor-fold { display: inline-block; padding: 0 var(--space-4); From e73a2e26b1bc6ecf00324629c7819da09350239c Mon Sep 17 00:00:00 2001 From: j3w1 Date: Wed, 14 Oct 2026 17:51:13 -0500 Subject: [PATCH 55/65] fix: resolve matrix styles from the raw composed specimens The normative demos can use more components than package examples, so discover their nested roots before building the scoped matrix CSS. Co-Authored-By: Claude Opus 5.5 --- site/src/pages/components/[id].astro | 17 +++++++++++++++-- tests/browser/reference-hub.spec.js | 7 +++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/site/src/pages/components/[id].astro b/site/src/pages/components/[id].astro index 120e795b0..ab40b3a92 100644 --- a/site/src/pages/components/[id].astro +++ b/site/src/pages/components/[id].astro @@ -3,6 +3,8 @@ import { getCollection } from "astro:content"; import ComponentSection from "../../components/ComponentSection.astro"; import SelectField from "../../components/fields/SelectField.astro"; import { profiles } from "../../lib/theme"; +import { parseFragment } from "parse5"; +import { attribute, walkMarkup } from "../../../../scripts/lib/markup.mjs"; import { cssSourceClosure } from "../../../../scripts/lib/ui-distribution.mjs"; import { scopeRecipeCss } from "../../../../scripts/lib/recipe-css.mjs"; import { definitions } from "../../../../packages/ui/src/catalogue.mjs"; @@ -23,9 +25,20 @@ const id = entry.id; const item = implementations.components.find((c) => c.id === id)!; const demoModules = import.meta.glob("/spec/components/*.demo.html", { query: "?raw", import: "default", eager: true }) as Record; const demo = demoModules[`/spec/components/${id}.demo.html`] ?? null; -const dependencies = [id, ...item.styleDependencies]; -const styleEntries = [...dependencies.map((name) => `components/${name}.css`), ...dependencies.flatMap((name) => definitions[name]?.extraStyles ?? []).map((file) => file.replace(/^site\/src\/styles\//, ""))]; const styleModules = import.meta.glob("../../styles/**/*.css", { query: "?raw", import: "default", eager: true }) as Record; +const dependencies = new Set(); +const addStyle = (name: string) => { + if (dependencies.has(name)) return; + dependencies.add(name); + for (const dependency of [...(definitions[name]?.styles ?? []), ...(definitions[name]?.dependencies ?? [])]) addStyle(dependency); +}; +[id, ...item.styleDependencies].forEach(addStyle); +// Raw specification demos can compose more parts than the package examples. +// Resolve their actual roots too; every dependency stays inside this matrix. +walkMarkup(parseFragment(demo ?? ""), (node) => { + for (const name of (attribute(node, "class") ?? "").split(/\s+/)) if (styleModules[`../../styles/components/${name}.css`]) addStyle(name); +}); +const styleEntries = [...[...dependencies].map((name) => `components/${name}.css`), ...[...dependencies].flatMap((name) => definitions[name]?.extraStyles ?? []).map((file) => file.replace(/^site\/src\/styles\//, ""))]; const matrixSources = await cssSourceClosure(".", styleEntries, { read: (file) => styleModules[`../../styles/${file}`] }); const matrixCss = [...matrixSources.values()].map((source) => scopeRecipeCss(source, { scope: `.reference-matrix-${id}`, keepStates: true })).join("\n"); const variants = examples[id]; diff --git a/tests/browser/reference-hub.spec.js b/tests/browser/reference-hub.spec.js index 3ae82fa3c..7f3bb8ed8 100644 --- a/tests/browser/reference-hub.spec.js +++ b/tests/browser/reference-hub.spec.js @@ -95,3 +95,10 @@ test("code-editor package and matrix render the same decorative whitespace glyph expect(specimen.width).toBeGreaterThan(0); expect(await shape(matrix)).toEqual(specimen); }); + +test("composed matrices keep their raw demo's nested wizard styles", scope, async ({ page }) => { + await page.goto("components/admin-form/"); + const step = page.locator('#admin-form-states [data-state="default"] .wizard-step-button').first(); + await expect(step).toHaveCSS("background-color", "rgba(0, 0, 0, 0)"); + await expect(step).toHaveCSS("border-bottom-width", "2px"); +}); From 06df0bc647ab0a7ca37c286d2d06153851bf25d6 Mon Sep 17 00:00:00 2001 From: j3w1 Date: Wed, 14 Oct 2026 17:51:13 -0500 Subject: [PATCH 56/65] chore: regenerate Generated artifacts remain current after the matrix dependency fix. Co-Authored-By: Claude Opus 5.5 From a84f87775dc8f6df5596361b8210d3a305e855d6 Mon Sep 17 00:00:00 2001 From: j3w1 Date: Wed, 14 Oct 2026 17:59:38 -0500 Subject: [PATCH 57/65] test: keep component evidence and token descriptions at their new homes Give the new component rendering checks explicit scopes and retain the original readable-description constraints in the token explorer. Co-Authored-By: Claude Opus 5.5 --- site/src/styles/chrome.css | 6 +++++- tests/browser/components/admin-form.spec.js | 9 ++++++++ tests/browser/components/code-editor.spec.js | 17 +++++++++++++++ tests/browser/reference-hub.spec.js | 22 -------------------- tests/browser/spec-tables.spec.js | 9 ++++++++ 5 files changed, 40 insertions(+), 23 deletions(-) create mode 100644 tests/browser/components/admin-form.spec.js create mode 100644 tests/browser/components/code-editor.spec.js diff --git a/site/src/styles/chrome.css b/site/src/styles/chrome.css index bcc99c15d..36c3151ea 100644 --- a/site/src/styles/chrome.css +++ b/site/src/styles/chrome.css @@ -369,10 +369,14 @@ html:not(.js) .js-only { wraps only at its dots (), never inside a segment, and keeps one line where there is room. */ .usage-section .table-cell:first-child, -.site-main .table-scroll > table :is(th, td) { +.site-main :is(.table-scroll, .site-table-wrap) > table :is(th, td) { overflow-wrap: normal; } +.usage-section .table-cell:last-child { + min-width: 24ch; +} + @media (min-width: 600px) { .usage-section .table-cell:first-child { white-space: nowrap; diff --git a/tests/browser/components/admin-form.spec.js b/tests/browser/components/admin-form.spec.js new file mode 100644 index 000000000..f9ad9d61c --- /dev/null +++ b/tests/browser/components/admin-form.spec.js @@ -0,0 +1,9 @@ +import { test, expect } from "../evidence-fixture.mjs"; +import { verification } from "../verification.mjs"; + +test("composed matrices keep their raw demo's nested wizard styles", verification({ component: "admin-form", category: "rendering", states: ["default"], variants: ["default"], note: "Default matrix variant, first wizard step: exact transparent fill and 2px edge. Rendering only; no wizard behavior or complete state coverage claim." }), async ({ page }) => { + await page.goto("components/admin-form/"); + const step = page.locator('#admin-form-states [data-state="default"] .wizard-step-button').first(); + await expect(step).toHaveCSS("background-color", "rgba(0, 0, 0, 0)"); + await expect(step).toHaveCSS("border-bottom-width", "2px"); +}); diff --git a/tests/browser/components/code-editor.spec.js b/tests/browser/components/code-editor.spec.js new file mode 100644 index 000000000..d3c4cd690 --- /dev/null +++ b/tests/browser/components/code-editor.spec.js @@ -0,0 +1,17 @@ +import { test, expect } from "../evidence-fixture.mjs"; +import { verification } from "../verification.mjs"; + +test("code-editor package and matrix render the same decorative whitespace glyphs", verification({ component: "code-editor", category: "rendering", states: ["default"], variants: ["default"], note: "Exact CSS-generated glyphs, colour and geometry in the default package example and default matrix cell; no editor behavior or other state claim." }), async ({ page }) => { + await page.goto("components/code-editor/"); + const shape = (locator) => locator.evaluate((el) => { + const style = getComputedStyle(el, "::before"), rect = el.getBoundingClientRect(); + return { glyphs: style.content, color: style.color, width: rect.width, height: rect.height, text: el.textContent }; + }); + const live = page.locator("j3w1-code-editor .code-editor-ws").first(); + const matrix = page.locator('#code-editor-states [data-state="default"] .code-editor-ws').first(); + const specimen = await shape(live); + expect(specimen.text).toBe(""); + expect(specimen.glyphs).toBe('"··"'); + expect(specimen.width).toBeGreaterThan(0); + expect(await shape(matrix)).toEqual(specimen); +}); diff --git a/tests/browser/reference-hub.spec.js b/tests/browser/reference-hub.spec.js index 7f3bb8ed8..fa2ff9e17 100644 --- a/tests/browser/reference-hub.spec.js +++ b/tests/browser/reference-hub.spec.js @@ -80,25 +80,3 @@ test("matrix forcing stays scoped and chrome stays compact when specimens change await expect(page.locator("html")).toHaveAttribute("data-density", "compact"); await expect(page.locator("#button-states")).toHaveAttribute("data-density", "comfortable"); }); - -test("code-editor package and matrix render the same decorative whitespace glyphs", scope, async ({ page }) => { - await page.goto("components/code-editor/"); - const shape = (locator) => locator.evaluate((el) => { - const style = getComputedStyle(el, "::before"), rect = el.getBoundingClientRect(); - return { glyphs: style.content, color: style.color, width: rect.width, height: rect.height, text: el.textContent }; - }); - const live = page.locator("j3w1-code-editor .code-editor-ws").first(); - const matrix = page.locator('#code-editor-states [data-state="default"] .code-editor-ws').first(); - const specimen = await shape(live); - expect(specimen.text).toBe(""); - expect(specimen.glyphs).toBe('"··"'); - expect(specimen.width).toBeGreaterThan(0); - expect(await shape(matrix)).toEqual(specimen); -}); - -test("composed matrices keep their raw demo's nested wizard styles", scope, async ({ page }) => { - await page.goto("components/admin-form/"); - const step = page.locator('#admin-form-states [data-state="default"] .wizard-step-button').first(); - await expect(step).toHaveCSS("background-color", "rgba(0, 0, 0, 0)"); - await expect(step).toHaveCSS("border-bottom-width", "2px"); -}); diff --git a/tests/browser/spec-tables.spec.js b/tests/browser/spec-tables.spec.js index 8a15e0d68..c08390c49 100644 --- a/tests/browser/spec-tables.spec.js +++ b/tests/browser/spec-tables.spec.js @@ -32,4 +32,13 @@ test("documentation tables keep readable columns and compact copy controls", ver expect(await region.evaluate((el) => el.scrollWidth <= el.clientWidth)).toBe(true); await page.locator("#t-color-border").screenshot({ path: "test-results/compact-border-table.png" }); } + // Descriptions and the other profile values moved to the token explorer. + // Keep the original readable-description constraints at their new home. + await page.goto("tokens/", { waitUntil: "networkidle" }); + const description = page.locator('[data-usage-profile="default"] [data-usage-path="color.border.active"]'); + const usage = await description.evaluate((row) => ({ width: row.cells[3].getBoundingClientRect().width, height: row.getBoundingClientRect().height, wrap: getComputedStyle(row.cells[3]).overflowWrap })); + expect(usage.width).toBeGreaterThanOrEqual(180); + expect(usage.height).toBeLessThanOrEqual(112); + expect(usage.wrap).toBe("normal"); + }); From b0a5ebc3cccff97380c1a157e6bcdec0864947b5 Mon Sep 17 00:00:00 2001 From: j3w1 Date: Wed, 14 Oct 2026 17:59:38 -0500 Subject: [PATCH 58/65] chore: regenerate Co-Authored-By: Claude Opus 5.5 --- README.md | 4 ++-- exports/components/admin-form.json | 4 ++-- exports/components/code-editor.json | 4 ++-- exports/coverage.json | 16 ++++++++-------- exports/digests.json | 14 +++++++------- exports/forms/identity.json | 2 +- exports/patterns/validation-recovery.json | 4 ++-- exports/task-inputs.json | 4 ++-- exports/theme.full.md | 4 ++-- packages/ui/dist/canonical/admin-form.json | 4 ++-- packages/ui/dist/canonical/code-editor.json | 4 ++-- ...lder-CTZPEyyR.js => form-builder-BIuY34V0.js} | 4 ++-- ...lder-B1mkqdgN.js => form-builder-DC0FAN8u.js} | 2 +- packages/ui/dist/components/form-builder.js | 2 +- packages/ui/dist/contracts/form-builder.json | 2 +- packages/ui/dist/copy/form-builder/manifest.json | 10 +++++----- ...lder-CTZPEyyR.js => form-builder-BIuY34V0.js} | 4 ++-- ...lder-B1mkqdgN.js => form-builder-DC0FAN8u.js} | 2 +- .../runtime/register/form-builder.js | 2 +- packages/ui/dist/enhance/form-builder.js | 2 +- packages/ui/dist/index.js | 2 +- packages/ui/dist/manifest.json | 8 ++++---- packages/ui/dist/register/form-builder.js | 2 +- 23 files changed, 53 insertions(+), 53 deletions(-) rename packages/ui/dist/chunks/{form-builder-CTZPEyyR.js => form-builder-BIuY34V0.js} (92%) rename packages/ui/dist/chunks/{form-builder-B1mkqdgN.js => form-builder-DC0FAN8u.js} (99%) rename packages/ui/dist/copy/form-builder/runtime/chunks/{form-builder-CTZPEyyR.js => form-builder-BIuY34V0.js} (92%) rename packages/ui/dist/copy/form-builder/runtime/chunks/{form-builder-B1mkqdgN.js => form-builder-DC0FAN8u.js} (99%) diff --git a/README.md b/README.md index 84bcc6730..d5f4895ed 100644 --- a/README.md +++ b/README.md @@ -254,7 +254,7 @@ the sources. | Component | Family | Priority | Specified | Demonstrated | Test implemented | | --- | --- | --- | --- | --- | --- | -| `admin-form` | composed | R1 | yes | yes | — | +| `admin-form` | composed | R1 | yes | yes | yes | | `alert` | feedback | R1 | yes | yes | — | | `avatar` | display | R2 | yes | yes | — | | `badge` | display | R1 | yes | yes | — | @@ -265,7 +265,7 @@ the sources. | `chart` | display | R2 | yes | yes | — | | `checkbox` | forms-basic | R1 | yes | yes | yes | | `chip` | display | R1 | yes | yes | — | -| `code-editor` | developer | R1 | yes | yes | — | +| `code-editor` | developer | R1 | yes | yes | yes | | `combobox` | forms-advanced | R1 | yes | yes | — | | `command-palette` | navigation | R2 | yes | yes | — | | `compact-dashboard` | composed | R2 | yes | yes | — | diff --git a/exports/components/admin-form.json b/exports/components/admin-form.json index 66acefa0d..9f3d356ad 100644 --- a/exports/components/admin-form.json +++ b/exports/components/admin-form.json @@ -20,8 +20,8 @@ "maturity": "stable", "specified": true, "demonstrated": true, - "tested": false, - "testImplemented": false, + "tested": true, + "testImplemented": true, "states": 4 }, "title": "Admin form", diff --git a/exports/components/code-editor.json b/exports/components/code-editor.json index 0ccdfcd15..08c5b92e0 100644 --- a/exports/components/code-editor.json +++ b/exports/components/code-editor.json @@ -20,8 +20,8 @@ "maturity": "stable", "specified": true, "demonstrated": true, - "tested": false, - "testImplemented": false, + "tested": true, + "testImplemented": true, "states": 6 }, "title": "Code editor", diff --git a/exports/coverage.json b/exports/coverage.json index 666969a50..6257ae3fa 100644 --- a/exports/coverage.json +++ b/exports/coverage.json @@ -12,8 +12,8 @@ "composed": { "specified": 6, "demonstrated": 6, - "tested": 0, - "testImplemented": 0, + "tested": 1, + "testImplemented": 1, "total": 6 }, "feedback": { @@ -54,8 +54,8 @@ "developer": { "specified": 5, "demonstrated": 5, - "tested": 0, - "testImplemented": 0, + "tested": 1, + "testImplemented": 1, "total": 5 }, "forms-advanced": { @@ -73,8 +73,8 @@ "maturity": "stable", "specified": true, "demonstrated": true, - "tested": false, - "testImplemented": false, + "tested": true, + "testImplemented": true, "states": 4 }, "alert": { @@ -183,8 +183,8 @@ "maturity": "stable", "specified": true, "demonstrated": true, - "tested": false, - "testImplemented": false, + "tested": true, + "testImplemented": true, "states": 6 }, "combobox": { diff --git a/exports/digests.json b/exports/digests.json index 9575b18c7..b3a381f5b 100644 --- a/exports/digests.json +++ b/exports/digests.json @@ -5,7 +5,7 @@ "algorithm": "sha256 over the file bytes with LF line endings, base64", "files": { "exports/components/admin-form.brief.txt": "sha256-E334XMUjnvF/ARd2JJc9QbdJ1F2ZtUbuohumVQNGxq4=", - "exports/components/admin-form.json": "sha256-dv7FBoityiC4faBsh2o8TPuu40l1RK5+6vfP8K8elw0=", + "exports/components/admin-form.json": "sha256-JU/17CskZXa8U3MGCziDqStEWPRLkvxtnAfDUUjDWxk=", "exports/components/alert.brief.txt": "sha256-lkyUAEUNqjaIQfTEZWG0Z56GazvtCHF56haqELEl4yg=", "exports/components/alert.json": "sha256-LdVX0qQl/h0t5q9i0u4ie75n1vmFS7MVrPG1Hv3E0sA=", "exports/components/avatar.brief.txt": "sha256-OK9zDfknpgSHuYXaJIVsQkS5SD/48hVaAWWOclgzsqk=", @@ -27,7 +27,7 @@ "exports/components/chip.brief.txt": "sha256-zrwPl3mt5TXcta1D6RIk4u/T9R7jV3Xoi0aAk7yD0kY=", "exports/components/chip.json": "sha256-LF+a3rmnUtcjJBjN6xmbwek9NFGu/qevFnR7Ag+BJJY=", "exports/components/code-editor.brief.txt": "sha256-oYeBmZUD+1xkftcF1BGMxKSq4ggWFtMLex8SF4NmjYU=", - "exports/components/code-editor.json": "sha256-VImzTzfsBrRO+NhV34nwTM/OQQklhJknOGA4yYnf64s=", + "exports/components/code-editor.json": "sha256-j3AQ/vXXJNlTQPoz2Wg+gD7bEDfTMa7ICyPrsmJZIfE=", "exports/components/combobox.brief.txt": "sha256-ci4vDHAWRvXIJJ1pQh5zRO/gBdJ0gy6Nfrpb96D8dYQ=", "exports/components/combobox.json": "sha256-P5vatMPCPfZYNIvM0WbEglG7Qw4wVrYGkLeTmPjoPJM=", "exports/components/command-palette.brief.txt": "sha256-1ktoWaNb4dH3Q8gOZJCke3N+HQM5PzQOiGtJLJCd4ho=", @@ -140,12 +140,12 @@ "exports/components/wizard.json": "sha256-Sq72bqXUL4wXCo7QeH3t+HqRYofjRlXRQ1FZBtyhD5s=", "exports/contrast.json": "sha256-9ygxhWhcIcixQ0PPunk+9pBP+5SiYXuPEeQr/ccO9gg=", "exports/contrast.md": "sha256-X9h7E/hCNnXjAAGaXsyeP8VkvaomtK0M+yCYpHZ/mLI=", - "exports/coverage.json": "sha256-FeuiH5WV9i3ILuDqqcloRbL6pCMOoA3qZeoMEv1HdDU=", + "exports/coverage.json": "sha256-TDMhez0DbbSrBmG57EbOZCiY1MBsbbBTfLHE2OIL/hc=", "exports/figma/importer.mjs": "sha256-VXfdSuZ1eYqKIIadm4JI73kT9Or0PTracOyncWAsbnI=", - "exports/forms/identity.json": "sha256-8C+WWcW4f0EyNinN31ax8EMIPyrIZbSKbkEGb+gX6m4=", + "exports/forms/identity.json": "sha256-p61wcGz3/P2k6xe92IA9zJmATcQMWOOT8eVSYvupUE8=", "exports/forms/templates.json": "sha256-k2e6tcvD0k6hUCU+l+1itDIeEGjAzxvq8bCmewl8XRg=", "exports/llms.txt": "sha256-Bzchjr9xc74FBFmz0hwbl9kjJBWCV/L8ZL/q+NvFOm8=", - "exports/patterns/validation-recovery.json": "sha256-b95jcFXXQwDfEeAmRXyixmv4/1iYt0I17C0bwc+HaFA=", + "exports/patterns/validation-recovery.json": "sha256-HuJHCQbbjWl/7tw2y8z1LytwDLoUdJZtELU9bcZlVZo=", "exports/port-capabilities.json": "sha256-6u3M0mXA+lN5FLjtOJvRkLpcFNePSv8ZUMpIiVohxVQ=", "exports/recipes/button/LICENSE.md": "sha256-vVf/G6WKJRqbyGZCppbAxMh+UAJdSzaPt5xWUujehyU=", "exports/recipes/button/README.md": "sha256-x4lEz+IoqPMXycbNllyu5pCAUoYYeQE2sYbSC92rhf8=", @@ -178,9 +178,9 @@ "exports/recipes/text-field/template.html": "sha256-IlSlLS7sPC3MLqIdxMRQUP4sFnn/58lwM3AFALtdY3c=", "exports/recipes/text-field/tokens.css": "sha256-Z7C9Hx+UzJAtRTBN08cB9BRDeTuCjEQr3xZyD2i0vgU=", "exports/recipes/text-field/two-instances.html": "sha256-JIl9HQHQPYXg+r8lkFfC0x50KKiLyNWAwYm9mdQXGGw=", - "exports/task-inputs.json": "sha256-9DYRnfyuUASZDqPmD3BuJ91I914+0REFirf3ygui5Wo=", + "exports/task-inputs.json": "sha256-GiFLgaRdDafFIjI4c1F4B6oO9qHwacJbUIlMqh4schk=", "exports/theme.compact.md": "sha256-QyPWc0W2dQcJgzifdT+JJWZ0dCKNcS56+p7SYogxShc=", - "exports/theme.full.md": "sha256-mtmdZ2yV3SFr1fldtmVPCMwLitps18AG8KOZmPuO3Vk=", + "exports/theme.full.md": "sha256-J6T6M6KkWmfHoX0HIcSVNfPRpkkO4gQsRkn8r6q/YNY=", "exports/token-usage.json": "sha256-2zZkZAezj2qzczffMftBaaz7UmIqu/sEodle7PsbZeE=", "exports/tokens.css": "sha256-ePraUzvnHrCsJIZ1frkOqaHPFHo7iT+aE6wrL4ian68=", "exports/tokens.resolved.json": "sha256-3KBrfmIiz4L6Qyqvi99TdTe4+5NeuA0ZWZe3Am4sRo4=" diff --git a/exports/forms/identity.json b/exports/forms/identity.json index 21d491bfd..07bd89fb6 100644 --- a/exports/forms/identity.json +++ b/exports/forms/identity.json @@ -2,5 +2,5 @@ "name": "j3w1-theme", "version": "4.0.0", "profile": "default", - "sourceDigest": "sha256-8kMjtT3OuVgw1t/LJAA5p5KM/AINN0HyLLLk77RyK1w=" + "sourceDigest": "sha256-/R0d6ZxFmURX7hxRGoaE98meOolxJ1yEbyAtdq+BzVw=" } diff --git a/exports/patterns/validation-recovery.json b/exports/patterns/validation-recovery.json index 8dfed5cc7..df54f557c 100644 --- a/exports/patterns/validation-recovery.json +++ b/exports/patterns/validation-recovery.json @@ -152,10 +152,10 @@ "name": "j3w1-theme", "version": "4.0.0", "profile": "default", - "sourceDigest": "sha256-8kMjtT3OuVgw1t/LJAA5p5KM/AINN0HyLLLk77RyK1w=" + "sourceDigest": "sha256-/R0d6ZxFmURX7hxRGoaE98meOolxJ1yEbyAtdq+BzVw=" }, "componentDigests": { - "admin-form": "sha256-dv7FBoityiC4faBsh2o8TPuu40l1RK5+6vfP8K8elw0=", + "admin-form": "sha256-JU/17CskZXa8U3MGCziDqStEWPRLkvxtnAfDUUjDWxk=", "alert": "sha256-LdVX0qQl/h0t5q9i0u4ie75n1vmFS7MVrPG1Hv3E0sA=", "button": "sha256-1opy//nTZ7HCWCxVBLKb4xfwUID7KU09tLwplxEg8IA=", "checkbox": "sha256-/WsERzh7E9dWQds8YoXcv6sY6vc6xb6+/RKCpLtJC6Q=", diff --git a/exports/task-inputs.json b/exports/task-inputs.json index eedf3d84d..8f408c94e 100644 --- a/exports/task-inputs.json +++ b/exports/task-inputs.json @@ -1004,7 +1004,7 @@ }, "files": { "agents/consume.md": "sha256-I7gvGchrdAXnxI1VpW1sIodxyPy9hNvveANaO2p7h8w=", - "exports/components/admin-form.json": "sha256-dv7FBoityiC4faBsh2o8TPuu40l1RK5+6vfP8K8elw0=", + "exports/components/admin-form.json": "sha256-JU/17CskZXa8U3MGCziDqStEWPRLkvxtnAfDUUjDWxk=", "exports/components/alert.json": "sha256-LdVX0qQl/h0t5q9i0u4ie75n1vmFS7MVrPG1Hv3E0sA=", "exports/components/avatar.json": "sha256-2PA7MYpHSJ4aY0u4OuQvSpWnJUhZ+izX6HEVNbdJSTA=", "exports/components/badge.json": "sha256-5tutit9V6Qn6RDS7T5QHIMd17ZnmNuTGVtWanepzwP0=", @@ -1015,7 +1015,7 @@ "exports/components/chart.json": "sha256-/UOQIj79vFwq31dFBkBI1wOQImDwyc6SQukub59W02U=", "exports/components/checkbox.json": "sha256-/WsERzh7E9dWQds8YoXcv6sY6vc6xb6+/RKCpLtJC6Q=", "exports/components/chip.json": "sha256-LF+a3rmnUtcjJBjN6xmbwek9NFGu/qevFnR7Ag+BJJY=", - "exports/components/code-editor.json": "sha256-VImzTzfsBrRO+NhV34nwTM/OQQklhJknOGA4yYnf64s=", + "exports/components/code-editor.json": "sha256-j3AQ/vXXJNlTQPoz2Wg+gD7bEDfTMa7ICyPrsmJZIfE=", "exports/components/combobox.json": "sha256-P5vatMPCPfZYNIvM0WbEglG7Qw4wVrYGkLeTmPjoPJM=", "exports/components/command-palette.json": "sha256-MUI21koqQqSJ8O0i0vFS1mf/265RLZa5NyYSKWmbzxQ=", "exports/components/compact-dashboard.json": "sha256-0wWZDoSoLy5um+ixPo3IOXd1+B9Z46JxulIg61EPY2A=", diff --git a/exports/theme.full.md b/exports/theme.full.md index 59df7e11b..b7eaa2070 100644 --- a/exports/theme.full.md +++ b/exports/theme.full.md @@ -7432,7 +7432,7 @@ Unlabelled controls, color-only status, drag-only operations, hidden required in | Component | Family | Priority | Specified | Demonstrated | Test implemented | | --- | --- | --- | --- | --- | --- | -| `admin-form` | composed | R1 | yes | yes | — | +| `admin-form` | composed | R1 | yes | yes | yes | | `alert` | feedback | R1 | yes | yes | — | | `avatar` | display | R2 | yes | yes | — | | `badge` | display | R1 | yes | yes | — | @@ -7443,7 +7443,7 @@ Unlabelled controls, color-only status, drag-only operations, hidden required in | `chart` | display | R2 | yes | yes | — | | `checkbox` | forms-basic | R1 | yes | yes | yes | | `chip` | display | R1 | yes | yes | — | -| `code-editor` | developer | R1 | yes | yes | — | +| `code-editor` | developer | R1 | yes | yes | yes | | `combobox` | forms-advanced | R1 | yes | yes | — | | `command-palette` | navigation | R2 | yes | yes | — | | `compact-dashboard` | composed | R2 | yes | yes | — | diff --git a/packages/ui/dist/canonical/admin-form.json b/packages/ui/dist/canonical/admin-form.json index 66acefa0d..9f3d356ad 100644 --- a/packages/ui/dist/canonical/admin-form.json +++ b/packages/ui/dist/canonical/admin-form.json @@ -20,8 +20,8 @@ "maturity": "stable", "specified": true, "demonstrated": true, - "tested": false, - "testImplemented": false, + "tested": true, + "testImplemented": true, "states": 4 }, "title": "Admin form", diff --git a/packages/ui/dist/canonical/code-editor.json b/packages/ui/dist/canonical/code-editor.json index 0ccdfcd15..08c5b92e0 100644 --- a/packages/ui/dist/canonical/code-editor.json +++ b/packages/ui/dist/canonical/code-editor.json @@ -20,8 +20,8 @@ "maturity": "stable", "specified": true, "demonstrated": true, - "tested": false, - "testImplemented": false, + "tested": true, + "testImplemented": true, "states": 6 }, "title": "Code editor", diff --git a/packages/ui/dist/chunks/form-builder-CTZPEyyR.js b/packages/ui/dist/chunks/form-builder-BIuY34V0.js similarity index 92% rename from packages/ui/dist/chunks/form-builder-CTZPEyyR.js rename to packages/ui/dist/chunks/form-builder-BIuY34V0.js index dca3add88..ffb064c04 100644 --- a/packages/ui/dist/chunks/form-builder-CTZPEyyR.js +++ b/packages/ui/dist/chunks/form-builder-BIuY34V0.js @@ -1,5 +1,5 @@ import { t as J3w1Element } from "./element-Dovcr9Ky.js"; -import { t as mountBuilder } from "./form-builder-B1mkqdgN.js"; +import { t as mountBuilder } from "./form-builder-DC0FAN8u.js"; //#region packages/ui/src/behaviors/form-builder.js function formBuilder(root, { signal }) { const editor = root.querySelector("[data-builder]"); @@ -22,7 +22,7 @@ function formBuilder(root, { signal }) { var J3w1FormBuilder = class extends J3w1Element { static componentId = "form-builder"; static version = "4.0.0"; - static implementationId = "sha256-JbCCfV5XgdJLLbw0IEEdzxcmST/xCWbU6t+ZvhWXUR0="; + static implementationId = "sha256-57hpTH5ofeT2toGa8tkOrbmL0htG4TRCnTPRHYerRbk="; static connect = formBuilder; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/chunks/form-builder-B1mkqdgN.js b/packages/ui/dist/chunks/form-builder-DC0FAN8u.js similarity index 99% rename from packages/ui/dist/chunks/form-builder-B1mkqdgN.js rename to packages/ui/dist/chunks/form-builder-DC0FAN8u.js index a02c4ca1c..c982b10a8 100644 --- a/packages/ui/dist/chunks/form-builder-B1mkqdgN.js +++ b/packages/ui/dist/chunks/form-builder-DC0FAN8u.js @@ -69,7 +69,7 @@ var identity_default = { name: "j3w1-theme", version: "4.0.0", profile: "default", - sourceDigest: "sha256-8kMjtT3OuVgw1t/LJAA5p5KM/AINN0HyLLLk77RyK1w=" + sourceDigest: "sha256-/R0d6ZxFmURX7hxRGoaE98meOolxJ1yEbyAtdq+BzVw=" }; //#endregion //#region packages/ui/src/internal/form-builder.js diff --git a/packages/ui/dist/components/form-builder.js b/packages/ui/dist/components/form-builder.js index 4541a61f0..c0aff7661 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-CTZPEyyR.js"; +export { t as J3w1FormBuilder } from "../chunks/form-builder-BIuY34V0.js"; diff --git a/packages/ui/dist/contracts/form-builder.json b/packages/ui/dist/contracts/form-builder.json index e42cf8e63..587de755e 100644 --- a/packages/ui/dist/contracts/form-builder.json +++ b/packages/ui/dist/contracts/form-builder.json @@ -878,6 +878,6 @@ "copy": { "directory": "copy/form-builder/", "manifest": "copy/form-builder/manifest.json", - "digest": "sha256-FZlzwRsgOgkquCohP+sWl01sRfEPrDGBlKaYP7Y3blo=" + "digest": "sha256-tGUJOkXCRAInDYjVuUq9cOrjL4+SEdadQhBNKcqsvnA=" } } diff --git a/packages/ui/dist/copy/form-builder/manifest.json b/packages/ui/dist/copy/form-builder/manifest.json index 7227eca36..8c4ac9102 100644 --- a/packages/ui/dist/copy/form-builder/manifest.json +++ b/packages/ui/dist/copy/form-builder/manifest.json @@ -7,17 +7,17 @@ "register/form-builder.js", "chunks/element-Dovcr9Ky.js", "chunks/choice-B7mo5Eq3.js", - "chunks/form-builder-CTZPEyyR.js", - "chunks/form-builder-B1mkqdgN.js", + "chunks/form-builder-BIuY34V0.js", + "chunks/form-builder-DC0FAN8u.js", "chunks/form-workflow-BKRLylvq.js", "chunks/markup-DeQ4bEMR.js" ], "files": { - "runtime/register/form-builder.js": "sha256-e1OVezJh54OxRXbICIcjAa9BvCAZAzuX2ojL58aZoNk=", + "runtime/register/form-builder.js": "sha256-8e6ImYlCerWT8qxtjtoX2TzQNv+2cQQOr3vS5IyPSV8=", "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/chunks/form-builder-CTZPEyyR.js": "sha256-3IBfXzhC/FDnqs1I39v4xaE1szykc+SfHJIHKpTRKIQ=", - "runtime/chunks/form-builder-B1mkqdgN.js": "sha256-oOyIEJTvJfvI006mFZpAJ3fr5f9tceAp0Wjsgy4OqUk=", + "runtime/chunks/form-builder-BIuY34V0.js": "sha256-L16G/CwwyHubIUj+r8dO9hSmAgLsovtyes4MPMd9X+Q=", + "runtime/chunks/form-builder-DC0FAN8u.js": "sha256-LbCKOvUYahzLPW9B2xSIwHTPgurlGAXoJhoq0wUpRTE=", "runtime/chunks/form-workflow-BKRLylvq.js": "sha256-LcDxqsGpnid91QErVgWLIaXtB5KQS8Uad6Q2shJ1Ohc=", "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", "tokens.css": "sha256-7A9Xv87HbmuVumnQtzllDxHGc2CPnurdpWWuBpEStJg=", diff --git a/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-CTZPEyyR.js b/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-BIuY34V0.js similarity index 92% rename from packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-CTZPEyyR.js rename to packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-BIuY34V0.js index dca3add88..ffb064c04 100644 --- a/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-CTZPEyyR.js +++ b/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-BIuY34V0.js @@ -1,5 +1,5 @@ import { t as J3w1Element } from "./element-Dovcr9Ky.js"; -import { t as mountBuilder } from "./form-builder-B1mkqdgN.js"; +import { t as mountBuilder } from "./form-builder-DC0FAN8u.js"; //#region packages/ui/src/behaviors/form-builder.js function formBuilder(root, { signal }) { const editor = root.querySelector("[data-builder]"); @@ -22,7 +22,7 @@ function formBuilder(root, { signal }) { var J3w1FormBuilder = class extends J3w1Element { static componentId = "form-builder"; static version = "4.0.0"; - static implementationId = "sha256-JbCCfV5XgdJLLbw0IEEdzxcmST/xCWbU6t+ZvhWXUR0="; + static implementationId = "sha256-57hpTH5ofeT2toGa8tkOrbmL0htG4TRCnTPRHYerRbk="; static connect = formBuilder; static upgradeProperties = [ "disabled", diff --git a/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-B1mkqdgN.js b/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-DC0FAN8u.js similarity index 99% rename from packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-B1mkqdgN.js rename to packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-DC0FAN8u.js index a02c4ca1c..c982b10a8 100644 --- a/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-B1mkqdgN.js +++ b/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-DC0FAN8u.js @@ -69,7 +69,7 @@ var identity_default = { name: "j3w1-theme", version: "4.0.0", profile: "default", - sourceDigest: "sha256-8kMjtT3OuVgw1t/LJAA5p5KM/AINN0HyLLLk77RyK1w=" + sourceDigest: "sha256-/R0d6ZxFmURX7hxRGoaE98meOolxJ1yEbyAtdq+BzVw=" }; //#endregion //#region packages/ui/src/internal/form-builder.js 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 364463956..bf38d42be 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,5 +1,5 @@ import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; -import { t as J3w1FormBuilder } from "../chunks/form-builder-CTZPEyyR.js"; +import { t as J3w1FormBuilder } from "../chunks/form-builder-BIuY34V0.js"; //#region .cache/ui-build/entries/register/form-builder.js var element = registerElement("j3w1-form-builder", J3w1FormBuilder); //#endregion diff --git a/packages/ui/dist/enhance/form-builder.js b/packages/ui/dist/enhance/form-builder.js index 49c9818ac..846197f8e 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-B1mkqdgN.js"; +export { t as mountBuilder } from "../chunks/form-builder-DC0FAN8u.js"; diff --git a/packages/ui/dist/index.js b/packages/ui/dist/index.js index 543e0d979..1db5f952a 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-CTZPEyyR.js"; +import { t as J3w1FormBuilder } from "./chunks/form-builder-BIuY34V0.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 7723a6690..867579a4c 100644 --- a/packages/ui/dist/manifest.json +++ b/packages/ui/dist/manifest.json @@ -12932,11 +12932,11 @@ "copy": { "directory": "copy/form-builder/", "files": { - "runtime/register/form-builder.js": "sha256-e1OVezJh54OxRXbICIcjAa9BvCAZAzuX2ojL58aZoNk=", + "runtime/register/form-builder.js": "sha256-8e6ImYlCerWT8qxtjtoX2TzQNv+2cQQOr3vS5IyPSV8=", "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/chunks/form-builder-CTZPEyyR.js": "sha256-3IBfXzhC/FDnqs1I39v4xaE1szykc+SfHJIHKpTRKIQ=", - "runtime/chunks/form-builder-B1mkqdgN.js": "sha256-oOyIEJTvJfvI006mFZpAJ3fr5f9tceAp0Wjsgy4OqUk=", + "runtime/chunks/form-builder-BIuY34V0.js": "sha256-L16G/CwwyHubIUj+r8dO9hSmAgLsovtyes4MPMd9X+Q=", + "runtime/chunks/form-builder-DC0FAN8u.js": "sha256-LbCKOvUYahzLPW9B2xSIwHTPgurlGAXoJhoq0wUpRTE=", "runtime/chunks/form-workflow-BKRLylvq.js": "sha256-LcDxqsGpnid91QErVgWLIaXtB5KQS8Uad6Q2shJ1Ohc=", "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", "tokens.css": "sha256-7A9Xv87HbmuVumnQtzllDxHGc2CPnurdpWWuBpEStJg=", @@ -12945,7 +12945,7 @@ "element.html": "sha256-WUjDiy4tZKp/CS/g5I/hIUQY0Mci0zrItPW5k4K7As4=", "index.html": "sha256-640gpCzARRbVwXUct1TM0s5GcegFiYevcWBsg7VSOqI=", "README.md": "sha256-MGlPh4CEW6DLecBSj7Ym9ww3NAGe8r5V9uANRpZLY48=", - "manifest.json": "sha256-FZlzwRsgOgkquCohP+sWl01sRfEPrDGBlKaYP7Y3blo=" + "manifest.json": "sha256-tGUJOkXCRAInDYjVuUq9cOrjL4+SEdadQhBNKcqsvnA=" } } }, diff --git a/packages/ui/dist/register/form-builder.js b/packages/ui/dist/register/form-builder.js index 364463956..bf38d42be 100644 --- a/packages/ui/dist/register/form-builder.js +++ b/packages/ui/dist/register/form-builder.js @@ -1,5 +1,5 @@ import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; -import { t as J3w1FormBuilder } from "../chunks/form-builder-CTZPEyyR.js"; +import { t as J3w1FormBuilder } from "../chunks/form-builder-BIuY34V0.js"; //#region .cache/ui-build/entries/register/form-builder.js var element = registerElement("j3w1-form-builder", J3w1FormBuilder); //#endregion From 349d39b2b13d983f492b7e5c5b245612e54ae518 Mon Sep 17 00:00:00 2001 From: j3w1 Date: Wed, 14 Oct 2026 18:19:44 -0500 Subject: [PATCH 59/65] docs: describe the site as a reference hub with detail pages The package description and the Astro config comment still called the site a single page; the reference is now a static hub whose detail lives on per-component, contrast and decision pages. Co-Authored-By: Claude Opus 5.5 --- astro.config.mjs | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/astro.config.mjs b/astro.config.mjs index 20a47ec48..6b483dd80 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -1,4 +1,4 @@ -// The site is one static page deployed under /theme/ on GitHub Pages. Every +// The site is a static portal deployed under /theme/ on GitHub Pages. Every // value on the page comes from tokens/ and spec/; Astro owns no truth. See // spec/decisions.md D-010 and D-012, and tests/dist/ for the base-path gate. diff --git a/package.json b/package.json index 3e1d292d9..963654156 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "4.0.0", "private": true, "type": "module", - "description": "j3w1 UI Theme Spec: canonical design tokens, component rules, a generated single-page visual specification, and machine exports for agents. The repository owns the theme; j3w1.github.io demonstrates it.", + "description": "j3w1 UI Theme Spec: canonical design tokens, component rules, a generated visual specification (a reference hub with detail pages), and machine exports for agents. The repository owns the theme; j3w1.github.io demonstrates it.", "engines": { "node": "24.x", "npm": ">=10" From 60b2b940a61eb256f2ed5e6ee826d6b3ccaa57e3 Mon Sep 17 00:00:00 2001 From: j3w1 Date: Wed, 14 Oct 2026 18:24:00 -0500 Subject: [PATCH 60/65] docs: condense AGENTS.md and describe the reference hub (owner approval pending) Folds the check loop, hex-swatch and evidence rules into shorter statements without dropping a rule, adds packages/ui/dist/ and the agents/consume.md marker block to the generated list (R-k: generators.mjs rebuilds them), names PW_PORT and the pinned GITHUB_SHA build, and replaces "single-page visual reference" with the /reference/ hub and its detail pages. The CE Meta integration section is byte-identical. The owner approves the exact text before this ships (G2). Co-Authored-By: Claude Opus 5.5 --- AGENTS.md | 111 +++++++++++++++++++++++------------------------------- 1 file changed, 47 insertions(+), 64 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index bd352dbec..6d9db2fb9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,10 +1,11 @@ # j3w1/theme agent instructions This repository **defines** the j3w1 theme: one versioned specification with -exact tokens, component rules, a generated single-page visual reference at -`https://j3w1.github.io/theme/`, and machine exports for agents. If you are -applying the theme somewhere else, read `agents/consume.md` instead of this -file. +exact tokens, component rules, machine exports for agents, and a portal at +`https://j3w1.github.io/theme/` with a compact `/reference/` hub, component +detail on `/components//`, and `/reference/contrast/` and +`/reference/decisions/`. If you are applying the theme somewhere else, read +`agents/consume.md` instead of this file. ## Required reading, in order @@ -23,57 +24,46 @@ Images never override tokens. ## Source of truth -Literal values live in `tokens/`. Meaning and permitted uses live in `spec/`. -Native keys live in port mappings. Test facts live in evidence records. +Literal values live in `tokens/`, meaning and permitted uses in `spec/`, native +keys in port mappings, test facts in evidence records (D-000). A contradiction +between spec and tokens is a defect to resolve, not a choice to make. -These files are generated: `exports/`, `schemas/json/`, -`site/src/styles/tokens.generated.css`, the port files under `ports/*/dist/`, -`ports/orca/install/specimen.json`, `packages/ui/README.md` (a copy of -`docs/ui-consumption.md`), and the marker blocks in `README.md` and the port -guides. Edit their sources and run `npm run generate`; never edit them by -hand. A contradiction between spec and tokens is a defect to resolve, not a -choice to make. +Generated, never edited by hand: `exports/`, `schemas/json/`, +`site/src/styles/tokens.generated.css`, `packages/ui/dist/`, +`packages/ui/README.md` (a copy of `docs/ui-consumption.md`), the port files +under `ports/*/dist/`, `ports/orca/install/specimen.json`, and the marker +blocks in `README.md`, `agents/consume.md` and the port guides. Edit their +sources and run `npm run generate`. ## The check loop -CI picks the checks a change needs (D-031). You can see its choice before you +CI picks the checks a change needs (D-031); `release-gate` is the only required +check and passes when every selected check passed. See the plan before you push: ``` node scripts/ci/select.mjs --event pull_request --base origin/main --head HEAD ``` -`release-gate` is the only required check: it passes when every selected check -passed. +Run what it selects, usually `npm run generate` (after any source change; `npm +run check` only reports drift), `npm run validate`, `npm run check`, `npm +test`, `npm run build && npm run test:dist`, and `npm run test:smoke`. Build +like CI with `GITHUB_SHA` set to the full commit; a pinned build refuses +uncommitted generated files, so commit first. Browser runs use port 4173; set +`PW_PORT` to a free port when another checkout is testing. -**Before you push.** Run what the plan selects. The usual set: +`npm run test:all` is the whole suite, with the browser part in parallel. Run +it when you changed rendering, tokens, components or the package, and say so +in the pull request. On `main`, CI runs the whole matrix for every site change +before it deploys; the workflow dispatch runs it on any branch. -``` -npm run generate # rewrite every generated file (run it after any source change) -npm run validate # sources: manifest, decisions, tokens, docs, spec, contrast, ports, references, private material -npm run check # generated files are current, no orphans -npm test # node --test over sources and exports -npm run build && npm run test:dist # the site under /theme/ -npm run test:smoke # the built site loads, renders from the tokens, takes a keyboard -``` - -`npm run check` only reports drift; `npm run generate` fixes it. - -**The whole suite.** `npm run test:all` runs everything; the browser part runs -in parallel. Run it when you changed rendering, tokens, components or the package, -and say in the pull request that you did. On `main`, CI runs the whole matrix -for every change to the site before it deploys. From the Actions tab, the -workflow dispatch runs it on any branch. +Only the whole suite writes execution evidence. A subset (`test:smoke`, the +specs a pull request selects, one spec, shard or project) writes none and +never claims coverage. Report checks that were not run separately from checks +that passed. -**Evidence.** Only the whole suite writes execution evidence. A subset, such as -`test:smoke`, the specs a pull request selects, or a local run of one spec, -shard or project, writes none and never claims coverage. - -Report checks that were not run separately from checks that passed. - -**Design mode is a working tool, not a gate.** `npm run design` compares the -site at an anchored commit with the live dev server (`docs/design-mode.md`). -Nothing it shows is evidence, and it approves nothing. +Design mode (`npm run design`, `docs/design-mode.md`) is a working tool, not a +gate: nothing it shows is evidence, and it approves nothing. ## What you may do without a decision @@ -115,34 +105,27 @@ exists) and the install commands generated from it into the port guides. Commits are conventional (`feat:`, `fix:`, `docs:`, `spec:`, `tokens:`, `site:`, `chore:`) and explain why. -## Specification UI maintenance - -Every CSS hex literal a person can see on the j3w1 UI Theme Spec must get its -generated inline color swatch (D-014). +## Hex swatches (D-014) -- New sections and components get swatches from the whole-page build - transform. Never add or maintain swatches by hand. -- Explicit runtime renderers, such as the token inspector, use the same - literal parser and presentation helpers. Never scan the runtime DOM for - colors. -- Keep source text, copied text and machine exports unchanged. -- Run the three hex gates: source (`tests/hex-literals.test.js`), dist - (`tests/dist/hex-swatches.test.js`) and browser - (`tests/browser/hex-swatches.spec.js`). +Every visible CSS hex literal on the site gets its generated inline swatch from +the whole-page build transform; never add or maintain one by hand. Runtime +renderers, such as the token inspector, use the same literal parser and +presentation helpers and never scan the DOM for colours. Source text, copied +text and machine exports stay unchanged. The three gates are +`tests/hex-literals.test.js`, `tests/dist/hex-swatches.test.js` and +`tests/browser/hex-swatches.spec.js`. ## Execution evidence -- `tested` stays the compatibility alias for `testImplemented`. It is never a - pass. -- Every browser test needs an explicit `verification` annotation that names its - component, category, states, variants and limits. -- Use the shared evidence fixture for the real environment metadata. -- A test in the matrix proves rendering coverage only. +- `tested` stays the compatibility alias for `testImplemented`; it is never a + pass. A test in the matrix proves rendering coverage only. +- Every browser test needs an explicit `verification` annotation naming its + component, category, states, variants and limits, and uses the shared + evidence fixture for the real environment metadata. - After the browser suite, run `npm run verification:report`, then `npm run verification:check`, then `npm run test:verification`. -- Keep the exact specimen bytes. -- Run records go in the ignored `test-results/` and the published - `dist/verification/`, never in the deterministic committed exports. +- Keep the exact specimen bytes. Run records go in the ignored `test-results/` + and the published `dist/verification/`, never in the committed exports. - Do not claim a manual keyboard or screen-reader pass without a recorded protocol and environment. From 054f9cf3e163815247cc7b0ec62af74726564bdc Mon Sep 17 00:00:00 2001 From: j3w1 Date: Wed, 14 Oct 2026 18:32:47 -0500 Subject: [PATCH 61/65] fix: align component states with accepted theme decisions Keep selection focus on the ordinary ring, record computed contrast limits, refresh focus dependencies and make calendar removal reversible. Co-Authored-By: Claude Opus 5.5 --- apps/demo/src/style.css | 7 + apps/demo/src/views/Productivity.vue | 83 ++++++++++- ports/obsidian/ANDROID.md | 2 +- ports/windows/COVERAGE.md | 2 +- site/src/styles/components/breadcrumbs.css | 2 +- site/src/styles/components/card.css | 6 +- site/src/styles/components/chip.css | 4 +- site/src/styles/components/combobox.css | 6 +- site/src/styles/components/data-table.css | 4 +- site/src/styles/components/diagnostics.css | 4 +- site/src/styles/components/diff-view.css | 4 +- .../src/styles/components/i3-window-frame.css | 2 +- site/src/styles/components/icon-button.css | 4 +- site/src/styles/components/list.css | 6 +- site/src/styles/components/menu.css | 6 +- site/src/styles/components/pagination.css | 4 +- site/src/styles/components/sidebar-nav.css | 4 +- site/src/styles/components/table.css | 4 +- site/src/styles/components/time-picker.css | 2 +- site/src/styles/components/toast.css | 2 +- spec/components/avatar.md | 2 +- spec/components/breadcrumbs.md | 6 +- spec/components/button-group.md | 2 +- spec/components/button.md | 2 +- spec/components/card.md | 12 +- spec/components/chart.md | 2 +- spec/components/chip.md | 6 +- spec/components/code-editor.md | 2 + spec/components/combobox.md | 6 +- spec/components/command-palette.md | 2 +- spec/components/compact-dashboard.md | 2 +- spec/components/data-table.md | 6 +- spec/components/description-list.md | 2 +- spec/components/diagnostics.md | 6 +- spec/components/diff-view.md | 6 +- spec/components/disclosure.md | 2 +- spec/components/editor-search.md | 2 +- spec/components/error-state.md | 2 +- spec/components/file-browser.md | 2 +- spec/components/file-input.md | 2 +- spec/components/i3-window-frame.md | 5 +- spec/components/icon-button.md | 6 +- spec/components/kbd.md | 1 + spec/components/list.md | 6 +- spec/components/menu.md | 6 +- spec/components/pagination.md | 6 +- spec/components/popover.md | 2 +- spec/components/progress.md | 2 +- spec/components/range.md | 1 + spec/components/repeater.md | 2 +- spec/components/search-field.md | 2 +- spec/components/segmented-control.md | 1 - spec/components/settings-panel.md | 2 +- spec/components/sidebar-nav.md | 6 +- spec/components/skeleton.md | 2 +- spec/components/table.md | 6 +- spec/components/time-picker.md | 8 ++ spec/components/timeline.md | 2 +- spec/components/toast.md | 8 +- spec/components/tree.md | 2 +- spec/components/wizard.md | 2 +- .../components/decision-alignment.spec.js | 129 ++++++++++++++++++ tests/browser/demo-calendar.spec.js | 82 +++++++++++ tests/component-decisions.test.js | 59 ++++++++ 64 files changed, 470 insertions(+), 110 deletions(-) create mode 100644 tests/browser/components/decision-alignment.spec.js create mode 100644 tests/browser/demo-calendar.spec.js create mode 100644 tests/component-decisions.test.js diff --git a/apps/demo/src/style.css b/apps/demo/src/style.css index 50fdcfcfb..4477f1cda 100644 --- a/apps/demo/src/style.css +++ b/apps/demo/src/style.css @@ -646,3 +646,10 @@ main { scroll-behavior: auto !important; } } + +.calendar-notifications { + position: fixed; + inset-inline-end: var(--space-8); + inset-block-end: var(--space-8); + max-inline-size: calc(100% - 2 * var(--space-8)); +} diff --git a/apps/demo/src/views/Productivity.vue b/apps/demo/src/views/Productivity.vue index 185749a14..9ab05564b 100644 --- a/apps/demo/src/views/Productivity.vue +++ b/apps/demo/src/views/Productivity.vue @@ -1,8 +1,10 @@