@ecoma-io/loom 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +188 -101
- package/dist/a11y.js +4 -3
- package/dist/composition/center/src/Center.js.map +1 -0
- package/dist/composition/center/src/Center.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/composition/dashboard-grid/src/DashboardGrid.js +7 -0
- package/dist/composition/dashboard-grid/src/DashboardGrid.js.map +1 -0
- package/dist/composition/dashboard-grid/src/DashboardGrid.vue_vue_type_script_setup_true_lang.js +45 -0
- package/dist/composition/dashboard-grid/src/DashboardGrid.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/composition/frame/src/Frame.js.map +1 -0
- package/dist/composition/frame/src/Frame.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/composition/grid/src/Grid.js.map +1 -0
- package/dist/composition/grid/src/Grid.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/composition/inline/src/Inline.js.map +1 -0
- package/dist/composition/inline/src/Inline.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/composition/scroll-reel/src/ScrollReel.js.map +1 -0
- package/dist/composition/scroll-reel/src/ScrollReel.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/composition/sidebar/src/Sidebar.js.map +1 -0
- package/dist/composition/sidebar/src/Sidebar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/composition/split/src/Split.js.map +1 -0
- package/dist/composition/split/src/Split.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/composition/stack/src/Stack.js.map +1 -0
- package/dist/composition/stack/src/Stack.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/core/src/a11y-contract.js +558 -0
- package/dist/core/src/a11y-contract.js.map +1 -0
- package/dist/core/src/a11y-scope.js +151 -0
- package/dist/core/src/a11y-scope.js.map +1 -0
- package/dist/core/src/attrs.js.map +1 -0
- package/dist/core/src/cn.js +61 -0
- package/dist/core/src/cn.js.map +1 -0
- package/dist/core/src/icon-defaults.js.map +1 -0
- package/dist/core/src/index.js +9 -0
- package/dist/core/src/motion.js +31 -0
- package/dist/core/src/motion.js.map +1 -0
- package/dist/core/src/props.js.map +1 -0
- package/dist/core/src/theme.js.map +1 -0
- package/dist/index.js +287 -285
- package/dist/labels/src/ancestor-disabled.js.map +1 -0
- package/dist/labels/src/count-labels.js.map +1 -0
- package/dist/labels/src/date-labels.js +206 -0
- package/dist/labels/src/date-labels.js.map +1 -0
- package/dist/labels/src/field-context.js.map +1 -0
- package/dist/labels/src/labels.js.map +1 -0
- package/dist/layouts/app-shell/src/AppShell.js.map +1 -0
- package/dist/layouts/app-shell/src/AppShell.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/layouts/centered/src/Centered.js.map +1 -0
- package/dist/layouts/centered/src/Centered.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/layouts/dashboard/src/Dashboard.js.map +1 -0
- package/dist/layouts/dashboard/src/Dashboard.vue_vue_type_script_setup_true_lang.js +65 -0
- package/dist/layouts/dashboard/src/Dashboard.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/layouts/desktop-app-shell/src/DesktopAppShell.js +7 -0
- package/dist/layouts/desktop-app-shell/src/DesktopAppShell.js.map +1 -0
- package/dist/layouts/desktop-app-shell/src/DesktopAppShell.vue_vue_type_script_setup_true_lang.js +76 -0
- package/dist/layouts/desktop-app-shell/src/DesktopAppShell.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/layouts/form-layout/src/FormLayout.js.map +1 -0
- package/dist/layouts/form-layout/src/FormLayout.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/layouts/master-detail/src/MasterDetail.js.map +1 -0
- package/dist/layouts/master-detail/src/MasterDetail.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/layouts/reading/src/Reading.js.map +1 -0
- package/dist/layouts/reading/src/Reading.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/layouts/settings/src/Settings.js.map +1 -0
- package/dist/layouts/settings/src/Settings.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/layouts/split-layout/src/SplitLayout.js.map +1 -0
- package/dist/layouts/split-layout/src/SplitLayout.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/packages/composition/dashboard-grid/src/DashboardGrid.vue.d.ts +26 -0
- package/dist/packages/composition/dashboard-grid/src/DashboardGrid.vue.d.ts.map +1 -0
- package/dist/packages/composition/dashboard-grid/src/index.d.ts.map +1 -0
- package/dist/packages/composition/split/src/Split.vue.d.ts.map +1 -1
- package/dist/packages/core/src/a11y-contract.d.ts +417 -0
- package/dist/packages/core/src/a11y-contract.d.ts.map +1 -0
- package/dist/packages/core/src/a11y-scope.d.ts +5 -3
- package/dist/packages/core/src/a11y-scope.d.ts.map +1 -1
- package/dist/packages/core/src/index.d.ts +7 -1
- package/dist/packages/core/src/index.d.ts.map +1 -1
- package/dist/packages/core/src/motion.d.ts +15 -6
- package/dist/packages/core/src/motion.d.ts.map +1 -1
- package/dist/packages/core/src/responsive-contract.d.ts +155 -0
- package/dist/packages/core/src/responsive-contract.d.ts.map +1 -0
- package/dist/packages/labels/src/component-shapes.d.ts +2 -0
- package/dist/packages/labels/src/component-shapes.d.ts.map +1 -1
- package/dist/packages/layouts/dashboard/src/Dashboard.vue.d.ts.map +1 -1
- package/dist/packages/layouts/desktop-app-shell/src/DesktopAppShell.vue.d.ts +103 -0
- package/dist/packages/layouts/desktop-app-shell/src/index.d.ts.map +1 -0
- package/dist/packages/loom/src/a11y.d.ts +2 -1
- package/dist/packages/loom/src/index.d.ts +23 -23
- package/dist/packages/patterns/app-header/src/AppHeader.vue.d.ts +82 -0
- package/dist/packages/patterns/app-header/src/AppHeader.vue.d.ts.map +1 -0
- package/dist/packages/patterns/app-header/src/index.d.ts.map +1 -0
- package/dist/packages/patterns/empty-state/src/EmptyState.vue.d.ts +54 -0
- package/dist/packages/patterns/empty-state/src/EmptyState.vue.d.ts.map +1 -0
- package/dist/packages/patterns/empty-state/src/index.d.ts.map +1 -0
- package/dist/packages/patterns/error-state/src/ErrorState.vue.d.ts +44 -0
- package/dist/packages/patterns/error-state/src/ErrorState.vue.d.ts.map +1 -0
- package/dist/packages/patterns/error-state/src/index.d.ts.map +1 -0
- package/dist/packages/patterns/form-actions/src/FormActions.vue.d.ts +56 -0
- package/dist/packages/patterns/form-actions/src/FormActions.vue.d.ts.map +1 -0
- package/dist/packages/patterns/form-actions/src/index.d.ts.map +1 -0
- package/dist/packages/patterns/form-section/src/FormSection.vue.d.ts +85 -0
- package/dist/packages/patterns/form-section/src/FormSection.vue.d.ts.map +1 -0
- package/dist/packages/patterns/form-section/src/index.d.ts.map +1 -0
- package/dist/packages/patterns/loading-state/src/LoadingState.vue.d.ts.map +1 -0
- package/dist/packages/patterns/loading-state/src/index.d.ts.map +1 -0
- package/dist/packages/patterns/metric-card/src/MetricCard.vue.d.ts +77 -0
- package/dist/packages/patterns/metric-card/src/MetricCard.vue.d.ts.map +1 -0
- package/dist/packages/patterns/metric-card/src/index.d.ts.map +1 -0
- package/dist/packages/patterns/page-header/src/PageHeader.vue.d.ts.map +1 -0
- package/dist/packages/patterns/page-header/src/index.d.ts.map +1 -0
- package/dist/packages/patterns/row-actions/src/RowActions.vue.d.ts.map +1 -0
- package/dist/packages/patterns/row-actions/src/index.d.ts.map +1 -0
- package/dist/packages/patterns/sidebar-nav/src/SidebarNav.vue.d.ts.map +1 -0
- package/dist/packages/patterns/sidebar-nav/src/index.d.ts.map +1 -0
- package/dist/packages/patterns/title-bar/src/TitleBar.vue.d.ts +83 -0
- package/dist/packages/patterns/title-bar/src/index.d.ts.map +1 -0
- package/dist/packages/patterns/toast-stack/src/index.d.ts.map +1 -0
- package/dist/packages/primitives/list/src/ListItem.vue.d.ts +1 -1
- package/dist/packages/primitives/list/src/ListItem.vue.d.ts.map +1 -1
- package/dist/packages/primitives/surface/src/Surface.vue.d.ts +2 -2
- package/dist/packages/primitives/surface/src/Surface.vue.d.ts.map +1 -1
- package/dist/packages/primitives/table/src/TableRow.vue.d.ts +2 -2
- package/dist/packages/primitives/table/src/TableRow.vue.d.ts.map +1 -1
- package/dist/patterns/app-header/src/AppHeader.js +7 -0
- package/dist/patterns/app-header/src/AppHeader.js.map +1 -0
- package/dist/patterns/app-header/src/AppHeader.vue_vue_type_script_setup_true_lang.js +96 -0
- package/dist/patterns/app-header/src/AppHeader.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/patterns/empty-state/src/EmptyState.js +7 -0
- package/dist/patterns/empty-state/src/EmptyState.js.map +1 -0
- package/dist/patterns/empty-state/src/EmptyState.vue_vue_type_script_setup_true_lang.js +73 -0
- package/dist/patterns/empty-state/src/EmptyState.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/patterns/error-state/src/ErrorState.js +7 -0
- package/dist/patterns/error-state/src/ErrorState.js.map +1 -0
- package/dist/patterns/error-state/src/ErrorState.vue_vue_type_script_setup_true_lang.js +60 -0
- package/dist/patterns/error-state/src/ErrorState.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/patterns/error-summary/src/ErrorSummary.js +7 -0
- package/dist/patterns/error-summary/src/ErrorSummary.js.map +1 -0
- package/dist/patterns/error-summary/src/ErrorSummary.vue_vue_type_script_setup_true_lang.js +90 -0
- package/dist/patterns/error-summary/src/ErrorSummary.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/patterns/form-actions/src/FormActions.js +7 -0
- package/dist/patterns/form-actions/src/FormActions.js.map +1 -0
- package/dist/patterns/form-actions/src/FormActions.vue_vue_type_script_setup_true_lang.js +22 -0
- package/dist/patterns/form-actions/src/FormActions.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/patterns/form-section/src/FormSection.js +7 -0
- package/dist/patterns/form-section/src/FormSection.js.map +1 -0
- package/dist/patterns/form-section/src/FormSection.vue_vue_type_script_setup_true_lang.js +64 -0
- package/dist/patterns/form-section/src/FormSection.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/patterns/loading-state/src/LoadingState.js +7 -0
- package/dist/patterns/loading-state/src/LoadingState.js.map +1 -0
- package/dist/patterns/loading-state/src/LoadingState.vue_vue_type_script_setup_true_lang.js +59 -0
- package/dist/patterns/loading-state/src/LoadingState.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/patterns/metric-card/src/MetricCard.js +7 -0
- package/dist/patterns/metric-card/src/MetricCard.js.map +1 -0
- package/dist/patterns/metric-card/src/MetricCard.vue_vue_type_script_setup_true_lang.js +87 -0
- package/dist/patterns/metric-card/src/MetricCard.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/patterns/page-header/src/PageHeader.js +7 -0
- package/dist/patterns/page-header/src/PageHeader.js.map +1 -0
- package/dist/patterns/page-header/src/PageHeader.vue_vue_type_script_setup_true_lang.js +68 -0
- package/dist/patterns/page-header/src/PageHeader.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/patterns/row-actions/src/RowActions.js +7 -0
- package/dist/patterns/row-actions/src/RowActions.js.map +1 -0
- package/dist/patterns/row-actions/src/RowActions.vue_vue_type_script_setup_true_lang.js +47 -0
- package/dist/patterns/row-actions/src/RowActions.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/patterns/sidebar-nav/src/SidebarNav.js +7 -0
- package/dist/patterns/sidebar-nav/src/SidebarNav.js.map +1 -0
- package/dist/patterns/sidebar-nav/src/SidebarNav.vue_vue_type_script_setup_true_lang.js +129 -0
- package/dist/patterns/sidebar-nav/src/SidebarNav.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/patterns/title-bar/src/TitleBar.js +7 -0
- package/dist/patterns/title-bar/src/TitleBar.js.map +1 -0
- package/dist/patterns/title-bar/src/TitleBar.vue_vue_type_script_setup_true_lang.js +69 -0
- package/dist/patterns/title-bar/src/TitleBar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/patterns/toast-stack/src/ToastStack.js +7 -0
- package/dist/patterns/toast-stack/src/ToastStack.js.map +1 -0
- package/dist/patterns/toast-stack/src/ToastStack.vue_vue_type_script_setup_true_lang.js +52 -0
- package/dist/patterns/toast-stack/src/ToastStack.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/accordion/src/Accordion.js.map +1 -0
- package/dist/primitives/accordion/src/Accordion.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/alert/src/Alert.js.map +1 -0
- package/dist/primitives/alert/src/Alert.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/alert-dialog/src/AlertDialog.js.map +1 -0
- package/dist/primitives/alert-dialog/src/AlertDialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/avatar/src/Avatar.js.map +1 -0
- package/dist/primitives/avatar/src/Avatar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/avatar-group/src/AvatarGroup.js.map +1 -0
- package/dist/primitives/avatar-group/src/AvatarGroup.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/badge/src/Badge.js.map +1 -0
- package/dist/primitives/badge/src/Badge.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/breadcrumb/src/Breadcrumb.js.map +1 -0
- package/dist/primitives/breadcrumb/src/Breadcrumb.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/button/src/Button.js.map +1 -0
- package/dist/primitives/button/src/Button.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/calendar/src/Calendar.js.map +1 -0
- package/dist/primitives/calendar/src/Calendar.vue_vue_type_script_setup_true_lang.js +202 -0
- package/dist/primitives/calendar/src/Calendar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/card/src/Card.js.map +1 -0
- package/dist/primitives/card/src/Card.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/carousel/src/Carousel.js.map +1 -0
- package/dist/primitives/carousel/src/Carousel.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/checkbox/src/Checkbox.js.map +1 -0
- package/dist/primitives/checkbox/src/Checkbox.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/chip/src/Chip.js.map +1 -0
- package/dist/primitives/chip/src/Chip.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/collapse/src/Collapse.js.map +1 -0
- package/dist/primitives/collapse/src/Collapse.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/color-picker/src/ColorPicker.js.map +1 -0
- package/dist/primitives/color-picker/src/ColorPicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/combobox/src/Combobox.js.map +1 -0
- package/dist/primitives/combobox/src/Combobox.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/command/src/Command.js.map +1 -0
- package/dist/primitives/command/src/Command.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/context-menu/src/ContextMenu.js.map +1 -0
- package/dist/primitives/context-menu/src/ContextMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/copy-button/src/CopyButton.js.map +1 -0
- package/dist/primitives/copy-button/src/CopyButton.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/copy-button/src/index.js +3 -0
- package/dist/primitives/data-grid/src/DataGrid.js.map +1 -0
- package/dist/primitives/data-grid/src/DataGrid.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/date-picker/src/DatePicker.js.map +1 -0
- package/dist/primitives/date-picker/src/DatePicker.vue_vue_type_script_setup_true_lang.js +292 -0
- package/dist/primitives/date-picker/src/DatePicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/date-range-picker/src/DateRangePicker.js.map +1 -0
- package/dist/primitives/date-range-picker/src/DateRangePicker.vue_vue_type_script_setup_true_lang.js +417 -0
- package/dist/primitives/date-range-picker/src/DateRangePicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/date-time-picker/src/DateTimePicker.js.map +1 -0
- package/dist/primitives/date-time-picker/src/DateTimePicker.vue_vue_type_script_setup_true_lang.js +359 -0
- package/dist/primitives/date-time-picker/src/DateTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/date-time-range-picker/src/DateTimeRangePicker.js.map +1 -0
- package/dist/primitives/date-time-range-picker/src/DateTimeRangePicker.vue_vue_type_script_setup_true_lang.js +563 -0
- package/dist/primitives/date-time-range-picker/src/DateTimeRangePicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/dialog/src/Dialog.js.map +1 -0
- package/dist/primitives/dialog/src/Dialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/drawer/src/Drawer.js.map +1 -0
- package/dist/primitives/drawer/src/Drawer.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/dropdown-menu/src/DropdownMenu.js.map +1 -0
- package/dist/primitives/dropdown-menu/src/DropdownMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/editable/src/Editable.js.map +1 -0
- package/dist/primitives/editable/src/Editable.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/field/src/Field.js.map +1 -0
- package/dist/primitives/field/src/Field.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/fieldset/src/Fieldset.js.map +1 -0
- package/dist/primitives/fieldset/src/Fieldset.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/file-upload/src/FileUpload.js.map +1 -0
- package/dist/primitives/file-upload/src/FileUpload.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/hover-card/src/HoverCard.js.map +1 -0
- package/dist/primitives/hover-card/src/HoverCard.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/icon-button/src/IconButton.js.map +1 -0
- package/dist/primitives/icon-button/src/IconButton.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/indicator/src/Indicator.js.map +1 -0
- package/dist/primitives/indicator/src/Indicator.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/inline-error/src/InlineError.js.map +1 -0
- package/dist/primitives/inline-error/src/InlineError.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/kbd/src/Kbd.js.map +1 -0
- package/dist/primitives/kbd/src/Kbd.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/link/src/Link.js.map +1 -0
- package/dist/primitives/link/src/Link.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/list/src/List.js.map +1 -0
- package/dist/primitives/list/src/List.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/list/src/ListItem.js.map +1 -0
- package/dist/primitives/list/src/ListItem.vue_vue_type_script_setup_true_lang.js +101 -0
- package/dist/primitives/list/src/ListItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/live-region/src/LiveRegion.js.map +1 -0
- package/dist/primitives/live-region/src/LiveRegion.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/live-region/src/context.js.map +1 -0
- package/dist/primitives/live-region/src/useAnnounce.js.map +1 -0
- package/dist/primitives/menubar/src/Menubar.js.map +1 -0
- package/dist/primitives/menubar/src/Menubar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/meter/src/Meter.js.map +1 -0
- package/dist/primitives/meter/src/Meter.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/navigation-menu/src/NavigationMenu.js.map +1 -0
- package/dist/primitives/navigation-menu/src/NavigationMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/number-field/src/NumberField.js.map +1 -0
- package/dist/primitives/number-field/src/NumberField.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/otp-input/src/OtpInput.js.map +1 -0
- package/dist/primitives/otp-input/src/OtpInput.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/pagination/src/Pagination.js.map +1 -0
- package/dist/primitives/pagination/src/Pagination.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/popover/src/Popover.js.map +1 -0
- package/dist/primitives/popover/src/Popover.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/progress/src/Progress.js.map +1 -0
- package/dist/primitives/progress/src/Progress.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/radial-progress/src/RadialProgress.js.map +1 -0
- package/dist/primitives/radial-progress/src/RadialProgress.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/radio-group/src/RadioGroup.js.map +1 -0
- package/dist/primitives/radio-group/src/RadioGroup.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/rating/src/Rating.js.map +1 -0
- package/dist/primitives/rating/src/Rating.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/scroll-area/src/ScrollArea.js.map +1 -0
- package/dist/primitives/scroll-area/src/ScrollArea.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/segmented-control/src/SegmentedControl.js.map +1 -0
- package/dist/primitives/segmented-control/src/SegmentedControl.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/select/src/Select.js.map +1 -0
- package/dist/primitives/select/src/Select.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/separator/src/Separator.js.map +1 -0
- package/dist/primitives/separator/src/Separator.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/skeleton/src/Skeleton.js.map +1 -0
- package/dist/primitives/skeleton/src/Skeleton.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/skip-link/src/SkipLink.js.map +1 -0
- package/dist/primitives/skip-link/src/SkipLink.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/slider/src/Slider.js.map +1 -0
- package/dist/primitives/slider/src/Slider.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/speed-dial/src/SpeedDial.js.map +1 -0
- package/dist/primitives/speed-dial/src/SpeedDial.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/spinner/src/Spinner.js.map +1 -0
- package/dist/primitives/spinner/src/Spinner.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/stepper/src/Stepper.js.map +1 -0
- package/dist/primitives/stepper/src/Stepper.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/surface/src/Surface.js.map +1 -0
- package/dist/primitives/surface/src/Surface.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/switch/src/Switch.js.map +1 -0
- package/dist/primitives/switch/src/Switch.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/table/src/Table.js.map +1 -0
- package/dist/primitives/table/src/Table.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/table/src/TableCell.js.map +1 -0
- package/dist/primitives/table/src/TableCell.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/table/src/TableHead.js.map +1 -0
- package/dist/primitives/table/src/TableHead.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/table/src/TableRow.js.map +1 -0
- package/dist/primitives/table/src/TableRow.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/tabs/src/Tabs.js.map +1 -0
- package/dist/primitives/tabs/src/Tabs.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/tags-input/src/TagsInput.js.map +1 -0
- package/dist/primitives/tags-input/src/TagsInput.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/text-field/src/TextField.js.map +1 -0
- package/dist/primitives/text-field/src/TextField.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/textarea/src/Textarea.js.map +1 -0
- package/dist/primitives/textarea/src/Textarea.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/time-picker/src/TimePicker.js.map +1 -0
- package/dist/primitives/time-picker/src/TimePicker.vue_vue_type_script_setup_true_lang.js +189 -0
- package/dist/primitives/time-picker/src/TimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/timeline/src/Timeline.js.map +1 -0
- package/dist/primitives/timeline/src/Timeline.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/timeline/src/TimelineItem.js.map +1 -0
- package/dist/primitives/timeline/src/TimelineItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/timeline/src/index.js +5 -0
- package/dist/primitives/toast/src/Toast.js.map +1 -0
- package/dist/primitives/toast/src/Toast.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/toast/src/ToastItem.js.map +1 -0
- package/dist/primitives/toast/src/ToastItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/toggle-group/src/ToggleGroup.js.map +1 -0
- package/dist/primitives/toggle-group/src/ToggleGroup.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/toolbar/src/Toolbar.js.map +1 -0
- package/dist/primitives/toolbar/src/Toolbar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/toolbar/src/ToolbarSeparator.js.map +1 -0
- package/dist/primitives/toolbar/src/ToolbarSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/tooltip/src/Tooltip.js.map +1 -0
- package/dist/primitives/tooltip/src/Tooltip.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/tree-view/src/TreeView.js.map +1 -0
- package/dist/primitives/tree-view/src/TreeView.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/tree-view/src/TreeViewNode.js.map +1 -0
- package/dist/primitives/tree-view/src/TreeViewNode.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/tree-view/src/context.js.map +1 -0
- package/dist/primitives/visually-hidden/src/VisuallyHidden.js.map +1 -0
- package/dist/primitives/visually-hidden/src/VisuallyHidden.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/primitives/window-controls/src/WindowControls.js.map +1 -0
- package/dist/primitives/window-controls/src/WindowControls.vue_vue_type_script_setup_true_lang.js +127 -0
- package/dist/primitives/window-controls/src/WindowControls.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/styles/theme.css +30 -6
- package/dist/theme.js +2 -2
- package/package.json +5 -4
- package/dist/node_modules/.pnpm/@internationalized_date@3.12.4/node_modules/@internationalized/date/dist/private/CalendarDate.js +0 -236
- package/dist/node_modules/.pnpm/@internationalized_date@3.12.4/node_modules/@internationalized/date/dist/private/CalendarDate.js.map +0 -1
- package/dist/node_modules/.pnpm/@internationalized_date@3.12.4/node_modules/@internationalized/date/dist/private/calendars/GregorianCalendar.js +0 -117
- package/dist/node_modules/.pnpm/@internationalized_date@3.12.4/node_modules/@internationalized/date/dist/private/calendars/GregorianCalendar.js.map +0 -1
- package/dist/node_modules/.pnpm/@internationalized_date@3.12.4/node_modules/@internationalized/date/dist/private/conversion.js +0 -142
- package/dist/node_modules/.pnpm/@internationalized_date@3.12.4/node_modules/@internationalized/date/dist/private/conversion.js.map +0 -1
- package/dist/node_modules/.pnpm/@internationalized_date@3.12.4/node_modules/@internationalized/date/dist/private/manipulation.js +0 -280
- package/dist/node_modules/.pnpm/@internationalized_date@3.12.4/node_modules/@internationalized/date/dist/private/manipulation.js.map +0 -1
- package/dist/node_modules/.pnpm/@internationalized_date@3.12.4/node_modules/@internationalized/date/dist/private/queries.js +0 -40
- package/dist/node_modules/.pnpm/@internationalized_date@3.12.4/node_modules/@internationalized/date/dist/private/queries.js.map +0 -1
- package/dist/node_modules/.pnpm/@internationalized_date@3.12.4/node_modules/@internationalized/date/dist/private/string.js +0 -69
- package/dist/node_modules/.pnpm/@internationalized_date@3.12.4/node_modules/@internationalized/date/dist/private/string.js.map +0 -1
- package/dist/node_modules/.pnpm/@internationalized_date@3.12.4/node_modules/@internationalized/date/dist/private/utils.js +0 -8
- package/dist/node_modules/.pnpm/@internationalized_date@3.12.4/node_modules/@internationalized/date/dist/private/utils.js.map +0 -1
- package/dist/packages/blocks/app-header/src/AppHeader.js +0 -7
- package/dist/packages/blocks/app-header/src/AppHeader.js.map +0 -1
- package/dist/packages/blocks/app-header/src/AppHeader.vue.d.ts +0 -82
- package/dist/packages/blocks/app-header/src/AppHeader.vue.d.ts.map +0 -1
- package/dist/packages/blocks/app-header/src/AppHeader.vue_vue_type_script_setup_true_lang.js +0 -96
- package/dist/packages/blocks/app-header/src/AppHeader.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/blocks/app-header/src/index.d.ts.map +0 -1
- package/dist/packages/blocks/dashboard-grid/src/DashboardGrid.js +0 -7
- package/dist/packages/blocks/dashboard-grid/src/DashboardGrid.js.map +0 -1
- package/dist/packages/blocks/dashboard-grid/src/DashboardGrid.vue.d.ts +0 -42
- package/dist/packages/blocks/dashboard-grid/src/DashboardGrid.vue.d.ts.map +0 -1
- package/dist/packages/blocks/dashboard-grid/src/DashboardGrid.vue_vue_type_script_setup_true_lang.js +0 -45
- package/dist/packages/blocks/dashboard-grid/src/DashboardGrid.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/blocks/dashboard-grid/src/index.d.ts.map +0 -1
- package/dist/packages/blocks/desktop-app-shell/src/DesktopAppShell.js +0 -7
- package/dist/packages/blocks/desktop-app-shell/src/DesktopAppShell.js.map +0 -1
- package/dist/packages/blocks/desktop-app-shell/src/DesktopAppShell.vue.d.ts +0 -102
- package/dist/packages/blocks/desktop-app-shell/src/DesktopAppShell.vue_vue_type_script_setup_true_lang.js +0 -76
- package/dist/packages/blocks/desktop-app-shell/src/DesktopAppShell.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/blocks/desktop-app-shell/src/index.d.ts.map +0 -1
- package/dist/packages/blocks/empty-state/src/EmptyState.js +0 -7
- package/dist/packages/blocks/empty-state/src/EmptyState.js.map +0 -1
- package/dist/packages/blocks/empty-state/src/EmptyState.vue.d.ts +0 -50
- package/dist/packages/blocks/empty-state/src/EmptyState.vue.d.ts.map +0 -1
- package/dist/packages/blocks/empty-state/src/EmptyState.vue_vue_type_script_setup_true_lang.js +0 -70
- package/dist/packages/blocks/empty-state/src/EmptyState.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/blocks/empty-state/src/index.d.ts.map +0 -1
- package/dist/packages/blocks/error-state/src/ErrorState.js +0 -7
- package/dist/packages/blocks/error-state/src/ErrorState.js.map +0 -1
- package/dist/packages/blocks/error-state/src/ErrorState.vue.d.ts +0 -44
- package/dist/packages/blocks/error-state/src/ErrorState.vue.d.ts.map +0 -1
- package/dist/packages/blocks/error-state/src/ErrorState.vue_vue_type_script_setup_true_lang.js +0 -60
- package/dist/packages/blocks/error-state/src/ErrorState.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/blocks/error-state/src/index.d.ts.map +0 -1
- package/dist/packages/blocks/error-summary/src/ErrorSummary.js +0 -7
- package/dist/packages/blocks/error-summary/src/ErrorSummary.js.map +0 -1
- package/dist/packages/blocks/error-summary/src/ErrorSummary.vue_vue_type_script_setup_true_lang.js +0 -90
- package/dist/packages/blocks/error-summary/src/ErrorSummary.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/blocks/form-actions/src/FormActions.js +0 -7
- package/dist/packages/blocks/form-actions/src/FormActions.js.map +0 -1
- package/dist/packages/blocks/form-actions/src/FormActions.vue.d.ts +0 -51
- package/dist/packages/blocks/form-actions/src/FormActions.vue.d.ts.map +0 -1
- package/dist/packages/blocks/form-actions/src/FormActions.vue_vue_type_script_setup_true_lang.js +0 -22
- package/dist/packages/blocks/form-actions/src/FormActions.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/blocks/form-actions/src/index.d.ts.map +0 -1
- package/dist/packages/blocks/form-section/src/FormSection.js +0 -7
- package/dist/packages/blocks/form-section/src/FormSection.js.map +0 -1
- package/dist/packages/blocks/form-section/src/FormSection.vue.d.ts +0 -85
- package/dist/packages/blocks/form-section/src/FormSection.vue.d.ts.map +0 -1
- package/dist/packages/blocks/form-section/src/FormSection.vue_vue_type_script_setup_true_lang.js +0 -64
- package/dist/packages/blocks/form-section/src/FormSection.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/blocks/form-section/src/index.d.ts.map +0 -1
- package/dist/packages/blocks/loading-state/src/LoadingState.js +0 -7
- package/dist/packages/blocks/loading-state/src/LoadingState.js.map +0 -1
- package/dist/packages/blocks/loading-state/src/LoadingState.vue.d.ts.map +0 -1
- package/dist/packages/blocks/loading-state/src/LoadingState.vue_vue_type_script_setup_true_lang.js +0 -59
- package/dist/packages/blocks/loading-state/src/LoadingState.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/blocks/loading-state/src/index.d.ts.map +0 -1
- package/dist/packages/blocks/metric-card/src/MetricCard.js +0 -7
- package/dist/packages/blocks/metric-card/src/MetricCard.js.map +0 -1
- package/dist/packages/blocks/metric-card/src/MetricCard.vue.d.ts +0 -77
- package/dist/packages/blocks/metric-card/src/MetricCard.vue.d.ts.map +0 -1
- package/dist/packages/blocks/metric-card/src/MetricCard.vue_vue_type_script_setup_true_lang.js +0 -87
- package/dist/packages/blocks/metric-card/src/MetricCard.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/blocks/metric-card/src/index.d.ts.map +0 -1
- package/dist/packages/blocks/page-header/src/PageHeader.js +0 -7
- package/dist/packages/blocks/page-header/src/PageHeader.js.map +0 -1
- package/dist/packages/blocks/page-header/src/PageHeader.vue.d.ts.map +0 -1
- package/dist/packages/blocks/page-header/src/PageHeader.vue_vue_type_script_setup_true_lang.js +0 -68
- package/dist/packages/blocks/page-header/src/PageHeader.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/blocks/page-header/src/index.d.ts.map +0 -1
- package/dist/packages/blocks/row-actions/src/RowActions.js +0 -7
- package/dist/packages/blocks/row-actions/src/RowActions.js.map +0 -1
- package/dist/packages/blocks/row-actions/src/RowActions.vue.d.ts.map +0 -1
- package/dist/packages/blocks/row-actions/src/RowActions.vue_vue_type_script_setup_true_lang.js +0 -47
- package/dist/packages/blocks/row-actions/src/RowActions.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/blocks/row-actions/src/index.d.ts.map +0 -1
- package/dist/packages/blocks/sidebar-nav/src/SidebarNav.js +0 -7
- package/dist/packages/blocks/sidebar-nav/src/SidebarNav.js.map +0 -1
- package/dist/packages/blocks/sidebar-nav/src/SidebarNav.vue.d.ts.map +0 -1
- package/dist/packages/blocks/sidebar-nav/src/SidebarNav.vue_vue_type_script_setup_true_lang.js +0 -129
- package/dist/packages/blocks/sidebar-nav/src/SidebarNav.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/blocks/sidebar-nav/src/index.d.ts.map +0 -1
- package/dist/packages/blocks/title-bar/src/TitleBar.js +0 -7
- package/dist/packages/blocks/title-bar/src/TitleBar.js.map +0 -1
- package/dist/packages/blocks/title-bar/src/TitleBar.vue.d.ts +0 -83
- package/dist/packages/blocks/title-bar/src/TitleBar.vue_vue_type_script_setup_true_lang.js +0 -69
- package/dist/packages/blocks/title-bar/src/TitleBar.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/blocks/title-bar/src/index.d.ts.map +0 -1
- package/dist/packages/blocks/toast-stack/src/ToastStack.js +0 -7
- package/dist/packages/blocks/toast-stack/src/ToastStack.js.map +0 -1
- package/dist/packages/blocks/toast-stack/src/ToastStack.vue_vue_type_script_setup_true_lang.js +0 -52
- package/dist/packages/blocks/toast-stack/src/ToastStack.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/blocks/toast-stack/src/index.d.ts.map +0 -1
- package/dist/packages/composition/center/src/Center.js.map +0 -1
- package/dist/packages/composition/center/src/Center.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/composition/frame/src/Frame.js.map +0 -1
- package/dist/packages/composition/frame/src/Frame.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/composition/grid/src/Grid.js.map +0 -1
- package/dist/packages/composition/grid/src/Grid.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/composition/inline/src/Inline.js.map +0 -1
- package/dist/packages/composition/inline/src/Inline.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/composition/scroll-reel/src/ScrollReel.js.map +0 -1
- package/dist/packages/composition/scroll-reel/src/ScrollReel.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/composition/sidebar/src/Sidebar.js.map +0 -1
- package/dist/packages/composition/sidebar/src/Sidebar.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/composition/split/src/Split.js.map +0 -1
- package/dist/packages/composition/split/src/Split.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/composition/stack/src/Stack.js.map +0 -1
- package/dist/packages/composition/stack/src/Stack.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/core/src/a11y-scope.js +0 -149
- package/dist/packages/core/src/a11y-scope.js.map +0 -1
- package/dist/packages/core/src/attrs.js.map +0 -1
- package/dist/packages/core/src/cn.js +0 -61
- package/dist/packages/core/src/cn.js.map +0 -1
- package/dist/packages/core/src/icon-defaults.js.map +0 -1
- package/dist/packages/core/src/index.js +0 -8
- package/dist/packages/core/src/motion.js +0 -27
- package/dist/packages/core/src/motion.js.map +0 -1
- package/dist/packages/core/src/props.js.map +0 -1
- package/dist/packages/core/src/theme.js.map +0 -1
- package/dist/packages/labels/src/ancestor-disabled.js.map +0 -1
- package/dist/packages/labels/src/count-labels.js.map +0 -1
- package/dist/packages/labels/src/date-labels.js +0 -206
- package/dist/packages/labels/src/date-labels.js.map +0 -1
- package/dist/packages/labels/src/field-context.js.map +0 -1
- package/dist/packages/labels/src/labels.js.map +0 -1
- package/dist/packages/layouts/app-shell/src/AppShell.js.map +0 -1
- package/dist/packages/layouts/app-shell/src/AppShell.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/layouts/centered/src/Centered.js.map +0 -1
- package/dist/packages/layouts/centered/src/Centered.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/layouts/dashboard/src/Dashboard.js.map +0 -1
- package/dist/packages/layouts/dashboard/src/Dashboard.vue_vue_type_script_setup_true_lang.js +0 -65
- package/dist/packages/layouts/dashboard/src/Dashboard.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/layouts/form-layout/src/FormLayout.js.map +0 -1
- package/dist/packages/layouts/form-layout/src/FormLayout.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/layouts/master-detail/src/MasterDetail.js.map +0 -1
- package/dist/packages/layouts/master-detail/src/MasterDetail.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/layouts/reading/src/Reading.js.map +0 -1
- package/dist/packages/layouts/reading/src/Reading.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/layouts/settings/src/Settings.js.map +0 -1
- package/dist/packages/layouts/settings/src/Settings.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/layouts/split-layout/src/SplitLayout.js.map +0 -1
- package/dist/packages/layouts/split-layout/src/SplitLayout.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/accordion/src/Accordion.js.map +0 -1
- package/dist/packages/primitives/accordion/src/Accordion.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/alert/src/Alert.js.map +0 -1
- package/dist/packages/primitives/alert/src/Alert.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/alert-dialog/src/AlertDialog.js.map +0 -1
- package/dist/packages/primitives/alert-dialog/src/AlertDialog.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/avatar/src/Avatar.js.map +0 -1
- package/dist/packages/primitives/avatar/src/Avatar.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/avatar-group/src/AvatarGroup.js.map +0 -1
- package/dist/packages/primitives/avatar-group/src/AvatarGroup.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/badge/src/Badge.js.map +0 -1
- package/dist/packages/primitives/badge/src/Badge.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/breadcrumb/src/Breadcrumb.js.map +0 -1
- package/dist/packages/primitives/breadcrumb/src/Breadcrumb.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/button/src/Button.js.map +0 -1
- package/dist/packages/primitives/button/src/Button.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/calendar/src/Calendar.js.map +0 -1
- package/dist/packages/primitives/calendar/src/Calendar.vue_vue_type_script_setup_true_lang.js +0 -204
- package/dist/packages/primitives/calendar/src/Calendar.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/card/src/Card.js.map +0 -1
- package/dist/packages/primitives/card/src/Card.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/carousel/src/Carousel.js.map +0 -1
- package/dist/packages/primitives/carousel/src/Carousel.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/checkbox/src/Checkbox.js.map +0 -1
- package/dist/packages/primitives/checkbox/src/Checkbox.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/chip/src/Chip.js.map +0 -1
- package/dist/packages/primitives/chip/src/Chip.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/collapse/src/Collapse.js.map +0 -1
- package/dist/packages/primitives/collapse/src/Collapse.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/color-picker/src/ColorPicker.js.map +0 -1
- package/dist/packages/primitives/color-picker/src/ColorPicker.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/combobox/src/Combobox.js.map +0 -1
- package/dist/packages/primitives/combobox/src/Combobox.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/command/src/Command.js.map +0 -1
- package/dist/packages/primitives/command/src/Command.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/context-menu/src/ContextMenu.js.map +0 -1
- package/dist/packages/primitives/context-menu/src/ContextMenu.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/copy-button/src/CopyButton.js.map +0 -1
- package/dist/packages/primitives/copy-button/src/CopyButton.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/copy-button/src/index.js +0 -3
- package/dist/packages/primitives/data-grid/src/DataGrid.js.map +0 -1
- package/dist/packages/primitives/data-grid/src/DataGrid.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/date-picker/src/DatePicker.js.map +0 -1
- package/dist/packages/primitives/date-picker/src/DatePicker.vue_vue_type_script_setup_true_lang.js +0 -294
- package/dist/packages/primitives/date-picker/src/DatePicker.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/date-range-picker/src/DateRangePicker.js.map +0 -1
- package/dist/packages/primitives/date-range-picker/src/DateRangePicker.vue_vue_type_script_setup_true_lang.js +0 -419
- package/dist/packages/primitives/date-range-picker/src/DateRangePicker.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/date-time-picker/src/DateTimePicker.js.map +0 -1
- package/dist/packages/primitives/date-time-picker/src/DateTimePicker.vue_vue_type_script_setup_true_lang.js +0 -361
- package/dist/packages/primitives/date-time-picker/src/DateTimePicker.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/date-time-range-picker/src/DateTimeRangePicker.js.map +0 -1
- package/dist/packages/primitives/date-time-range-picker/src/DateTimeRangePicker.vue_vue_type_script_setup_true_lang.js +0 -565
- package/dist/packages/primitives/date-time-range-picker/src/DateTimeRangePicker.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/dialog/src/Dialog.js.map +0 -1
- package/dist/packages/primitives/dialog/src/Dialog.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/drawer/src/Drawer.js.map +0 -1
- package/dist/packages/primitives/drawer/src/Drawer.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/dropdown-menu/src/DropdownMenu.js.map +0 -1
- package/dist/packages/primitives/dropdown-menu/src/DropdownMenu.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/editable/src/Editable.js.map +0 -1
- package/dist/packages/primitives/editable/src/Editable.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/field/src/Field.js.map +0 -1
- package/dist/packages/primitives/field/src/Field.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/fieldset/src/Fieldset.js.map +0 -1
- package/dist/packages/primitives/fieldset/src/Fieldset.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/file-upload/src/FileUpload.js.map +0 -1
- package/dist/packages/primitives/file-upload/src/FileUpload.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/hover-card/src/HoverCard.js.map +0 -1
- package/dist/packages/primitives/hover-card/src/HoverCard.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/icon-button/src/IconButton.js.map +0 -1
- package/dist/packages/primitives/icon-button/src/IconButton.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/indicator/src/Indicator.js.map +0 -1
- package/dist/packages/primitives/indicator/src/Indicator.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/inline-error/src/InlineError.js.map +0 -1
- package/dist/packages/primitives/inline-error/src/InlineError.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/kbd/src/Kbd.js.map +0 -1
- package/dist/packages/primitives/kbd/src/Kbd.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/link/src/Link.js.map +0 -1
- package/dist/packages/primitives/link/src/Link.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/list/src/List.js.map +0 -1
- package/dist/packages/primitives/list/src/List.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/list/src/ListItem.js.map +0 -1
- package/dist/packages/primitives/list/src/ListItem.vue_vue_type_script_setup_true_lang.js +0 -101
- package/dist/packages/primitives/list/src/ListItem.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/live-region/src/LiveRegion.js.map +0 -1
- package/dist/packages/primitives/live-region/src/LiveRegion.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/live-region/src/context.js.map +0 -1
- package/dist/packages/primitives/live-region/src/useAnnounce.js.map +0 -1
- package/dist/packages/primitives/menubar/src/Menubar.js.map +0 -1
- package/dist/packages/primitives/menubar/src/Menubar.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/meter/src/Meter.js.map +0 -1
- package/dist/packages/primitives/meter/src/Meter.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/navigation-menu/src/NavigationMenu.js.map +0 -1
- package/dist/packages/primitives/navigation-menu/src/NavigationMenu.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/number-field/src/NumberField.js.map +0 -1
- package/dist/packages/primitives/number-field/src/NumberField.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/otp-input/src/OtpInput.js.map +0 -1
- package/dist/packages/primitives/otp-input/src/OtpInput.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/pagination/src/Pagination.js.map +0 -1
- package/dist/packages/primitives/pagination/src/Pagination.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/popover/src/Popover.js.map +0 -1
- package/dist/packages/primitives/popover/src/Popover.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/progress/src/Progress.js.map +0 -1
- package/dist/packages/primitives/progress/src/Progress.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/radial-progress/src/RadialProgress.js.map +0 -1
- package/dist/packages/primitives/radial-progress/src/RadialProgress.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/radio-group/src/RadioGroup.js.map +0 -1
- package/dist/packages/primitives/radio-group/src/RadioGroup.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/rating/src/Rating.js.map +0 -1
- package/dist/packages/primitives/rating/src/Rating.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/scroll-area/src/ScrollArea.js.map +0 -1
- package/dist/packages/primitives/scroll-area/src/ScrollArea.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/segmented-control/src/SegmentedControl.js.map +0 -1
- package/dist/packages/primitives/segmented-control/src/SegmentedControl.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/select/src/Select.js.map +0 -1
- package/dist/packages/primitives/select/src/Select.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/separator/src/Separator.js.map +0 -1
- package/dist/packages/primitives/separator/src/Separator.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/skeleton/src/Skeleton.js.map +0 -1
- package/dist/packages/primitives/skeleton/src/Skeleton.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/skip-link/src/SkipLink.js.map +0 -1
- package/dist/packages/primitives/skip-link/src/SkipLink.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/slider/src/Slider.js.map +0 -1
- package/dist/packages/primitives/slider/src/Slider.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/speed-dial/src/SpeedDial.js.map +0 -1
- package/dist/packages/primitives/speed-dial/src/SpeedDial.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/spinner/src/Spinner.js.map +0 -1
- package/dist/packages/primitives/spinner/src/Spinner.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/stepper/src/Stepper.js.map +0 -1
- package/dist/packages/primitives/stepper/src/Stepper.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/surface/src/Surface.js.map +0 -1
- package/dist/packages/primitives/surface/src/Surface.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/switch/src/Switch.js.map +0 -1
- package/dist/packages/primitives/switch/src/Switch.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/table/src/Table.js.map +0 -1
- package/dist/packages/primitives/table/src/Table.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/table/src/TableCell.js.map +0 -1
- package/dist/packages/primitives/table/src/TableCell.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/table/src/TableHead.js.map +0 -1
- package/dist/packages/primitives/table/src/TableHead.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/table/src/TableRow.js.map +0 -1
- package/dist/packages/primitives/table/src/TableRow.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/tabs/src/Tabs.js.map +0 -1
- package/dist/packages/primitives/tabs/src/Tabs.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/tags-input/src/TagsInput.js.map +0 -1
- package/dist/packages/primitives/tags-input/src/TagsInput.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/text-field/src/TextField.js.map +0 -1
- package/dist/packages/primitives/text-field/src/TextField.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/textarea/src/Textarea.js.map +0 -1
- package/dist/packages/primitives/textarea/src/Textarea.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/time-picker/src/TimePicker.js.map +0 -1
- package/dist/packages/primitives/time-picker/src/TimePicker.vue_vue_type_script_setup_true_lang.js +0 -189
- package/dist/packages/primitives/time-picker/src/TimePicker.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/timeline/src/Timeline.js.map +0 -1
- package/dist/packages/primitives/timeline/src/Timeline.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/timeline/src/TimelineItem.js.map +0 -1
- package/dist/packages/primitives/timeline/src/TimelineItem.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/timeline/src/index.js +0 -5
- package/dist/packages/primitives/toast/src/Toast.js.map +0 -1
- package/dist/packages/primitives/toast/src/Toast.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/toast/src/ToastItem.js.map +0 -1
- package/dist/packages/primitives/toast/src/ToastItem.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/toggle-group/src/ToggleGroup.js.map +0 -1
- package/dist/packages/primitives/toggle-group/src/ToggleGroup.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/toolbar/src/Toolbar.js.map +0 -1
- package/dist/packages/primitives/toolbar/src/Toolbar.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/toolbar/src/ToolbarSeparator.js.map +0 -1
- package/dist/packages/primitives/toolbar/src/ToolbarSeparator.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/tooltip/src/Tooltip.js.map +0 -1
- package/dist/packages/primitives/tooltip/src/Tooltip.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/tree-view/src/TreeView.js.map +0 -1
- package/dist/packages/primitives/tree-view/src/TreeView.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/tree-view/src/TreeViewNode.js.map +0 -1
- package/dist/packages/primitives/tree-view/src/TreeViewNode.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/tree-view/src/context.js.map +0 -1
- package/dist/packages/primitives/visually-hidden/src/VisuallyHidden.js.map +0 -1
- package/dist/packages/primitives/visually-hidden/src/VisuallyHidden.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/packages/primitives/window-controls/src/WindowControls.js.map +0 -1
- package/dist/packages/primitives/window-controls/src/WindowControls.vue_vue_type_script_setup_true_lang.js +0 -124
- package/dist/packages/primitives/window-controls/src/WindowControls.vue_vue_type_script_setup_true_lang.js.map +0 -1
- /package/dist/{packages/composition → composition}/center/src/Center.js +0 -0
- /package/dist/{packages/composition → composition}/center/src/Center.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/composition → composition}/center/src/index.js +0 -0
- /package/dist/{packages/blocks → composition}/dashboard-grid/src/index.js +0 -0
- /package/dist/{packages/composition → composition}/frame/src/Frame.js +0 -0
- /package/dist/{packages/composition → composition}/frame/src/Frame.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/composition → composition}/frame/src/index.js +0 -0
- /package/dist/{packages/composition → composition}/grid/src/Grid.js +0 -0
- /package/dist/{packages/composition → composition}/grid/src/Grid.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/composition → composition}/grid/src/index.js +0 -0
- /package/dist/{packages/composition → composition}/inline/src/Inline.js +0 -0
- /package/dist/{packages/composition → composition}/inline/src/Inline.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/composition → composition}/inline/src/index.js +0 -0
- /package/dist/{packages/composition → composition}/scroll-reel/src/ScrollReel.js +0 -0
- /package/dist/{packages/composition → composition}/scroll-reel/src/ScrollReel.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/composition → composition}/scroll-reel/src/index.js +0 -0
- /package/dist/{packages/composition → composition}/sidebar/src/Sidebar.js +0 -0
- /package/dist/{packages/composition → composition}/sidebar/src/Sidebar.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/composition → composition}/sidebar/src/index.js +0 -0
- /package/dist/{packages/composition → composition}/split/src/Split.js +0 -0
- /package/dist/{packages/composition → composition}/split/src/Split.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/composition → composition}/split/src/index.js +0 -0
- /package/dist/{packages/composition → composition}/stack/src/Stack.js +0 -0
- /package/dist/{packages/composition → composition}/stack/src/Stack.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/composition → composition}/stack/src/index.js +0 -0
- /package/dist/{packages/core → core}/src/attrs.js +0 -0
- /package/dist/{packages/core → core}/src/icon-defaults.js +0 -0
- /package/dist/{packages/core → core}/src/props.js +0 -0
- /package/dist/{packages/core → core}/src/theme.js +0 -0
- /package/dist/{packages/labels → labels}/src/ancestor-disabled.js +0 -0
- /package/dist/{packages/labels → labels}/src/count-labels.js +0 -0
- /package/dist/{packages/labels → labels}/src/field-context.js +0 -0
- /package/dist/{packages/labels → labels}/src/index.js +0 -0
- /package/dist/{packages/labels → labels}/src/labels.js +0 -0
- /package/dist/{packages/layouts → layouts}/app-shell/src/AppShell.js +0 -0
- /package/dist/{packages/layouts → layouts}/app-shell/src/AppShell.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/layouts → layouts}/app-shell/src/index.js +0 -0
- /package/dist/{packages/layouts → layouts}/centered/src/Centered.js +0 -0
- /package/dist/{packages/layouts → layouts}/centered/src/Centered.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/layouts → layouts}/centered/src/index.js +0 -0
- /package/dist/{packages/layouts → layouts}/dashboard/src/Dashboard.js +0 -0
- /package/dist/{packages/layouts → layouts}/dashboard/src/index.js +0 -0
- /package/dist/{packages/blocks → layouts}/desktop-app-shell/src/index.js +0 -0
- /package/dist/{packages/layouts → layouts}/form-layout/src/FormLayout.js +0 -0
- /package/dist/{packages/layouts → layouts}/form-layout/src/FormLayout.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/layouts → layouts}/form-layout/src/index.js +0 -0
- /package/dist/{packages/layouts → layouts}/master-detail/src/MasterDetail.js +0 -0
- /package/dist/{packages/layouts → layouts}/master-detail/src/MasterDetail.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/layouts → layouts}/master-detail/src/index.js +0 -0
- /package/dist/{packages/layouts → layouts}/reading/src/Reading.js +0 -0
- /package/dist/{packages/layouts → layouts}/reading/src/Reading.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/layouts → layouts}/reading/src/index.js +0 -0
- /package/dist/{packages/layouts → layouts}/settings/src/Settings.js +0 -0
- /package/dist/{packages/layouts → layouts}/settings/src/Settings.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/layouts → layouts}/settings/src/index.js +0 -0
- /package/dist/{packages/layouts → layouts}/split-layout/src/SplitLayout.js +0 -0
- /package/dist/{packages/layouts → layouts}/split-layout/src/SplitLayout.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/layouts → layouts}/split-layout/src/index.js +0 -0
- /package/dist/packages/{blocks → composition}/dashboard-grid/src/index.d.ts +0 -0
- /package/dist/packages/{blocks → layouts}/desktop-app-shell/src/index.d.ts +0 -0
- /package/dist/packages/{blocks → patterns}/app-header/src/index.d.ts +0 -0
- /package/dist/packages/{blocks → patterns}/empty-state/src/index.d.ts +0 -0
- /package/dist/packages/{blocks → patterns}/error-state/src/index.d.ts +0 -0
- /package/dist/packages/{blocks → patterns}/error-summary/src/ErrorSummary.vue.d.ts +0 -0
- /package/dist/packages/{blocks → patterns}/error-summary/src/index.d.ts +0 -0
- /package/dist/packages/{blocks → patterns}/form-actions/src/index.d.ts +0 -0
- /package/dist/packages/{blocks → patterns}/form-section/src/index.d.ts +0 -0
- /package/dist/packages/{blocks → patterns}/loading-state/src/LoadingState.vue.d.ts +0 -0
- /package/dist/packages/{blocks → patterns}/loading-state/src/index.d.ts +0 -0
- /package/dist/packages/{blocks → patterns}/metric-card/src/index.d.ts +0 -0
- /package/dist/packages/{blocks → patterns}/page-header/src/PageHeader.vue.d.ts +0 -0
- /package/dist/packages/{blocks → patterns}/page-header/src/index.d.ts +0 -0
- /package/dist/packages/{blocks → patterns}/row-actions/src/RowActions.vue.d.ts +0 -0
- /package/dist/packages/{blocks → patterns}/row-actions/src/index.d.ts +0 -0
- /package/dist/packages/{blocks → patterns}/sidebar-nav/src/SidebarNav.vue.d.ts +0 -0
- /package/dist/packages/{blocks → patterns}/sidebar-nav/src/index.d.ts +0 -0
- /package/dist/packages/{blocks → patterns}/title-bar/src/index.d.ts +0 -0
- /package/dist/packages/{blocks → patterns}/toast-stack/src/ToastStack.vue.d.ts +0 -0
- /package/dist/packages/{blocks → patterns}/toast-stack/src/index.d.ts +0 -0
- /package/dist/{packages/blocks → patterns}/app-header/src/index.js +0 -0
- /package/dist/{packages/blocks → patterns}/empty-state/src/index.js +0 -0
- /package/dist/{packages/blocks → patterns}/error-state/src/index.js +0 -0
- /package/dist/{packages/blocks → patterns}/error-summary/src/index.js +0 -0
- /package/dist/{packages/blocks → patterns}/form-actions/src/index.js +0 -0
- /package/dist/{packages/blocks → patterns}/form-section/src/index.js +0 -0
- /package/dist/{packages/blocks → patterns}/loading-state/src/index.js +0 -0
- /package/dist/{packages/blocks → patterns}/metric-card/src/index.js +0 -0
- /package/dist/{packages/blocks → patterns}/page-header/src/index.js +0 -0
- /package/dist/{packages/blocks → patterns}/row-actions/src/index.js +0 -0
- /package/dist/{packages/blocks → patterns}/sidebar-nav/src/index.js +0 -0
- /package/dist/{packages/blocks → patterns}/title-bar/src/index.js +0 -0
- /package/dist/{packages/blocks → patterns}/toast-stack/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/accordion/src/Accordion.js +0 -0
- /package/dist/{packages/primitives → primitives}/accordion/src/Accordion.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/accordion/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/alert/src/Alert.js +0 -0
- /package/dist/{packages/primitives → primitives}/alert/src/Alert.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/alert/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/alert-dialog/src/AlertDialog.js +0 -0
- /package/dist/{packages/primitives → primitives}/alert-dialog/src/AlertDialog.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/alert-dialog/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/avatar/src/Avatar.js +0 -0
- /package/dist/{packages/primitives → primitives}/avatar/src/Avatar.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/avatar/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/avatar-group/src/AvatarGroup.js +0 -0
- /package/dist/{packages/primitives → primitives}/avatar-group/src/AvatarGroup.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/avatar-group/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/badge/src/Badge.js +0 -0
- /package/dist/{packages/primitives → primitives}/badge/src/Badge.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/badge/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/breadcrumb/src/Breadcrumb.js +0 -0
- /package/dist/{packages/primitives → primitives}/breadcrumb/src/Breadcrumb.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/breadcrumb/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/button/src/Button.js +0 -0
- /package/dist/{packages/primitives → primitives}/button/src/Button.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/button/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/calendar/src/Calendar.js +0 -0
- /package/dist/{packages/primitives → primitives}/calendar/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/card/src/Card.js +0 -0
- /package/dist/{packages/primitives → primitives}/card/src/Card.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/card/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/carousel/src/Carousel.js +0 -0
- /package/dist/{packages/primitives → primitives}/carousel/src/Carousel.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/carousel/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/checkbox/src/Checkbox.js +0 -0
- /package/dist/{packages/primitives → primitives}/checkbox/src/Checkbox.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/checkbox/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/chip/src/Chip.js +0 -0
- /package/dist/{packages/primitives → primitives}/chip/src/Chip.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/chip/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/collapse/src/Collapse.js +0 -0
- /package/dist/{packages/primitives → primitives}/collapse/src/Collapse.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/collapse/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/color-picker/src/ColorPicker.js +0 -0
- /package/dist/{packages/primitives → primitives}/color-picker/src/ColorPicker.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/color-picker/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/combobox/src/Combobox.js +0 -0
- /package/dist/{packages/primitives → primitives}/combobox/src/Combobox.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/combobox/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/command/src/Command.js +0 -0
- /package/dist/{packages/primitives → primitives}/command/src/Command.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/command/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/context-menu/src/ContextMenu.js +0 -0
- /package/dist/{packages/primitives → primitives}/context-menu/src/ContextMenu.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/context-menu/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/copy-button/src/CopyButton.js +0 -0
- /package/dist/{packages/primitives → primitives}/copy-button/src/CopyButton.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/data-grid/src/DataGrid.js +0 -0
- /package/dist/{packages/primitives → primitives}/data-grid/src/DataGrid.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/data-grid/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/date-picker/src/DatePicker.js +0 -0
- /package/dist/{packages/primitives → primitives}/date-picker/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/date-range-picker/src/DateRangePicker.js +0 -0
- /package/dist/{packages/primitives → primitives}/date-range-picker/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/date-time-picker/src/DateTimePicker.js +0 -0
- /package/dist/{packages/primitives → primitives}/date-time-picker/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/date-time-range-picker/src/DateTimeRangePicker.js +0 -0
- /package/dist/{packages/primitives → primitives}/date-time-range-picker/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/dialog/src/Dialog.js +0 -0
- /package/dist/{packages/primitives → primitives}/dialog/src/Dialog.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/dialog/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/drawer/src/Drawer.js +0 -0
- /package/dist/{packages/primitives → primitives}/drawer/src/Drawer.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/drawer/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/dropdown-menu/src/DropdownMenu.js +0 -0
- /package/dist/{packages/primitives → primitives}/dropdown-menu/src/DropdownMenu.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/dropdown-menu/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/editable/src/Editable.js +0 -0
- /package/dist/{packages/primitives → primitives}/editable/src/Editable.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/editable/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/field/src/Field.js +0 -0
- /package/dist/{packages/primitives → primitives}/field/src/Field.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/field/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/fieldset/src/Fieldset.js +0 -0
- /package/dist/{packages/primitives → primitives}/fieldset/src/Fieldset.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/fieldset/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/file-upload/src/FileUpload.js +0 -0
- /package/dist/{packages/primitives → primitives}/file-upload/src/FileUpload.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/file-upload/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/hover-card/src/HoverCard.js +0 -0
- /package/dist/{packages/primitives → primitives}/hover-card/src/HoverCard.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/hover-card/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/icon-button/src/IconButton.js +0 -0
- /package/dist/{packages/primitives → primitives}/icon-button/src/IconButton.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/icon-button/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/indicator/src/Indicator.js +0 -0
- /package/dist/{packages/primitives → primitives}/indicator/src/Indicator.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/indicator/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/inline-error/src/InlineError.js +0 -0
- /package/dist/{packages/primitives → primitives}/inline-error/src/InlineError.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/inline-error/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/kbd/src/Kbd.js +0 -0
- /package/dist/{packages/primitives → primitives}/kbd/src/Kbd.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/kbd/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/link/src/Link.js +0 -0
- /package/dist/{packages/primitives → primitives}/link/src/Link.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/link/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/list/src/List.js +0 -0
- /package/dist/{packages/primitives → primitives}/list/src/List.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/list/src/ListItem.js +0 -0
- /package/dist/{packages/primitives → primitives}/list/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/live-region/src/LiveRegion.js +0 -0
- /package/dist/{packages/primitives → primitives}/live-region/src/LiveRegion.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/live-region/src/context.js +0 -0
- /package/dist/{packages/primitives → primitives}/live-region/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/live-region/src/useAnnounce.js +0 -0
- /package/dist/{packages/primitives → primitives}/menubar/src/Menubar.js +0 -0
- /package/dist/{packages/primitives → primitives}/menubar/src/Menubar.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/menubar/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/meter/src/Meter.js +0 -0
- /package/dist/{packages/primitives → primitives}/meter/src/Meter.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/meter/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/navigation-menu/src/NavigationMenu.js +0 -0
- /package/dist/{packages/primitives → primitives}/navigation-menu/src/NavigationMenu.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/navigation-menu/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/number-field/src/NumberField.js +0 -0
- /package/dist/{packages/primitives → primitives}/number-field/src/NumberField.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/number-field/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/otp-input/src/OtpInput.js +0 -0
- /package/dist/{packages/primitives → primitives}/otp-input/src/OtpInput.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/otp-input/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/pagination/src/Pagination.js +0 -0
- /package/dist/{packages/primitives → primitives}/pagination/src/Pagination.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/pagination/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/popover/src/Popover.js +0 -0
- /package/dist/{packages/primitives → primitives}/popover/src/Popover.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/popover/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/progress/src/Progress.js +0 -0
- /package/dist/{packages/primitives → primitives}/progress/src/Progress.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/progress/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/radial-progress/src/RadialProgress.js +0 -0
- /package/dist/{packages/primitives → primitives}/radial-progress/src/RadialProgress.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/radial-progress/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/radio-group/src/RadioGroup.js +0 -0
- /package/dist/{packages/primitives → primitives}/radio-group/src/RadioGroup.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/radio-group/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/rating/src/Rating.js +0 -0
- /package/dist/{packages/primitives → primitives}/rating/src/Rating.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/rating/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/scroll-area/src/ScrollArea.js +0 -0
- /package/dist/{packages/primitives → primitives}/scroll-area/src/ScrollArea.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/scroll-area/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/segmented-control/src/SegmentedControl.js +0 -0
- /package/dist/{packages/primitives → primitives}/segmented-control/src/SegmentedControl.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/segmented-control/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/select/src/Select.js +0 -0
- /package/dist/{packages/primitives → primitives}/select/src/Select.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/select/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/separator/src/Separator.js +0 -0
- /package/dist/{packages/primitives → primitives}/separator/src/Separator.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/separator/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/skeleton/src/Skeleton.js +0 -0
- /package/dist/{packages/primitives → primitives}/skeleton/src/Skeleton.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/skeleton/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/skip-link/src/SkipLink.js +0 -0
- /package/dist/{packages/primitives → primitives}/skip-link/src/SkipLink.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/skip-link/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/slider/src/Slider.js +0 -0
- /package/dist/{packages/primitives → primitives}/slider/src/Slider.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/slider/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/speed-dial/src/SpeedDial.js +0 -0
- /package/dist/{packages/primitives → primitives}/speed-dial/src/SpeedDial.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/speed-dial/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/spinner/src/Spinner.js +0 -0
- /package/dist/{packages/primitives → primitives}/spinner/src/Spinner.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/spinner/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/stepper/src/Stepper.js +0 -0
- /package/dist/{packages/primitives → primitives}/stepper/src/Stepper.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/stepper/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/surface/src/Surface.js +0 -0
- /package/dist/{packages/primitives → primitives}/surface/src/Surface.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/surface/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/switch/src/Switch.js +0 -0
- /package/dist/{packages/primitives → primitives}/switch/src/Switch.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/switch/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/table/src/Table.js +0 -0
- /package/dist/{packages/primitives → primitives}/table/src/Table.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/table/src/TableCell.js +0 -0
- /package/dist/{packages/primitives → primitives}/table/src/TableCell.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/table/src/TableHead.js +0 -0
- /package/dist/{packages/primitives → primitives}/table/src/TableHead.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/table/src/TableRow.js +0 -0
- /package/dist/{packages/primitives → primitives}/table/src/TableRow.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/table/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/tabs/src/Tabs.js +0 -0
- /package/dist/{packages/primitives → primitives}/tabs/src/Tabs.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/tabs/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/tags-input/src/TagsInput.js +0 -0
- /package/dist/{packages/primitives → primitives}/tags-input/src/TagsInput.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/tags-input/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/text-field/src/TextField.js +0 -0
- /package/dist/{packages/primitives → primitives}/text-field/src/TextField.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/text-field/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/textarea/src/Textarea.js +0 -0
- /package/dist/{packages/primitives → primitives}/textarea/src/Textarea.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/textarea/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/time-picker/src/TimePicker.js +0 -0
- /package/dist/{packages/primitives → primitives}/time-picker/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/timeline/src/Timeline.js +0 -0
- /package/dist/{packages/primitives → primitives}/timeline/src/Timeline.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/timeline/src/TimelineItem.js +0 -0
- /package/dist/{packages/primitives → primitives}/timeline/src/TimelineItem.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/toast/src/Toast.js +0 -0
- /package/dist/{packages/primitives → primitives}/toast/src/Toast.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/toast/src/ToastItem.js +0 -0
- /package/dist/{packages/primitives → primitives}/toast/src/ToastItem.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/toast/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/toggle-group/src/ToggleGroup.js +0 -0
- /package/dist/{packages/primitives → primitives}/toggle-group/src/ToggleGroup.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/toggle-group/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/toolbar/src/Toolbar.js +0 -0
- /package/dist/{packages/primitives → primitives}/toolbar/src/Toolbar.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/toolbar/src/ToolbarSeparator.js +0 -0
- /package/dist/{packages/primitives → primitives}/toolbar/src/ToolbarSeparator.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/toolbar/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/tooltip/src/Tooltip.js +0 -0
- /package/dist/{packages/primitives → primitives}/tooltip/src/Tooltip.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/tooltip/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/tree-view/src/TreeView.js +0 -0
- /package/dist/{packages/primitives → primitives}/tree-view/src/TreeView.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/tree-view/src/TreeViewNode.js +0 -0
- /package/dist/{packages/primitives → primitives}/tree-view/src/TreeViewNode.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/tree-view/src/context.js +0 -0
- /package/dist/{packages/primitives → primitives}/tree-view/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/visually-hidden/src/VisuallyHidden.js +0 -0
- /package/dist/{packages/primitives → primitives}/visually-hidden/src/VisuallyHidden.vue_vue_type_script_setup_true_lang.js +0 -0
- /package/dist/{packages/primitives → primitives}/visually-hidden/src/index.js +0 -0
- /package/dist/{packages/primitives → primitives}/window-controls/src/WindowControls.js +0 -0
- /package/dist/{packages/primitives → primitives}/window-controls/src/index.js +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Field.js","names":[],"sources":["../../../../packages/primitives/field/src/Field.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/* eslint vuejs-accessibility/label-has-for: [\"error\", { \"required\": \"id\" }] */\n/*\n * The workspace default for this rule requires BOTH a `for`/id pairing AND\n * the control physically nested inside the `<label>` (`required: {every:\n * [\"nesting\",\"id\"]}`). Field labels a control passed through the default\n * slot — never nested inside the `<label>` — so \"nesting\" can never be\n * satisfied by any slot-based composition, regardless of how the label is\n * written. The `for`/id pairing below is itself a fully valid, standard\n * accessible-name association (WCAG 1.3.1 / 4.1.2); this override scopes the\n * rule to that single valid strategy for this file only.\n */\nimport { computed, useId, useSlots } from \"vue\";\nimport InlineError from \"@ecoma-io/loom-inline-error\";\nimport { provideFieldContext, useOuterFieldContext } from \"@ecoma-io/loom-labels\";\n\n/**\n * Field — the form-row wrapper: label + control + one hint-or-error line, so\n * a consumer stops hand-assembling that layout at every call site. Pure\n * composition, not a Reka component — the default slot is the control\n * (TextField, Textarea, a select, …). Setting `error` swaps InlineError in\n * for `hint`, because a row shows one message at a time, never both stacked.\n *\n * **A Loom control in the slot wires itself.** Field publishes the row's id,\n * the id of whichever message is showing, and `required` / `invalid` /\n * `disabled` / `readonly` / `name`; every Loom form control picks those up\n * through `useFieldControl()`. So the three attributes this component used to\n * ask a caller to copy by hand — `id`, `aria-describedby`, `invalid` — are now\n * the default, and forgetting one is no longer a silent defect:\n *\n * ```vue\n * <Field label=\"Email\" error=\"Invalid address\" required>\n * <TextField />\n * </Field>\n * ```\n *\n * A prop set on the control always wins, in both directions: `undefined` is\n * the only value that yields, `false` is a decision. One control inside a row\n * that is showing an error can still declare itself individually fine.\n *\n * **`for` is not a legacy path.** `provide`/`inject` only reaches a component\n * that injects, so a bare `<input>`, a product's own control or a third-party\n * widget in the slot cannot be wired this way — and that is the case `for` has\n * always answered. Pass it and the label points at your id, the message line\n * publishes `${for}-description` for your own `aria-describedby`, and a Loom\n * control adopts that id rather than a generated one, so an existing call site\n * keeps every id it published.\n */\nconst props = withDefaults(\n defineProps<{\n /** The visible label text. Renders as a real `<label>` once there is a control for it to name. */\n label?: string;\n /** Supporting text shown below the control. Hidden while `error` is set. */\n hint?: string;\n /** The error message. Renders through InlineError, replaces `hint`, and marks a Loom control inside invalid. */\n error?: string;\n /** Marks the row mandatory: a destructive asterisk on the label, and `aria-required` on a Loom control inside. */\n required?: boolean;\n /** Disables a Loom control inside. Leave unset to let the control decide for itself. */\n disabled?: boolean | undefined;\n /** Renders a Loom control inside read-only: still focusable, still submitted, not editable. */\n readonly?: boolean | undefined;\n /** The name a Loom control inside submits under, for a native form post or `FormData`. */\n name?: string;\n /** The id of the control in the default slot. Omit it and Field generates one for a Loom control. */\n for?: string;\n }>(),\n {\n // `disabled` and `readonly` carry an explicit `undefined` because absent\n // has to stay tellable from `false` all the way down: a Field saying\n // nothing must not overrule a control that disabled itself, and Vue casts\n // an absent Boolean prop with no declared default to `false`. `required`\n // stays a plain boolean — Field is the only thing that claims a row is\n // mandatory, so there is no lower opinion for a `false` to beat.\n required: false,\n disabled: undefined,\n readonly: undefined,\n },\n);\n\n// Called unconditionally, even when `for` makes it unused: `useId()` draws\n// from a per-app counter walked in setup order, and a conditional call makes\n// that sequence depend on props — every id after it shifts, and the server's\n// walk stops matching the client's.\nconst generatedId = useId();\n\n// Whether the call site wrote children at all is a fact about the template,\n// not about state, so it is read once rather than computed — `slots` is not a\n// reactive source and a `computed` over it would cache and go stale. It also\n// has to be answerable during *this* component's render: the server renders a\n// component's own output before any of its slot children, so anything Field\n// learned from the mounted controls would arrive after the label and the hint\n// were already written on the server and before them on the client, which is a\n// hydration mismatch by construction.\nconst hasControl = useSlots().default !== undefined;\n\n// The row's control id is what you passed, or a generated one when there is a\n// control in the slot to give it to. Nothing in the slot means nothing to name\n// and nothing to describe — a `<label for>` pointing at no control names\n// nobody, and an id nothing references is a landmark for no one.\nconst controlId = computed(() => props.for ?? (hasControl ? generatedId : undefined));\n\n// The label's own id, for group controls that name themselves with\n// `aria-labelledby` rather than by `label for`. Follows the same `-label`\n// convention as the description line's `-description`, and it exists for the\n// same reason: a group element inside the slot cannot be pointed at by `<label\n// for>` (that element is not a labelable element), so it needs a second way to\n// learn the label's id.\nconst labelId = computed(() => (controlId.value ? `${controlId.value}-label` : undefined));\n\n// The hint and the error are mutually exclusive, so one id covers whichever is\n// showing.\nconst descriptionId = computed(() =>\n controlId.value ? `${controlId.value}-description` : undefined,\n);\n\n// A Fieldset above answers exactly one key this Field also answers, and its\n// `readonly` is a claim about the whole group that a row does not get to\n// forget. Everything else a Fieldset knows either stops there deliberately\n// (`required`, `invalid`, the group's own description) or travels natively\n// (`disabled`, through the real `<fieldset>`) — see Fieldset.vue. Merging it\n// here rather than inside the context keeps the one overlapping key visible.\nconst group = useOuterFieldContext();\n\nprovideFieldContext({\n controlId: () => controlId.value,\n // Group controls name themselves with `aria-labelledby`, not `label for`, so\n // they need the label's own id. Only when the label is actually rendered: an\n // IDREF that resolves to nothing is worse than no attribute at all.\n labelledBy: () => (props.label ? labelId.value : undefined),\n // Only while a message is actually rendered. An IDREF resolving to nothing\n // is a worse answer than no attribute — the same reasoning Fieldset already\n // carries for its own `aria-describedby`.\n describedBy: () => ((props.error ?? props.hint) ? descriptionId.value : undefined),\n name: () => props.name,\n required: () => props.required || undefined,\n // The row's message and the control's `aria-invalid` are two halves of one\n // state; two independent switches for it is how they come to disagree.\n invalid: () => (props.error ? true : undefined),\n disabled: () => props.disabled,\n readonly: () => props.readonly ?? group?.readonly.value,\n});\n</script>\n\n<template>\n <div class=\"flex flex-col gap-1.5\">\n <label\n v-if=\"label && controlId\"\n :id=\"labelId\"\n :for=\"controlId\"\n class=\"text-sm font-medium text-foreground\"\n >\n {{ label }} <span v-if=\"required\" class=\"text-destructive-text\">*</span>\n </label>\n <span v-else-if=\"label\" class=\"text-sm font-medium text-foreground\">\n {{ label }} <span v-if=\"required\" class=\"text-destructive-text\">*</span>\n </span>\n <slot />\n <p v-if=\"hint && !error\" :id=\"descriptionId\" class=\"text-xs text-muted-foreground\">\n {{ hint }}\n </p>\n <InlineError v-if=\"error\" :id=\"descriptionId\" :message=\"error\" />\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Field.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../packages/primitives/field/src/Field.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/* eslint vuejs-accessibility/label-has-for: [\"error\", { \"required\": \"id\" }] */\n/*\n * The workspace default for this rule requires BOTH a `for`/id pairing AND\n * the control physically nested inside the `<label>` (`required: {every:\n * [\"nesting\",\"id\"]}`). Field labels a control passed through the default\n * slot — never nested inside the `<label>` — so \"nesting\" can never be\n * satisfied by any slot-based composition, regardless of how the label is\n * written. The `for`/id pairing below is itself a fully valid, standard\n * accessible-name association (WCAG 1.3.1 / 4.1.2); this override scopes the\n * rule to that single valid strategy for this file only.\n */\nimport { computed, useId, useSlots } from \"vue\";\nimport InlineError from \"@ecoma-io/loom-inline-error\";\nimport { provideFieldContext, useOuterFieldContext } from \"@ecoma-io/loom-labels\";\n\n/**\n * Field — the form-row wrapper: label + control + one hint-or-error line, so\n * a consumer stops hand-assembling that layout at every call site. Pure\n * composition, not a Reka component — the default slot is the control\n * (TextField, Textarea, a select, …). Setting `error` swaps InlineError in\n * for `hint`, because a row shows one message at a time, never both stacked.\n *\n * **A Loom control in the slot wires itself.** Field publishes the row's id,\n * the id of whichever message is showing, and `required` / `invalid` /\n * `disabled` / `readonly` / `name`; every Loom form control picks those up\n * through `useFieldControl()`. So the three attributes this component used to\n * ask a caller to copy by hand — `id`, `aria-describedby`, `invalid` — are now\n * the default, and forgetting one is no longer a silent defect:\n *\n * ```vue\n * <Field label=\"Email\" error=\"Invalid address\" required>\n * <TextField />\n * </Field>\n * ```\n *\n * A prop set on the control always wins, in both directions: `undefined` is\n * the only value that yields, `false` is a decision. One control inside a row\n * that is showing an error can still declare itself individually fine.\n *\n * **`for` is not a legacy path.** `provide`/`inject` only reaches a component\n * that injects, so a bare `<input>`, a product's own control or a third-party\n * widget in the slot cannot be wired this way — and that is the case `for` has\n * always answered. Pass it and the label points at your id, the message line\n * publishes `${for}-description` for your own `aria-describedby`, and a Loom\n * control adopts that id rather than a generated one, so an existing call site\n * keeps every id it published.\n */\nconst props = withDefaults(\n defineProps<{\n /** The visible label text. Renders as a real `<label>` once there is a control for it to name. */\n label?: string;\n /** Supporting text shown below the control. Hidden while `error` is set. */\n hint?: string;\n /** The error message. Renders through InlineError, replaces `hint`, and marks a Loom control inside invalid. */\n error?: string;\n /** Marks the row mandatory: a destructive asterisk on the label, and `aria-required` on a Loom control inside. */\n required?: boolean;\n /** Disables a Loom control inside. Leave unset to let the control decide for itself. */\n disabled?: boolean | undefined;\n /** Renders a Loom control inside read-only: still focusable, still submitted, not editable. */\n readonly?: boolean | undefined;\n /** The name a Loom control inside submits under, for a native form post or `FormData`. */\n name?: string;\n /** The id of the control in the default slot. Omit it and Field generates one for a Loom control. */\n for?: string;\n }>(),\n {\n // `disabled` and `readonly` carry an explicit `undefined` because absent\n // has to stay tellable from `false` all the way down: a Field saying\n // nothing must not overrule a control that disabled itself, and Vue casts\n // an absent Boolean prop with no declared default to `false`. `required`\n // stays a plain boolean — Field is the only thing that claims a row is\n // mandatory, so there is no lower opinion for a `false` to beat.\n required: false,\n disabled: undefined,\n readonly: undefined,\n },\n);\n\n// Called unconditionally, even when `for` makes it unused: `useId()` draws\n// from a per-app counter walked in setup order, and a conditional call makes\n// that sequence depend on props — every id after it shifts, and the server's\n// walk stops matching the client's.\nconst generatedId = useId();\n\n// Whether the call site wrote children at all is a fact about the template,\n// not about state, so it is read once rather than computed — `slots` is not a\n// reactive source and a `computed` over it would cache and go stale. It also\n// has to be answerable during *this* component's render: the server renders a\n// component's own output before any of its slot children, so anything Field\n// learned from the mounted controls would arrive after the label and the hint\n// were already written on the server and before them on the client, which is a\n// hydration mismatch by construction.\nconst hasControl = useSlots().default !== undefined;\n\n// The row's control id is what you passed, or a generated one when there is a\n// control in the slot to give it to. Nothing in the slot means nothing to name\n// and nothing to describe — a `<label for>` pointing at no control names\n// nobody, and an id nothing references is a landmark for no one.\nconst controlId = computed(() => props.for ?? (hasControl ? generatedId : undefined));\n\n// The label's own id, for group controls that name themselves with\n// `aria-labelledby` rather than by `label for`. Follows the same `-label`\n// convention as the description line's `-description`, and it exists for the\n// same reason: a group element inside the slot cannot be pointed at by `<label\n// for>` (that element is not a labelable element), so it needs a second way to\n// learn the label's id.\nconst labelId = computed(() => (controlId.value ? `${controlId.value}-label` : undefined));\n\n// The hint and the error are mutually exclusive, so one id covers whichever is\n// showing.\nconst descriptionId = computed(() =>\n controlId.value ? `${controlId.value}-description` : undefined,\n);\n\n// A Fieldset above answers exactly one key this Field also answers, and its\n// `readonly` is a claim about the whole group that a row does not get to\n// forget. Everything else a Fieldset knows either stops there deliberately\n// (`required`, `invalid`, the group's own description) or travels natively\n// (`disabled`, through the real `<fieldset>`) — see Fieldset.vue. Merging it\n// here rather than inside the context keeps the one overlapping key visible.\nconst group = useOuterFieldContext();\n\nprovideFieldContext({\n controlId: () => controlId.value,\n // Group controls name themselves with `aria-labelledby`, not `label for`, so\n // they need the label's own id. Only when the label is actually rendered: an\n // IDREF that resolves to nothing is worse than no attribute at all.\n labelledBy: () => (props.label ? labelId.value : undefined),\n // Only while a message is actually rendered. An IDREF resolving to nothing\n // is a worse answer than no attribute — the same reasoning Fieldset already\n // carries for its own `aria-describedby`.\n describedBy: () => ((props.error ?? props.hint) ? descriptionId.value : undefined),\n name: () => props.name,\n required: () => props.required || undefined,\n // The row's message and the control's `aria-invalid` are two halves of one\n // state; two independent switches for it is how they come to disagree.\n invalid: () => (props.error ? true : undefined),\n disabled: () => props.disabled,\n readonly: () => props.readonly ?? group?.readonly.value,\n});\n</script>\n\n<template>\n <div class=\"flex flex-col gap-1.5\">\n <label\n v-if=\"label && controlId\"\n :id=\"labelId\"\n :for=\"controlId\"\n class=\"text-sm font-medium text-foreground\"\n >\n {{ label }} <span v-if=\"required\" class=\"text-destructive-text\">*</span>\n </label>\n <span v-else-if=\"label\" class=\"text-sm font-medium text-foreground\">\n {{ label }} <span v-if=\"required\" class=\"text-destructive-text\">*</span>\n </span>\n <slot />\n <p v-if=\"hint && !error\" :id=\"descriptionId\" class=\"text-xs text-muted-foreground\">\n {{ hint }}\n </p>\n <InlineError v-if=\"error\" :id=\"descriptionId\" :message=\"error\" />\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgDA,MAAM,QAAQ;EAoCd,MAAM,cAAc,MAAM;EAU1B,MAAM,aAAa,SAAS,CAAC,CAAC,YAAY,KAAA;EAM1C,MAAM,YAAY,eAAe,MAAM,QAAQ,aAAa,cAAc,KAAA,EAAU;EAQpF,MAAM,UAAU,eAAgB,UAAU,QAAQ,GAAG,UAAU,MAAM,UAAU,KAAA,CAAU;EAIzF,MAAM,gBAAgB,eACpB,UAAU,QAAQ,GAAG,UAAU,MAAM,gBAAgB,KAAA,CACvD;EAQA,MAAM,QAAQ,qBAAqB;EAEnC,oBAAoB;GAClB,iBAAiB,UAAU;GAI3B,kBAAmB,MAAM,QAAQ,QAAQ,QAAQ,KAAA;GAIjD,mBAAqB,MAAM,SAAS,MAAM,OAAQ,cAAc,QAAQ,KAAA;GACxE,YAAY,MAAM;GAClB,gBAAgB,MAAM,YAAY,KAAA;GAGlC,eAAgB,MAAM,QAAQ,OAAO,KAAA;GACrC,gBAAgB,MAAM;GACtB,gBAAgB,MAAM,YAAY,OAAO,SAAS;EACpD,CAAC;;GAIC,OAAA,UAAA,GAAA,mBAiBM,OAjBN,YAiBM;IAfI,QAAA,SAAS,UAAA,SADjB,UAAA,GAAA,mBAOQ,SAAA;;KALL,IAAI,QAAA;KACJ,KAAK,UAAA;KACN,OAAM;IAEH,GAAA,CAAA,gBAAA,gBAAA,QAAA,KAAK,IAAG,KAAC,CAAA,GAAY,QAAA,YAAZ,UAAA,GAAA,mBAA4D,QAA5D,YAAoD,GAAC,KAAA,mBAAA,IAAA,IAAA,CAAA,GAAA,GAAA,UAAA,KAElD,QAAA,SAAjB,UAAA,GAAA,mBAEO,QAFP,YAEO,CADF,gBAAA,gBAAA,QAAA,KAAK,IAAG,KAAC,CAAA,GAAY,QAAA,YAAZ,UAAA,GAAA,mBAA4D,QAA5D,YAAoD,GAAC,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;IAEnE,WAAQ,KAAA,QAAA,SAAA;IACC,QAAA,QAAI,CAAK,QAAA,SAAlB,UAAA,GAAA,mBAEI,KAAA;;KAFsB,IAAI,cAAA;KAAe,OAAM;IAC9C,GAAA,gBAAA,QAAA,IAAI,GAAA,GAAA,UAAA,KAAA,mBAAA,IAAA,IAAA;IAEU,QAAA,SAAnB,UAAA,GAAA,YAAiE,MAAA,mBAAA,GAAA;;KAAtC,IAAI,cAAA;KAAgB,SAAS,QAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Fieldset.js","names":[],"sources":["../../../../packages/primitives/fieldset/src/Fieldset.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport InlineError from \"@ecoma-io/loom-inline-error\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { useSplitAttrs } from \"@ecoma-io/loom-core\";\nimport { provideFieldContext } from \"@ecoma-io/loom-labels\";\n\n/**\n * Fieldset — several related controls under one name and one shared\n * hint-or-error line: an address block, a set of notification switches, a\n * date range. Where Field is a single row (label, control, message), Fieldset\n * is the group those rows sit in, and the two nest — a Fieldset of Fields is\n * the shape it was drawn for. A lone control does not need a group; that is a\n * Field.\n *\n * It renders a real `<fieldset>` and `<legend>`, and that choice is most of\n * the component. A `<div role=\"group\" aria-labelledby>` names the group just\n * as well and gives up `<fieldset disabled>`, which disables every form\n * control inside it natively — including controls that arrived through the\n * default slot and that Fieldset holds no reference to. Nothing adds that\n * back from a `div`: a wrapper cannot pass a `disabled` prop to a control it\n * never rendered.\n *\n * The hint-or-error line answers exactly as Field's does, for the reason\n * Field.vue sets out — a wrapper cannot reach into a slotted control to set\n * `aria-describedby`, so it publishes a predictable `${id}-description` and\n * leaves that one attribute to the caller. One half differs: Fieldset owns a\n * real element, so it points the group's own `aria-describedby` at that id\n * itself. Wire a control inside to the same id only when you want the message\n * announced a second time on that control.\n *\n * ```vue\n * <Fieldset legend=\"Shipping address\" id=\"shipping\" hint=\"Where the order goes\" required>\n * <Field label=\"Street\"><TextField /></Field>\n * <Field label=\"City\"><TextField /></Field>\n * </Fieldset>\n * ```\n *\n * **The group hands down exactly one thing: `readonly`.** Everything else it\n * knows either travels natively or is a claim about the group that is not\n * automatically a claim about each control in it, and the reasoning is worth\n * stating because the next person will ask:\n *\n * - `disabled` travels through the real `<fieldset>`, and a second mechanism\n * alongside it would be actively harmful rather than merely redundant. One\n * fact carried two ways lets the two disagree: a control written\n * `:disabled=\"false\"` beats a context by the precedence rule, while the\n * native attribute disables it anyway — leaving a control that renders\n * enabled and silently refuses input. The element also reaches strictly\n * further, which is the argument for rendering a `<fieldset>` at all.\n * - `required` and `invalid` stop here. \"This group is mandatory\" is not\n * \"every control in it is mandatory\" — an address block needs a street and\n * not an apartment number — and a group-level error does not make each\n * control in it individually wrong. `aria-required` or `aria-invalid` on a\n * control that is fine is a false statement to the only audience that hears\n * it.\n * - The description stops here too, because unlike Field this component owns a\n * real element and already points its own `aria-describedby` at the message.\n * - `controlId` would collide with the id on the `<fieldset>` itself, and one\n * shared `name` is right for a set of radios and wrong for everything else.\n *\n * `readonly` is left because nothing else can carry it: there is no native\n * `<fieldset readonly>`, and a group shown in view mode is a real state.\n */\nconst props = withDefaults(\n defineProps<{\n /** The group's name, rendered as a real `<legend>` — the accessible name of the group. */\n legend?: string;\n /** Supporting text shown below the group. Hidden while `error` is set. */\n hint?: string;\n /** The group's error message. Renders through InlineError and replaces `hint`. */\n error?: string;\n /** Marks the group mandatory and appends a destructive asterisk to the legend. */\n required?: boolean;\n /** Disables every control inside, slotted ones included, and dims the group. */\n disabled?: boolean;\n /** Renders every Loom control inside read-only: still focusable, still submitted, not editable. */\n readonly?: boolean | undefined;\n /** Set on the `<fieldset>`, and what the hint/error id is derived from (`${id}-description`). */\n id?: string;\n }>(),\n {\n required: false,\n disabled: false,\n // Explicitly `undefined`, not `false`: a Fieldset that says nothing about\n // `readonly` must not overrule a Field or a control that set it, and Vue\n // casts an absent Boolean prop with no declared default to `false`.\n readonly: undefined,\n },\n);\n\nprovideFieldContext({\n controlId: () => undefined,\n describedBy: () => undefined,\n name: () => undefined,\n required: () => undefined,\n invalid: () => undefined,\n disabled: () => undefined,\n readonly: () => props.readonly,\n});\n\n// The hint and the error are mutually exclusive, so one id covers whichever\n// is showing. Undefined without `id`, exactly as in Field: an id nothing can\n// be pointed at is a landmark for no one. Undefined with no message either —\n// unlike Field, this id is also spent on the group's own `aria-describedby`,\n// and an IDREF resolving to nothing is a worse answer than no attribute.\nconst descriptionId = computed(() =>\n props.id && (props.hint ?? props.error) ? `${props.id}-description` : undefined,\n);\n\n// One rendered node, so this split is only about `class`. Vue's own\n// fallthrough merge concatenates the two lists rather than resolving them, so\n// a caller's `min-w-full` would beat — or lose to — the `min-w-0` below on\n// Tailwind's emission order instead of on being the later declaration. That\n// one utility is load-bearing (see the root class), so the merge has to be\n// Tailwind-aware.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: fieldsetAttrs } = useSplitAttrs();\n</script>\n\n<template>\n <fieldset\n v-bind=\"fieldsetAttrs\"\n :id=\"id\"\n :disabled=\"disabled\"\n :aria-describedby=\"descriptionId\"\n :class=\"\n cn(\n 'flex flex-col gap-4',\n // Not defensive. Every UA stylesheet gives `<fieldset>` a\n // `min-inline-size: min-content` that no `width` can beat, so a group\n // holding a text input refuses to shrink below that input's intrinsic\n // width and blows out the column of any consumer who drops one into a\n // form grid. Overriding the minimum itself is the only fix.\n 'min-w-0',\n // `group`, and no `opacity`. Dimming the group was the worst instance\n // of that mistake in the library, because opacity *composites* and\n // therefore multiplies: this element's 50% ran over a Switch's or a\n // Select's own 50%, so a control inside a disabled group rendered at\n // 25% effective alpha and its label measured 1.65:1 — and the group's\n // own hint, one dim rather than two, still came out at 2.05:1. Neither\n // was reachable by fixing the controls, because neither was the\n // controls' doing.\n //\n // Removing it here is what un-multiplies them: a nested control now\n // computes only its own drained treatment (Select and OtpInput land\n // their labels on 4.67:1 that way), and nothing this element does\n // reduces it further. The group still reads as unavailable — the\n // legend below mutes, and every control in it wears its own disabled\n // state — and the native `disabled` attribute carries the fact to\n // assistive tech, so none of it rests on colour alone.\n //\n // And no fill either, which is the other half of the same answer. Every\n // control in the library drains to `bg-muted` when it is unavailable,\n // so a `bg-muted` on the group would be that exact colour running\n // edge-to-edge behind them: the fills would meet at 1:1 and a row of\n // disabled controls would read as one grey slab with no controls in it.\n // The group is a grouping, not a surface — it has no fill available and\n // no `readonly` appearance either, because a read-only group is a group\n // of read-only controls, each of which now says so on its own.\n 'disabled:cursor-not-allowed',\n 'group',\n attrs.class as string,\n )\n \"\n >\n <!-- Deliberately borderless, like Field: with no border to interrupt, the\n legend's notch rendering never arises and the group is spaced rather\n than boxed. The margin is not a stand-in for the container's `gap`\n either — a rendered legend sits outside the anonymous box that holds\n a fieldset's content, so it is never a flex item and no `gap` reaches\n it. -->\n <!-- The legend is where \"this whole group is unavailable\" is now painted:\n it is the group's accessible name and the only text the group owns\n rather than borrows. `group-disabled:` reads the real `:disabled` on\n the `<fieldset>` above, so there is no second copy of the state to fall\n out of step with the attribute. 14.09:1 available, 5.25:1 not — a drop\n a reader can see, at a colour they can still read. -->\n <legend\n v-if=\"legend\"\n class=\"mb-2 text-sm font-medium text-foreground group-disabled:text-muted-foreground\"\n >\n {{ legend }} <span v-if=\"required\" class=\"text-destructive-text\">*</span>\n </legend>\n <!-- @slot The controls in the group — Fields, most often. -->\n <slot />\n <p v-if=\"hint && !error\" :id=\"descriptionId\" class=\"text-xs text-muted-foreground\">\n {{ hint }}\n </p>\n <InlineError v-if=\"error\" :id=\"descriptionId\" :message=\"error\" />\n </fieldset>\n</template>\n"],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Fieldset.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../packages/primitives/fieldset/src/Fieldset.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport InlineError from \"@ecoma-io/loom-inline-error\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { useSplitAttrs } from \"@ecoma-io/loom-core\";\nimport { provideFieldContext } from \"@ecoma-io/loom-labels\";\n\n/**\n * Fieldset — several related controls under one name and one shared\n * hint-or-error line: an address block, a set of notification switches, a\n * date range. Where Field is a single row (label, control, message), Fieldset\n * is the group those rows sit in, and the two nest — a Fieldset of Fields is\n * the shape it was drawn for. A lone control does not need a group; that is a\n * Field.\n *\n * It renders a real `<fieldset>` and `<legend>`, and that choice is most of\n * the component. A `<div role=\"group\" aria-labelledby>` names the group just\n * as well and gives up `<fieldset disabled>`, which disables every form\n * control inside it natively — including controls that arrived through the\n * default slot and that Fieldset holds no reference to. Nothing adds that\n * back from a `div`: a wrapper cannot pass a `disabled` prop to a control it\n * never rendered.\n *\n * The hint-or-error line answers exactly as Field's does, for the reason\n * Field.vue sets out — a wrapper cannot reach into a slotted control to set\n * `aria-describedby`, so it publishes a predictable `${id}-description` and\n * leaves that one attribute to the caller. One half differs: Fieldset owns a\n * real element, so it points the group's own `aria-describedby` at that id\n * itself. Wire a control inside to the same id only when you want the message\n * announced a second time on that control.\n *\n * ```vue\n * <Fieldset legend=\"Shipping address\" id=\"shipping\" hint=\"Where the order goes\" required>\n * <Field label=\"Street\"><TextField /></Field>\n * <Field label=\"City\"><TextField /></Field>\n * </Fieldset>\n * ```\n *\n * **The group hands down exactly one thing: `readonly`.** Everything else it\n * knows either travels natively or is a claim about the group that is not\n * automatically a claim about each control in it, and the reasoning is worth\n * stating because the next person will ask:\n *\n * - `disabled` travels through the real `<fieldset>`, and a second mechanism\n * alongside it would be actively harmful rather than merely redundant. One\n * fact carried two ways lets the two disagree: a control written\n * `:disabled=\"false\"` beats a context by the precedence rule, while the\n * native attribute disables it anyway — leaving a control that renders\n * enabled and silently refuses input. The element also reaches strictly\n * further, which is the argument for rendering a `<fieldset>` at all.\n * - `required` and `invalid` stop here. \"This group is mandatory\" is not\n * \"every control in it is mandatory\" — an address block needs a street and\n * not an apartment number — and a group-level error does not make each\n * control in it individually wrong. `aria-required` or `aria-invalid` on a\n * control that is fine is a false statement to the only audience that hears\n * it.\n * - The description stops here too, because unlike Field this component owns a\n * real element and already points its own `aria-describedby` at the message.\n * - `controlId` would collide with the id on the `<fieldset>` itself, and one\n * shared `name` is right for a set of radios and wrong for everything else.\n *\n * `readonly` is left because nothing else can carry it: there is no native\n * `<fieldset readonly>`, and a group shown in view mode is a real state.\n */\nconst props = withDefaults(\n defineProps<{\n /** The group's name, rendered as a real `<legend>` — the accessible name of the group. */\n legend?: string;\n /** Supporting text shown below the group. Hidden while `error` is set. */\n hint?: string;\n /** The group's error message. Renders through InlineError and replaces `hint`. */\n error?: string;\n /** Marks the group mandatory and appends a destructive asterisk to the legend. */\n required?: boolean;\n /** Disables every control inside, slotted ones included, and dims the group. */\n disabled?: boolean;\n /** Renders every Loom control inside read-only: still focusable, still submitted, not editable. */\n readonly?: boolean | undefined;\n /** Set on the `<fieldset>`, and what the hint/error id is derived from (`${id}-description`). */\n id?: string;\n }>(),\n {\n required: false,\n disabled: false,\n // Explicitly `undefined`, not `false`: a Fieldset that says nothing about\n // `readonly` must not overrule a Field or a control that set it, and Vue\n // casts an absent Boolean prop with no declared default to `false`.\n readonly: undefined,\n },\n);\n\nprovideFieldContext({\n controlId: () => undefined,\n describedBy: () => undefined,\n name: () => undefined,\n required: () => undefined,\n invalid: () => undefined,\n disabled: () => undefined,\n readonly: () => props.readonly,\n});\n\n// The hint and the error are mutually exclusive, so one id covers whichever\n// is showing. Undefined without `id`, exactly as in Field: an id nothing can\n// be pointed at is a landmark for no one. Undefined with no message either —\n// unlike Field, this id is also spent on the group's own `aria-describedby`,\n// and an IDREF resolving to nothing is a worse answer than no attribute.\nconst descriptionId = computed(() =>\n props.id && (props.hint ?? props.error) ? `${props.id}-description` : undefined,\n);\n\n// One rendered node, so this split is only about `class`. Vue's own\n// fallthrough merge concatenates the two lists rather than resolving them, so\n// a caller's `min-w-full` would beat — or lose to — the `min-w-0` below on\n// Tailwind's emission order instead of on being the later declaration. That\n// one utility is load-bearing (see the root class), so the merge has to be\n// Tailwind-aware.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: fieldsetAttrs } = useSplitAttrs();\n</script>\n\n<template>\n <fieldset\n v-bind=\"fieldsetAttrs\"\n :id=\"id\"\n :disabled=\"disabled\"\n :aria-describedby=\"descriptionId\"\n :class=\"\n cn(\n 'flex flex-col gap-4',\n // Not defensive. Every UA stylesheet gives `<fieldset>` a\n // `min-inline-size: min-content` that no `width` can beat, so a group\n // holding a text input refuses to shrink below that input's intrinsic\n // width and blows out the column of any consumer who drops one into a\n // form grid. Overriding the minimum itself is the only fix.\n 'min-w-0',\n // `group`, and no `opacity`. Dimming the group was the worst instance\n // of that mistake in the library, because opacity *composites* and\n // therefore multiplies: this element's 50% ran over a Switch's or a\n // Select's own 50%, so a control inside a disabled group rendered at\n // 25% effective alpha and its label measured 1.65:1 — and the group's\n // own hint, one dim rather than two, still came out at 2.05:1. Neither\n // was reachable by fixing the controls, because neither was the\n // controls' doing.\n //\n // Removing it here is what un-multiplies them: a nested control now\n // computes only its own drained treatment (Select and OtpInput land\n // their labels on 4.67:1 that way), and nothing this element does\n // reduces it further. The group still reads as unavailable — the\n // legend below mutes, and every control in it wears its own disabled\n // state — and the native `disabled` attribute carries the fact to\n // assistive tech, so none of it rests on colour alone.\n //\n // And no fill either, which is the other half of the same answer. Every\n // control in the library drains to `bg-muted` when it is unavailable,\n // so a `bg-muted` on the group would be that exact colour running\n // edge-to-edge behind them: the fills would meet at 1:1 and a row of\n // disabled controls would read as one grey slab with no controls in it.\n // The group is a grouping, not a surface — it has no fill available and\n // no `readonly` appearance either, because a read-only group is a group\n // of read-only controls, each of which now says so on its own.\n 'disabled:cursor-not-allowed',\n 'group',\n attrs.class as string,\n )\n \"\n >\n <!-- Deliberately borderless, like Field: with no border to interrupt, the\n legend's notch rendering never arises and the group is spaced rather\n than boxed. The margin is not a stand-in for the container's `gap`\n either — a rendered legend sits outside the anonymous box that holds\n a fieldset's content, so it is never a flex item and no `gap` reaches\n it. -->\n <!-- The legend is where \"this whole group is unavailable\" is now painted:\n it is the group's accessible name and the only text the group owns\n rather than borrows. `group-disabled:` reads the real `:disabled` on\n the `<fieldset>` above, so there is no second copy of the state to fall\n out of step with the attribute. 14.09:1 available, 5.25:1 not — a drop\n a reader can see, at a colour they can still read. -->\n <legend\n v-if=\"legend\"\n class=\"mb-2 text-sm font-medium text-foreground group-disabled:text-muted-foreground\"\n >\n {{ legend }} <span v-if=\"required\" class=\"text-destructive-text\">*</span>\n </legend>\n <!-- @slot The controls in the group — Fields, most often. -->\n <slot />\n <p v-if=\"hint && !error\" :id=\"descriptionId\" class=\"text-xs text-muted-foreground\">\n {{ hint }}\n </p>\n <InlineError v-if=\"error\" :id=\"descriptionId\" :message=\"error\" />\n </fieldset>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgEA,MAAM,QAAQ;EA2Bd,oBAAoB;GAClB,iBAAiB,KAAA;GACjB,mBAAmB,KAAA;GACnB,YAAY,KAAA;GACZ,gBAAgB,KAAA;GAChB,eAAe,KAAA;GACf,gBAAgB,KAAA;GAChB,gBAAgB,MAAM;EACxB,CAAC;EAOD,MAAM,gBAAgB,eACpB,MAAM,OAAO,MAAM,QAAQ,MAAM,SAAS,GAAG,MAAM,GAAG,gBAAgB,KAAA,CACxE;EASA,MAAM,EAAE,OAAO,MAAM,kBAAkB,cAAc;;GAInD,OAAA,UAAA,GAAA,mBAqEW,YArEX,WACU,MAoEC,aAAA,GApEY;IACpB,IAAI,QAAA;IACJ,UAAU,QAAA;IACV,oBAAkB,cAAA;IAClB,OAAc,MAAA,EAAA,CAAE,CAAA,uBAAA,WAAA,+BAAA,SAAqrE,MAAA,KAAA,CAAK,CAAC,KAAA;;IAqDpsE,QAAA,UADR,UAAA,GAAA,mBAKS,UALT,YAKS,CADJ,gBAAA,gBAAA,QAAA,MAAM,IAAG,KAAC,CAAA,GAAY,QAAA,YAAZ,UAAA,GAAA,mBAA4D,QAA5D,YAAoD,GAAC,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;IAGpE,WAAQ,KAAA,QAAA,SAAA;IACC,QAAA,QAAI,CAAK,QAAA,SAAlB,UAAA,GAAA,mBAEI,KAAA;;KAFsB,IAAI,cAAA;KAAe,OAAM;IAC9C,GAAA,gBAAA,QAAA,IAAI,GAAA,GAAA,UAAA,KAAA,mBAAA,IAAA,IAAA;IAEU,QAAA,SAAnB,UAAA,GAAA,YAAiE,MAAA,mBAAA,GAAA;;KAAtC,IAAI,cAAA;KAAgB,SAAS,QAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileUpload.js","names":[],"sources":["../../../../packages/primitives/file-upload/src/FileUpload.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { FileUploadLabels, FileUploadRejection } from \"@ecoma-io/loom-labels\";\n\nconst BYTE_UNITS = [\"B\", \"KB\", \"MB\", \"GB\"] as const;\n\n/**\n * A byte count as a person reads it.\n *\n * Binary steps with the short decimal names, which is what every operating\n * system file dialog beside this control shows — a reader comparing \"1.4 MB\"\n * here against \"1.4 MB\" in their own file browser should see the same number,\n * and the pedantically-correct \"1.5 MB\" (or \"1.4 MiB\") only reads as a bug.\n * One decimal below ten and none above it, so the size column stays the same\n * width down the list.\n *\n * Deliberately not exported: it is a formatter this control needs, not a\n * public utility, and the moment a host imports it from here the wording of a\n * file size becomes part of this component's API.\n */\nfunction formatBytes(bytes: number): string {\n let value = Math.max(bytes, 0);\n let step = 0;\n while (value >= 1024 && step < BYTE_UNITS.length - 1) {\n value /= 1024;\n step += 1;\n }\n const rounded = step > 0 && value < 10 ? Math.round(value * 10) / 10 : Math.round(value);\n return `${String(rounded)} ${BYTE_UNITS[step] ?? \"B\"}`;\n}\n\n/**\n * Every refusal names the file, because the reader is looking at a list of\n * several and \"that file is too large\" identifies none of them.\n */\nfunction describeRejection(rejection: FileUploadRejection, limit: string): string {\n const name = rejection.file.name;\n switch (rejection.reason) {\n case \"too-large\":\n return `${name} is larger than ${limit}.`;\n case \"type\":\n return `${name} is not an accepted file type.`;\n case \"duplicate\":\n return `${name} has already been chosen.`;\n case \"too-many\":\n return `${name} was not added — only one file can be chosen.`;\n }\n}\n\n/**\n * Loom's English, co-located with the component so it tree-shakes with it, and\n * exported so a host can build a partial vocabulary against the real thing.\n */\nexport const FILE_UPLOAD_LABELS: FileUploadLabels = {\n zone: ({ multiple }) =>\n multiple ? \"Choose files or drag them here\" : \"Choose a file or drag it here\",\n hint: ({ maxSize }) => `Up to ${formatBytes(maxSize)}`,\n size: ({ bytes }) => formatBytes(bytes),\n remove: ({ file }) => `Remove ${file.name}`,\n rejected: ({ rejections, maxSize }) => {\n const limit = maxSize === undefined ? \"the size limit\" : formatBytes(maxSize);\n return rejections.map((rejection) => describeRejection(rejection, limit)).join(\" \");\n },\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref, useId, useTemplateRef } from \"vue\";\nimport { CloudUpload, File as FileIcon, TriangleAlert, X } from \"@lucide/vue\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { listStaggerDelay } from \"@ecoma-io/loom-core\";\nimport { useSplitAttrs } from \"@ecoma-io/loom-core\";\nimport { useAncestorDisabled } from \"@ecoma-io/loom-labels\";\nimport { useFieldControl } from \"@ecoma-io/loom-labels\";\nimport { useLabels, type LabelOverrides } from \"@ecoma-io/loom-labels\";\n\n/**\n * FileUpload — choosing files, and nothing else. A drop zone that is also a\n * real file dialog, plus the list of what has been chosen so far, with each\n * row removable.\n *\n * **It chooses; it does not upload.** There is no progress bar here and no\n * request: the host reads `modelValue`, sends it wherever it goes, and renders\n * `Progress` (or `Spinner`, when there is no percentage) for that half. Two\n * controls rather than one, because the upload's states — retrying, partial,\n * failed on the server — belong to whatever is doing the uploading, and a\n * control that owned both would have to guess at all of them.\n *\n * **Drag and drop is a shortcut, never the path.** The zone is a `<label>`\n * wrapped around a real `<input type=\"file\">`, visually hidden by the clip\n * technique rather than by `display: none` or `hidden` — both of which take\n * the input out of the tab order and leave a control only a pointer can reach.\n * Tab lands on the input, Space or Enter opens the system file dialog, and the\n * zone draws the focus ring on its behalf because a 1px input cannot show one.\n * A `div` with a click handler in place of that input is the standard defect\n * in this control, and it is invisible to everyone testing with a mouse.\n *\n * Files arriving while `multiple` is set are appended to the list rather than\n * replacing it: a reader who drops two files and then a third means three, and\n * the native input's replace-everything behaviour is the surprise. Without\n * `multiple` the newest choice replaces the old one, exactly as the input does.\n *\n * Inside a [Field](../Field/Field.vue) it wires itself through\n * `useFieldControl()`: the row's id lands on the input (and on the `<label>`'s\n * `for`, so the zone keeps activating it), and the row's `name`, `required`,\n * `invalid` and the id of its hint or error line arrive with it. The row's\n * description is **merged** with this control's own refusal message rather than\n * replacing it — a file turned away for being too large has to keep saying so.\n *\n * There is no `readonly`, and a row's is ignored rather than approximated.\n * `readonly` is inert on `<input type=\"file\">` in every browser, for the reason\n * it is inert on a checkbox: there is no text to protect, only a dialog to\n * open. A zone that may be read but not added to is a disabled zone above a\n * list — and the list, which is where the value actually is, stays readable\n * either way.\n */\nconst props = withDefaults(\n defineProps<{\n /** The chosen files. Leave it unbound to let the control keep its own list. */\n modelValue?: File[] | undefined;\n /** What the file dialog offers and what a drop is checked against — the native `accept` syntax: `.csv`, `image/png`, `image/*`, comma-separated. */\n accept?: string;\n /** Allows more than one file, and appends each new choice to the list instead of replacing it. */\n multiple?: boolean;\n /** Largest file accepted, in bytes. A file over it is refused and named in the message. */\n maxSize?: number;\n /** Unavailable: dims the zone, refuses the dialog, the drop and every remove button. Unset defers to a wrapping Field. */\n disabled?: boolean | undefined;\n /** Error state: paints the destructive border and ring, and sets `aria-invalid` on the input. Unset defers to a wrapping Field's `error`. */\n invalid?: boolean | undefined;\n /** The zone's own line of copy, which is also the input's accessible name. Defaults to `labels.zone`, whose wording matches `multiple`. */\n label?: string;\n /** The smaller line under it. Defaults to `labels.hint` against the `maxSize` limit, when there is one. */\n hint?: string;\n /**\n * Everything this control says that is not a file name, as any subset of\n * `FileUploadLabels` — the rest stay as the host's `provideLoomLabels`\n * vocabulary left them, and then as Loom's English.\n *\n * This is the per-instance correction, not the place to localise an\n * application. `label` and `hint` are the shorter way to reach the two\n * keys of the same name for one zone; this is what reaches the refusal\n * message, the remove buttons and the size column.\n */\n labels?: LabelOverrides<FileUploadLabels>;\n }>(),\n {\n // Not `[]`. An empty array is a concrete value, so it would say \"the host\n // owns this list\" — and a host that binds nothing would then watch every\n // file it chose vanish on the next render. `undefined` is what leaves the\n // control managing its own, the same distinction `optional()` exists to\n // preserve for the Reka-backed primitives.\n modelValue: undefined,\n multiple: false,\n // Not `false`, for either. `false` is a caller saying \"this zone is fine /\n // enabled even though its row is not\"; absent is a caller saying nothing,\n // and only `undefined` survives to mean that past Vue's\n // absent-Boolean-casts-to-false rule — see TextField.vue, which carries the\n // full reasoning.\n disabled: undefined,\n invalid: undefined,\n },\n);\n\nconst emit = defineEmits<{\n /** The full list after the change — files added, or one removed. Never a partial list. */\n \"update:modelValue\": [files: File[]];\n /** Every file refused by this one interaction, each with the rule that refused it. Fires once per interaction, not once per file. */\n reject: [rejections: FileUploadRejection[]];\n}>();\n\n// `text`, not `labels`: the prop of that name is one of the three sources this\n// resolves, and a template reading the raw prop would be reading the overrides\n// rather than the answer.\nconst text = useLabels(\"fileUpload\", FILE_UPLOAD_LABELS, () => props.labels);\n\n// `class` sizes the whole control, so it lands on the root; everything else a\n// caller passes — `name`, `id`, `data-testid`, `aria-describedby` — describes\n// the real `<input type=\"file\">` and lands there. Splitting them is the only\n// way to route both correctly: the root is not a form control and the input is\n// not the box a caller lays out.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: inputAttrs } = useSplitAttrs();\n\n// The label's `for` needs the input's id, and a caller passing their own id —\n// or a Field row publishing one — must not end up with a label pointing at\n// nothing. `inputId` is resolved from `field` at the foot of this block.\nconst generatedId = useId();\nconst messageId = useId();\n\nconst ownFiles = ref<File[]>([]);\nconst files = computed(() => props.modelValue ?? ownFiles.value);\n\nconst rejections = ref<FileUploadRejection[]>([]);\n\n/**\n * A stable key per file, held against the File object itself.\n *\n * Keying the rows by index instead re-keys every row after the one removed, so\n * removing the first of five replays the entrance animation on the other four\n * — the list appears to reload because one row left it. A WeakMap keys by\n * identity, holds nothing alive, and survives the list being reordered.\n */\nconst rowIds = new WeakMap<File, number>();\nlet nextRowId = 0;\nfunction rowId(file: File): number {\n let id = rowIds.get(file);\n if (id === undefined) {\n id = nextRowId++;\n rowIds.set(file, id);\n }\n return id;\n}\n\n/** Name, size and mtime — what the file system itself calls the same file. */\nfunction signature(file: File): string {\n return `${file.name}:${String(file.size)}:${String(file.lastModified)}`;\n}\n\n/**\n * The same test the native input applies to `accept`, applied again to a drop\n * — the browser enforces it in the file dialog and not at all on a drag, so a\n * zone that only sets the attribute accepts anything dropped on it.\n *\n * `file.type` is the browser's guess from the extension and it is empty for\n * anything it does not recognise, which is why an `accept` written as MIME\n * types alone turns away files it meant to take. Naming both — `.csv,text/csv`\n * — is the form that works, and it is what the documentation shows.\n */\nfunction accepts(file: File): boolean {\n const accept = props.accept?.trim();\n if (accept === undefined || accept.length === 0) return true;\n const name = file.name.toLowerCase();\n const type = file.type.toLowerCase();\n return accept.split(\",\").some((raw) => {\n const pattern = raw.trim().toLowerCase();\n if (pattern.length === 0) return false;\n if (pattern.startsWith(\".\")) return name.endsWith(pattern);\n if (pattern.endsWith(\"/*\")) return type.startsWith(pattern.slice(0, -1));\n return type === pattern;\n });\n}\n\nfunction commit(next: File[]): void {\n if (props.modelValue === undefined) ownFiles.value = next;\n emit(\"update:modelValue\", next);\n}\n\n/** Runs the offered files past every rule, keeping what passes and reporting the rest. */\nfunction add(incoming: File[]): void {\n if (field.disabled) return;\n\n const current = files.value;\n const kept = props.multiple ? [...current] : [];\n const seen = new Set(kept.map(signature));\n const refused: FileUploadRejection[] = [];\n const limit = props.maxSize;\n\n for (const file of incoming) {\n if (!props.multiple && kept.length > 0) {\n refused.push({ file, reason: \"too-many\" });\n } else if (limit !== undefined && file.size > limit) {\n refused.push({ file, reason: \"too-large\" });\n } else if (!accepts(file)) {\n refused.push({ file, reason: \"type\" });\n } else if (seen.has(signature(file))) {\n refused.push({ file, reason: \"duplicate\" });\n } else {\n seen.add(signature(file));\n kept.push(file);\n }\n }\n\n rejections.value = refused;\n if (refused.length > 0) emit(\"reject\", refused);\n\n const unchanged = kept.length === current.length && kept.every((file, i) => file === current[i]);\n if (!unchanged) commit(kept);\n}\n\nfunction remove(index: number): void {\n if (field.disabled) return;\n // The message named files from the last selection. Once the reader edits the\n // list themselves it no longer describes anything on screen, and an error\n // sitting under a list somebody is actively fixing reads as an error about\n // that list.\n rejections.value = [];\n commit(files.value.filter((_, i) => i !== index));\n}\n\nfunction onSelect(event: Event): void {\n const input = event.target as HTMLInputElement;\n add(Array.from(input.files ?? []));\n // Cleared so choosing the same file a second time still fires `change`. The\n // input compares the new selection against its own value and stays silent\n // when they match — which, after a file has been removed from the list, is a\n // control that refuses to take back the file the reader just took out.\n input.value = \"\";\n}\n\n/**\n * Enters minus leaves, rather than a boolean.\n *\n * `dragleave` fires on the zone every time the pointer crosses onto one of its\n * own children, so an enter/leave pair drops the highlight and picks it up\n * again as the reader drags across the icon and the copy — the zone flickers\n * under the cursor at the exact moment it is meant to be saying \"let go here\".\n * A child's `dragenter` always lands before the parent's `dragleave`, so the\n * count never reaches zero until the pointer has genuinely left. `relatedTarget`\n * answers the same question in one line, but it is not reliably populated for a\n * drag that began outside the document — which is every drag this zone sees.\n */\nconst dragDepth = ref(0);\nconst dragging = computed(() => dragDepth.value > 0 && !field.disabled);\n\nfunction onDragEnter(): void {\n dragDepth.value += 1;\n}\n\nfunction onDragLeave(): void {\n dragDepth.value = Math.max(dragDepth.value - 1, 0);\n}\n\nfunction onDragOver(event: DragEvent): void {\n // Without this the browser keeps its default handling, which for a file is\n // \"navigate to it\" — the drop never reaches the zone and the page is gone.\n // Setting dropEffect is what makes the cursor say copy rather than move.\n event.preventDefault();\n if (event.dataTransfer) event.dataTransfer.dropEffect = field.disabled ? \"none\" : \"copy\";\n}\n\nfunction onDrop(event: DragEvent): void {\n event.preventDefault();\n // Reset rather than decrement: the drop consumes the drag, and no matching\n // `dragleave` follows it.\n dragDepth.value = 0;\n add(Array.from(event.dataTransfer?.files ?? []));\n}\n\n// Nothing here listens on `window` or `document`. A page-wide drag handler\n// would be the usual way to stop a file dropped *beside* the zone from\n// navigating the browser away, but a library primitive that installs one\n// silently governs every other drop target on the host's page. That decision\n// is the host's, so the listeners a component cannot tear down are the ones it\n// never registers.\n\n// The two content props sit *above* the resolved label rather than replacing\n// it: `label` is the wording for one zone — \"Drop last month's export here\" —\n// and the label is what every other zone says. Read through `text.` here and\n// not resolved above, so a language switch after mount repaints the copy.\nconst zoneLabel = computed(() => props.label ?? text.value.zone({ multiple: props.multiple }));\n\nconst zoneHint = computed(() => {\n if (props.hint !== undefined) return props.hint;\n // The limit is handed over as a byte count, never as `formatBytes` output: a\n // host that writes `1,5 Mo` or Eastern Arabic digits cannot get there from a\n // string this component already decided the shape of.\n return props.maxSize === undefined ? undefined : text.value.hint({ maxSize: props.maxSize });\n});\n\n// One call over the whole list rather than one per refusal joined with a\n// space. The joiner was the fragment: which character separates two sentences\n// is a property of the script, and a language that would rather count the\n// refused files than list them has no way to say so from a per-file message.\nconst message = computed(() =>\n rejections.value.length === 0\n ? \"\"\n : text.value.rejected({ rejections: rejections.value, maxSize: props.maxSize }),\n);\n\n/**\n * The drop is the reason this control cannot be left to the platform.\n *\n * `<fieldset disabled>` makes the nested `<input type=\"file\">` inert, which\n * closes the click and the keyboard, and it makes each file's remove button\n * inert too. It does nothing at all to the `drop` handler, because that sits on\n * a `<label>` — not a form control, and never disabled by a fieldset. `add()`\n * bails on `field.disabled`, which is exactly the value a disabled fieldset\n * does not reach, so a zone inside a disabled group accepted a dragged file\n * while refusing every other way in.\n *\n * Read off the DOM rather than taken from the Field context, which publishes no\n * `disabled` on purpose — see `../../lib/ancestor-disabled.ts`.\n */\nconst root = useTemplateRef<HTMLElement>(\"root\");\nconst groupDisabled = useAncestorDisabled(() => root.value);\n\n// The Field wiring sits here, below `message`, because it reads it: this is the\n// one control in the family that already had something of its own to say about\n// itself, so its `describedBy` is a *merge* and not a hand-over. Its refusal\n// message reads first — a file turned away for being too large is the most\n// specific thing there is to say — then whatever the caller pointed at, then\n// the row's hint or error, which `useFieldControl` appends. Replacing rather\n// than merging at either end is how a rejection stops being announced.\n//\n// The condition is `message` itself, not `rejections`, so the id can never\n// point at a `<p>` the template has not rendered.\n//\n// `name` and `required` are absent from the object because this component has\n// no prop for either: the row's answer stands unopposed, and its `name` reaches\n// the real `<input type=\"file\">`, which is what a `<form>` posts. `readonly` is\n// absent for the reason the docblock gives.\nconst field = useFieldControl(() => ({\n id: attrs.id as string | undefined,\n describedBy: [message.value.length > 0 ? messageId : undefined, attrs[\"aria-describedby\"]]\n .filter((id): id is string => typeof id === \"string\" && id.length > 0)\n .join(\" \"),\n // The fieldset beats the prop in both directions, exactly as it does for the\n // `<input type=\"file\">` inside this very control.\n disabled: groupDisabled.value ? true : props.disabled,\n invalid: props.invalid,\n}));\n\n// `field.id` is the caller's own id, then the row's; the generated one is the\n// floor beneath both, because the `<label for>` and the input have to agree on\n// an id whether or not anybody supplied one.\nconst inputId = computed(() => field.id ?? generatedId);\n</script>\n\n<template>\n <div ref=\"root\" :class=\"cn('flex w-full flex-col', attrs.class as string)\">\n <!-- The drag handlers sit on a <label>, which the rule reads as a static\n element — and it is usually right to: a box with a drop handler and\n nothing else is a control no keyboard can reach. Here the keyboard\n path is the real <input type=\"file\"> nested inside, which the label\n both names and activates, so the drop adds a pointer shortcut to a\n control that already works without one. -->\n <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->\n <label\n :for=\"inputId\"\n :data-dragging=\"dragging || undefined\"\n :data-invalid=\"field.invalid || undefined\"\n :data-disabled=\"field.disabled || undefined\"\n :class=\"\n cn(\n // `group` so the two lines of copy below can name their own disabled\n // colour off this element's state. A colour set here would only be\n // *inherited* by them, and both declare a colour of their own — an\n // inherited value loses to any declaration, however weak.\n 'group flex flex-col items-center justify-center gap-2 rounded-md border border-dashed border-input bg-background px-6 py-8 text-center',\n // Border and fill are the drag feedback, so they carry the transition\n // — fast, because a zone that lights up after the pointer has already\n // crossed it is answering a question the reader stopped asking.\n 'transition-[color,background-color,border-color,box-shadow] duration-fast ease-out',\n // Focus lives on the clipped input, which is 1px and can show a reader\n // nothing. The zone wears the ring on its behalf, the same\n // focus-within arrangement TextField uses for its own inner input.\n 'focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-ring',\n !field.invalid && 'focus-within:shadow-halo',\n // The dash going solid is what keeps the drag state off colour alone.\n 'data-[dragging]:border-solid data-[dragging]:border-primary data-[dragging]:bg-primary-muted',\n // Drained, not dimmed. The zone is a large blank region whose whole\n // purpose is the two lines of text in the middle of it, and\n // `opacity-50` took the headline to 3.06:1 and the hint below it to\n // 2.05:1 — the reader least able to guess what a drop zone wants is\n // the one it stopped telling. The fill falls to the neutral well\n // instead, which is where every other unavailable surface in the\n // library goes, and both lines land at 4.67:1 over it. The dash stays,\n // because it is what marks this out as a drop target even while\n // nothing may be dropped on it; only its colour slackens, from\n // `input` to the lighter `border`, so the state is told in a weight\n // as well as in two fills rather than in hue alone.\n field.disabled\n ? 'cursor-not-allowed border-border bg-muted'\n : 'cursor-pointer hover:bg-subtle',\n // Last of the rules naming a border colour, and the order is\n // load-bearing: `cn()` resolves one by whichever class it saw last,\n // so a zone both refusing a file and unavailable would lose its\n // destructive rim to the disabled one if this sat above it.\n field.invalid && 'border-destructive focus-within:outline-destructive',\n )\n \"\n @dragenter=\"onDragEnter\"\n @dragleave=\"onDragLeave\"\n @dragover=\"onDragOver\"\n @drop=\"onDrop\"\n >\n <!-- `field.attrs` spreads **after** the fallthrough attrs, and that\n position is the contract (see TextField.vue): the bag has already\n resolved the caller's own id and merged their description with this\n zone's refusal message and the row's hint, and it drops every key\n that resolved to nothing, so it can only add. The `:aria-invalid` and\n `:aria-describedby` bindings that used to sit here went with it — an\n individual attribute written after a `v-bind` wins, so either one\n kept would overwrite the resolved value with the raw prop.\n\n `:id` is the deliberate exception, and not that failure: `inputId` is\n the bag's own id with the generated one beneath it, so it can only\n ever restate what the bag holds or supply the id the `<label for>`\n needs when the bag holds none. -->\n <input\n v-bind=\"{ ...inputAttrs, ...field.attrs }\"\n :id=\"inputId\"\n type=\"file\"\n :accept=\"accept\"\n :multiple=\"multiple\"\n :disabled=\"field.disabled\"\n class=\"sr-only\"\n @change=\"onSelect\"\n />\n <!-- The medallion, as EmptyState draws it: a 20px glyph alone in a large\n blank region has nothing holding it and reads as a stray mark. -->\n <span\n aria-hidden=\"true\"\n class=\"grid h-10 w-10 place-items-center rounded-full border border-border bg-subtle text-muted-foreground\"\n >\n <CloudUpload class=\"h-5 w-5\" />\n </span>\n <!-- The disabled colour is declared here rather than inherited from the\n zone, for the reason the `group` on it records: this span sets\n `text-foreground` itself, and an inherited value never beats a\n declared one. The hint below needs no such rule — it is already on\n the muted colour, which holds 4.67:1 over the drained fill. -->\n <span class=\"text-sm text-foreground group-data-[disabled]:text-muted-foreground\">{{\n zoneLabel\n }}</span>\n <span v-if=\"zoneHint\" class=\"text-small text-muted-foreground\">{{ zoneHint }}</span>\n </label>\n\n <!-- The region is in the DOM from the first render, empty. A live region\n mounted at the same moment as its text is a region assistive tech was\n not yet watching, so the first refusal — the one that matters most —\n is the one it announces least reliably. -->\n <div aria-live=\"polite\" aria-atomic=\"true\">\n <p\n v-if=\"message.length > 0\"\n :id=\"messageId\"\n class=\"mt-2 flex animate-fade-rise items-start gap-2 text-small text-destructive-text\"\n >\n <TriangleAlert class=\"mt-0.5 h-4 w-4 shrink-0\" aria-hidden=\"true\" />\n <span>{{ message }}</span>\n </p>\n </div>\n\n <ul v-if=\"files.length > 0\" class=\"mt-3 flex flex-col gap-1.5\">\n <li\n v-for=\"(file, index) in files\"\n :key=\"rowId(file)\"\n class=\"flex animate-fade-rise items-center gap-2 rounded-md border border-border bg-card px-3 py-2\"\n :style=\"{ animationDelay: listStaggerDelay(index) }\"\n >\n <FileIcon class=\"h-4 w-4 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />\n <span class=\"min-w-0 flex-1 truncate text-sm text-foreground\">{{ file.name }}</span>\n <span class=\"shrink-0 tabular text-small text-muted-foreground\">\n {{ text.size({ bytes: file.size }) }}\n </span>\n <!-- Named with the file it removes. Seven buttons all called \"Remove\"\n are seven identical announcements and one guess about which row a\n reader is on. -->\n <!-- Drained, not dimmed: `opacity-50` faded the glyph inside its own\n row card, compositing it below contrast — the failure Button\n records for its dim. The glyph-only control takes the neutral\n well, and the native attribute carries unavailability to AT. -->\n <button\n type=\"button\"\n :aria-label=\"text.remove({ file })\"\n :disabled=\"field.disabled\"\n class=\"inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-sm text-muted-foreground transition-colors duration-fast ease-out hover:bg-subtle hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo disabled:cursor-not-allowed disabled:bg-muted disabled:shadow-none\"\n @click=\"remove(index)\"\n >\n <X class=\"h-4 w-4\" />\n </button>\n </li>\n </ul>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileUpload.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../packages/primitives/file-upload/src/FileUpload.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { FileUploadLabels, FileUploadRejection } from \"@ecoma-io/loom-labels\";\n\nconst BYTE_UNITS = [\"B\", \"KB\", \"MB\", \"GB\"] as const;\n\n/**\n * A byte count as a person reads it.\n *\n * Binary steps with the short decimal names, which is what every operating\n * system file dialog beside this control shows — a reader comparing \"1.4 MB\"\n * here against \"1.4 MB\" in their own file browser should see the same number,\n * and the pedantically-correct \"1.5 MB\" (or \"1.4 MiB\") only reads as a bug.\n * One decimal below ten and none above it, so the size column stays the same\n * width down the list.\n *\n * Deliberately not exported: it is a formatter this control needs, not a\n * public utility, and the moment a host imports it from here the wording of a\n * file size becomes part of this component's API.\n */\nfunction formatBytes(bytes: number): string {\n let value = Math.max(bytes, 0);\n let step = 0;\n while (value >= 1024 && step < BYTE_UNITS.length - 1) {\n value /= 1024;\n step += 1;\n }\n const rounded = step > 0 && value < 10 ? Math.round(value * 10) / 10 : Math.round(value);\n return `${String(rounded)} ${BYTE_UNITS[step] ?? \"B\"}`;\n}\n\n/**\n * Every refusal names the file, because the reader is looking at a list of\n * several and \"that file is too large\" identifies none of them.\n */\nfunction describeRejection(rejection: FileUploadRejection, limit: string): string {\n const name = rejection.file.name;\n switch (rejection.reason) {\n case \"too-large\":\n return `${name} is larger than ${limit}.`;\n case \"type\":\n return `${name} is not an accepted file type.`;\n case \"duplicate\":\n return `${name} has already been chosen.`;\n case \"too-many\":\n return `${name} was not added — only one file can be chosen.`;\n }\n}\n\n/**\n * Loom's English, co-located with the component so it tree-shakes with it, and\n * exported so a host can build a partial vocabulary against the real thing.\n */\nexport const FILE_UPLOAD_LABELS: FileUploadLabels = {\n zone: ({ multiple }) =>\n multiple ? \"Choose files or drag them here\" : \"Choose a file or drag it here\",\n hint: ({ maxSize }) => `Up to ${formatBytes(maxSize)}`,\n size: ({ bytes }) => formatBytes(bytes),\n remove: ({ file }) => `Remove ${file.name}`,\n rejected: ({ rejections, maxSize }) => {\n const limit = maxSize === undefined ? \"the size limit\" : formatBytes(maxSize);\n return rejections.map((rejection) => describeRejection(rejection, limit)).join(\" \");\n },\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref, useId, useTemplateRef } from \"vue\";\nimport { CloudUpload, File as FileIcon, TriangleAlert, X } from \"@lucide/vue\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { listStaggerDelay } from \"@ecoma-io/loom-core\";\nimport { useSplitAttrs } from \"@ecoma-io/loom-core\";\nimport { useAncestorDisabled } from \"@ecoma-io/loom-labels\";\nimport { useFieldControl } from \"@ecoma-io/loom-labels\";\nimport { useLabels, type LabelOverrides } from \"@ecoma-io/loom-labels\";\n\n/**\n * FileUpload — choosing files, and nothing else. A drop zone that is also a\n * real file dialog, plus the list of what has been chosen so far, with each\n * row removable.\n *\n * **It chooses; it does not upload.** There is no progress bar here and no\n * request: the host reads `modelValue`, sends it wherever it goes, and renders\n * `Progress` (or `Spinner`, when there is no percentage) for that half. Two\n * controls rather than one, because the upload's states — retrying, partial,\n * failed on the server — belong to whatever is doing the uploading, and a\n * control that owned both would have to guess at all of them.\n *\n * **Drag and drop is a shortcut, never the path.** The zone is a `<label>`\n * wrapped around a real `<input type=\"file\">`, visually hidden by the clip\n * technique rather than by `display: none` or `hidden` — both of which take\n * the input out of the tab order and leave a control only a pointer can reach.\n * Tab lands on the input, Space or Enter opens the system file dialog, and the\n * zone draws the focus ring on its behalf because a 1px input cannot show one.\n * A `div` with a click handler in place of that input is the standard defect\n * in this control, and it is invisible to everyone testing with a mouse.\n *\n * Files arriving while `multiple` is set are appended to the list rather than\n * replacing it: a reader who drops two files and then a third means three, and\n * the native input's replace-everything behaviour is the surprise. Without\n * `multiple` the newest choice replaces the old one, exactly as the input does.\n *\n * Inside a [Field](../Field/Field.vue) it wires itself through\n * `useFieldControl()`: the row's id lands on the input (and on the `<label>`'s\n * `for`, so the zone keeps activating it), and the row's `name`, `required`,\n * `invalid` and the id of its hint or error line arrive with it. The row's\n * description is **merged** with this control's own refusal message rather than\n * replacing it — a file turned away for being too large has to keep saying so.\n *\n * There is no `readonly`, and a row's is ignored rather than approximated.\n * `readonly` is inert on `<input type=\"file\">` in every browser, for the reason\n * it is inert on a checkbox: there is no text to protect, only a dialog to\n * open. A zone that may be read but not added to is a disabled zone above a\n * list — and the list, which is where the value actually is, stays readable\n * either way.\n */\nconst props = withDefaults(\n defineProps<{\n /** The chosen files. Leave it unbound to let the control keep its own list. */\n modelValue?: File[] | undefined;\n /** What the file dialog offers and what a drop is checked against — the native `accept` syntax: `.csv`, `image/png`, `image/*`, comma-separated. */\n accept?: string;\n /** Allows more than one file, and appends each new choice to the list instead of replacing it. */\n multiple?: boolean;\n /** Largest file accepted, in bytes. A file over it is refused and named in the message. */\n maxSize?: number;\n /** Unavailable: dims the zone, refuses the dialog, the drop and every remove button. Unset defers to a wrapping Field. */\n disabled?: boolean | undefined;\n /** Error state: paints the destructive border and ring, and sets `aria-invalid` on the input. Unset defers to a wrapping Field's `error`. */\n invalid?: boolean | undefined;\n /** The zone's own line of copy, which is also the input's accessible name. Defaults to `labels.zone`, whose wording matches `multiple`. */\n label?: string;\n /** The smaller line under it. Defaults to `labels.hint` against the `maxSize` limit, when there is one. */\n hint?: string;\n /**\n * Everything this control says that is not a file name, as any subset of\n * `FileUploadLabels` — the rest stay as the host's `provideLoomLabels`\n * vocabulary left them, and then as Loom's English.\n *\n * This is the per-instance correction, not the place to localise an\n * application. `label` and `hint` are the shorter way to reach the two\n * keys of the same name for one zone; this is what reaches the refusal\n * message, the remove buttons and the size column.\n */\n labels?: LabelOverrides<FileUploadLabels>;\n }>(),\n {\n // Not `[]`. An empty array is a concrete value, so it would say \"the host\n // owns this list\" — and a host that binds nothing would then watch every\n // file it chose vanish on the next render. `undefined` is what leaves the\n // control managing its own, the same distinction `optional()` exists to\n // preserve for the Reka-backed primitives.\n modelValue: undefined,\n multiple: false,\n // Not `false`, for either. `false` is a caller saying \"this zone is fine /\n // enabled even though its row is not\"; absent is a caller saying nothing,\n // and only `undefined` survives to mean that past Vue's\n // absent-Boolean-casts-to-false rule — see TextField.vue, which carries the\n // full reasoning.\n disabled: undefined,\n invalid: undefined,\n },\n);\n\nconst emit = defineEmits<{\n /** The full list after the change — files added, or one removed. Never a partial list. */\n \"update:modelValue\": [files: File[]];\n /** Every file refused by this one interaction, each with the rule that refused it. Fires once per interaction, not once per file. */\n reject: [rejections: FileUploadRejection[]];\n}>();\n\n// `text`, not `labels`: the prop of that name is one of the three sources this\n// resolves, and a template reading the raw prop would be reading the overrides\n// rather than the answer.\nconst text = useLabels(\"fileUpload\", FILE_UPLOAD_LABELS, () => props.labels);\n\n// `class` sizes the whole control, so it lands on the root; everything else a\n// caller passes — `name`, `id`, `data-testid`, `aria-describedby` — describes\n// the real `<input type=\"file\">` and lands there. Splitting them is the only\n// way to route both correctly: the root is not a form control and the input is\n// not the box a caller lays out.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: inputAttrs } = useSplitAttrs();\n\n// The label's `for` needs the input's id, and a caller passing their own id —\n// or a Field row publishing one — must not end up with a label pointing at\n// nothing. `inputId` is resolved from `field` at the foot of this block.\nconst generatedId = useId();\nconst messageId = useId();\n\nconst ownFiles = ref<File[]>([]);\nconst files = computed(() => props.modelValue ?? ownFiles.value);\n\nconst rejections = ref<FileUploadRejection[]>([]);\n\n/**\n * A stable key per file, held against the File object itself.\n *\n * Keying the rows by index instead re-keys every row after the one removed, so\n * removing the first of five replays the entrance animation on the other four\n * — the list appears to reload because one row left it. A WeakMap keys by\n * identity, holds nothing alive, and survives the list being reordered.\n */\nconst rowIds = new WeakMap<File, number>();\nlet nextRowId = 0;\nfunction rowId(file: File): number {\n let id = rowIds.get(file);\n if (id === undefined) {\n id = nextRowId++;\n rowIds.set(file, id);\n }\n return id;\n}\n\n/** Name, size and mtime — what the file system itself calls the same file. */\nfunction signature(file: File): string {\n return `${file.name}:${String(file.size)}:${String(file.lastModified)}`;\n}\n\n/**\n * The same test the native input applies to `accept`, applied again to a drop\n * — the browser enforces it in the file dialog and not at all on a drag, so a\n * zone that only sets the attribute accepts anything dropped on it.\n *\n * `file.type` is the browser's guess from the extension and it is empty for\n * anything it does not recognise, which is why an `accept` written as MIME\n * types alone turns away files it meant to take. Naming both — `.csv,text/csv`\n * — is the form that works, and it is what the documentation shows.\n */\nfunction accepts(file: File): boolean {\n const accept = props.accept?.trim();\n if (accept === undefined || accept.length === 0) return true;\n const name = file.name.toLowerCase();\n const type = file.type.toLowerCase();\n return accept.split(\",\").some((raw) => {\n const pattern = raw.trim().toLowerCase();\n if (pattern.length === 0) return false;\n if (pattern.startsWith(\".\")) return name.endsWith(pattern);\n if (pattern.endsWith(\"/*\")) return type.startsWith(pattern.slice(0, -1));\n return type === pattern;\n });\n}\n\nfunction commit(next: File[]): void {\n if (props.modelValue === undefined) ownFiles.value = next;\n emit(\"update:modelValue\", next);\n}\n\n/** Runs the offered files past every rule, keeping what passes and reporting the rest. */\nfunction add(incoming: File[]): void {\n if (field.disabled) return;\n\n const current = files.value;\n const kept = props.multiple ? [...current] : [];\n const seen = new Set(kept.map(signature));\n const refused: FileUploadRejection[] = [];\n const limit = props.maxSize;\n\n for (const file of incoming) {\n if (!props.multiple && kept.length > 0) {\n refused.push({ file, reason: \"too-many\" });\n } else if (limit !== undefined && file.size > limit) {\n refused.push({ file, reason: \"too-large\" });\n } else if (!accepts(file)) {\n refused.push({ file, reason: \"type\" });\n } else if (seen.has(signature(file))) {\n refused.push({ file, reason: \"duplicate\" });\n } else {\n seen.add(signature(file));\n kept.push(file);\n }\n }\n\n rejections.value = refused;\n if (refused.length > 0) emit(\"reject\", refused);\n\n const unchanged = kept.length === current.length && kept.every((file, i) => file === current[i]);\n if (!unchanged) commit(kept);\n}\n\nfunction remove(index: number): void {\n if (field.disabled) return;\n // The message named files from the last selection. Once the reader edits the\n // list themselves it no longer describes anything on screen, and an error\n // sitting under a list somebody is actively fixing reads as an error about\n // that list.\n rejections.value = [];\n commit(files.value.filter((_, i) => i !== index));\n}\n\nfunction onSelect(event: Event): void {\n const input = event.target as HTMLInputElement;\n add(Array.from(input.files ?? []));\n // Cleared so choosing the same file a second time still fires `change`. The\n // input compares the new selection against its own value and stays silent\n // when they match — which, after a file has been removed from the list, is a\n // control that refuses to take back the file the reader just took out.\n input.value = \"\";\n}\n\n/**\n * Enters minus leaves, rather than a boolean.\n *\n * `dragleave` fires on the zone every time the pointer crosses onto one of its\n * own children, so an enter/leave pair drops the highlight and picks it up\n * again as the reader drags across the icon and the copy — the zone flickers\n * under the cursor at the exact moment it is meant to be saying \"let go here\".\n * A child's `dragenter` always lands before the parent's `dragleave`, so the\n * count never reaches zero until the pointer has genuinely left. `relatedTarget`\n * answers the same question in one line, but it is not reliably populated for a\n * drag that began outside the document — which is every drag this zone sees.\n */\nconst dragDepth = ref(0);\nconst dragging = computed(() => dragDepth.value > 0 && !field.disabled);\n\nfunction onDragEnter(): void {\n dragDepth.value += 1;\n}\n\nfunction onDragLeave(): void {\n dragDepth.value = Math.max(dragDepth.value - 1, 0);\n}\n\nfunction onDragOver(event: DragEvent): void {\n // Without this the browser keeps its default handling, which for a file is\n // \"navigate to it\" — the drop never reaches the zone and the page is gone.\n // Setting dropEffect is what makes the cursor say copy rather than move.\n event.preventDefault();\n if (event.dataTransfer) event.dataTransfer.dropEffect = field.disabled ? \"none\" : \"copy\";\n}\n\nfunction onDrop(event: DragEvent): void {\n event.preventDefault();\n // Reset rather than decrement: the drop consumes the drag, and no matching\n // `dragleave` follows it.\n dragDepth.value = 0;\n add(Array.from(event.dataTransfer?.files ?? []));\n}\n\n// Nothing here listens on `window` or `document`. A page-wide drag handler\n// would be the usual way to stop a file dropped *beside* the zone from\n// navigating the browser away, but a library primitive that installs one\n// silently governs every other drop target on the host's page. That decision\n// is the host's, so the listeners a component cannot tear down are the ones it\n// never registers.\n\n// The two content props sit *above* the resolved label rather than replacing\n// it: `label` is the wording for one zone — \"Drop last month's export here\" —\n// and the label is what every other zone says. Read through `text.` here and\n// not resolved above, so a language switch after mount repaints the copy.\nconst zoneLabel = computed(() => props.label ?? text.value.zone({ multiple: props.multiple }));\n\nconst zoneHint = computed(() => {\n if (props.hint !== undefined) return props.hint;\n // The limit is handed over as a byte count, never as `formatBytes` output: a\n // host that writes `1,5 Mo` or Eastern Arabic digits cannot get there from a\n // string this component already decided the shape of.\n return props.maxSize === undefined ? undefined : text.value.hint({ maxSize: props.maxSize });\n});\n\n// One call over the whole list rather than one per refusal joined with a\n// space. The joiner was the fragment: which character separates two sentences\n// is a property of the script, and a language that would rather count the\n// refused files than list them has no way to say so from a per-file message.\nconst message = computed(() =>\n rejections.value.length === 0\n ? \"\"\n : text.value.rejected({ rejections: rejections.value, maxSize: props.maxSize }),\n);\n\n/**\n * The drop is the reason this control cannot be left to the platform.\n *\n * `<fieldset disabled>` makes the nested `<input type=\"file\">` inert, which\n * closes the click and the keyboard, and it makes each file's remove button\n * inert too. It does nothing at all to the `drop` handler, because that sits on\n * a `<label>` — not a form control, and never disabled by a fieldset. `add()`\n * bails on `field.disabled`, which is exactly the value a disabled fieldset\n * does not reach, so a zone inside a disabled group accepted a dragged file\n * while refusing every other way in.\n *\n * Read off the DOM rather than taken from the Field context, which publishes no\n * `disabled` on purpose — see `../../lib/ancestor-disabled.ts`.\n */\nconst root = useTemplateRef<HTMLElement>(\"root\");\nconst groupDisabled = useAncestorDisabled(() => root.value);\n\n// The Field wiring sits here, below `message`, because it reads it: this is the\n// one control in the family that already had something of its own to say about\n// itself, so its `describedBy` is a *merge* and not a hand-over. Its refusal\n// message reads first — a file turned away for being too large is the most\n// specific thing there is to say — then whatever the caller pointed at, then\n// the row's hint or error, which `useFieldControl` appends. Replacing rather\n// than merging at either end is how a rejection stops being announced.\n//\n// The condition is `message` itself, not `rejections`, so the id can never\n// point at a `<p>` the template has not rendered.\n//\n// `name` and `required` are absent from the object because this component has\n// no prop for either: the row's answer stands unopposed, and its `name` reaches\n// the real `<input type=\"file\">`, which is what a `<form>` posts. `readonly` is\n// absent for the reason the docblock gives.\nconst field = useFieldControl(() => ({\n id: attrs.id as string | undefined,\n describedBy: [message.value.length > 0 ? messageId : undefined, attrs[\"aria-describedby\"]]\n .filter((id): id is string => typeof id === \"string\" && id.length > 0)\n .join(\" \"),\n // The fieldset beats the prop in both directions, exactly as it does for the\n // `<input type=\"file\">` inside this very control.\n disabled: groupDisabled.value ? true : props.disabled,\n invalid: props.invalid,\n}));\n\n// `field.id` is the caller's own id, then the row's; the generated one is the\n// floor beneath both, because the `<label for>` and the input have to agree on\n// an id whether or not anybody supplied one.\nconst inputId = computed(() => field.id ?? generatedId);\n</script>\n\n<template>\n <div ref=\"root\" :class=\"cn('flex w-full flex-col', attrs.class as string)\">\n <!-- The drag handlers sit on a <label>, which the rule reads as a static\n element — and it is usually right to: a box with a drop handler and\n nothing else is a control no keyboard can reach. Here the keyboard\n path is the real <input type=\"file\"> nested inside, which the label\n both names and activates, so the drop adds a pointer shortcut to a\n control that already works without one. -->\n <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->\n <label\n :for=\"inputId\"\n :data-dragging=\"dragging || undefined\"\n :data-invalid=\"field.invalid || undefined\"\n :data-disabled=\"field.disabled || undefined\"\n :class=\"\n cn(\n // `group` so the two lines of copy below can name their own disabled\n // colour off this element's state. A colour set here would only be\n // *inherited* by them, and both declare a colour of their own — an\n // inherited value loses to any declaration, however weak.\n 'group flex flex-col items-center justify-center gap-2 rounded-md border border-dashed border-input bg-background px-6 py-8 text-center',\n // Border and fill are the drag feedback, so they carry the transition\n // — fast, because a zone that lights up after the pointer has already\n // crossed it is answering a question the reader stopped asking.\n 'transition-[color,background-color,border-color,box-shadow] duration-fast ease-out',\n // Focus lives on the clipped input, which is 1px and can show a reader\n // nothing. The zone wears the ring on its behalf, the same\n // focus-within arrangement TextField uses for its own inner input.\n 'focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-ring',\n !field.invalid && 'focus-within:shadow-halo',\n // The dash going solid is what keeps the drag state off colour alone.\n 'data-[dragging]:border-solid data-[dragging]:border-primary data-[dragging]:bg-primary-muted',\n // Drained, not dimmed. The zone is a large blank region whose whole\n // purpose is the two lines of text in the middle of it, and\n // `opacity-50` took the headline to 3.06:1 and the hint below it to\n // 2.05:1 — the reader least able to guess what a drop zone wants is\n // the one it stopped telling. The fill falls to the neutral well\n // instead, which is where every other unavailable surface in the\n // library goes, and both lines land at 4.67:1 over it. The dash stays,\n // because it is what marks this out as a drop target even while\n // nothing may be dropped on it; only its colour slackens, from\n // `input` to the lighter `border`, so the state is told in a weight\n // as well as in two fills rather than in hue alone.\n field.disabled\n ? 'cursor-not-allowed border-border bg-muted'\n : 'cursor-pointer hover:bg-subtle',\n // Last of the rules naming a border colour, and the order is\n // load-bearing: `cn()` resolves one by whichever class it saw last,\n // so a zone both refusing a file and unavailable would lose its\n // destructive rim to the disabled one if this sat above it.\n field.invalid && 'border-destructive focus-within:outline-destructive',\n )\n \"\n @dragenter=\"onDragEnter\"\n @dragleave=\"onDragLeave\"\n @dragover=\"onDragOver\"\n @drop=\"onDrop\"\n >\n <!-- `field.attrs` spreads **after** the fallthrough attrs, and that\n position is the contract (see TextField.vue): the bag has already\n resolved the caller's own id and merged their description with this\n zone's refusal message and the row's hint, and it drops every key\n that resolved to nothing, so it can only add. The `:aria-invalid` and\n `:aria-describedby` bindings that used to sit here went with it — an\n individual attribute written after a `v-bind` wins, so either one\n kept would overwrite the resolved value with the raw prop.\n\n `:id` is the deliberate exception, and not that failure: `inputId` is\n the bag's own id with the generated one beneath it, so it can only\n ever restate what the bag holds or supply the id the `<label for>`\n needs when the bag holds none. -->\n <input\n v-bind=\"{ ...inputAttrs, ...field.attrs }\"\n :id=\"inputId\"\n type=\"file\"\n :accept=\"accept\"\n :multiple=\"multiple\"\n :disabled=\"field.disabled\"\n class=\"sr-only\"\n @change=\"onSelect\"\n />\n <!-- The medallion, as EmptyState draws it: a 20px glyph alone in a large\n blank region has nothing holding it and reads as a stray mark. -->\n <span\n aria-hidden=\"true\"\n class=\"grid h-10 w-10 place-items-center rounded-full border border-border bg-subtle text-muted-foreground\"\n >\n <CloudUpload class=\"h-5 w-5\" />\n </span>\n <!-- The disabled colour is declared here rather than inherited from the\n zone, for the reason the `group` on it records: this span sets\n `text-foreground` itself, and an inherited value never beats a\n declared one. The hint below needs no such rule — it is already on\n the muted colour, which holds 4.67:1 over the drained fill. -->\n <span class=\"text-sm text-foreground group-data-[disabled]:text-muted-foreground\">{{\n zoneLabel\n }}</span>\n <span v-if=\"zoneHint\" class=\"text-small text-muted-foreground\">{{ zoneHint }}</span>\n </label>\n\n <!-- The region is in the DOM from the first render, empty. A live region\n mounted at the same moment as its text is a region assistive tech was\n not yet watching, so the first refusal — the one that matters most —\n is the one it announces least reliably. -->\n <div aria-live=\"polite\" aria-atomic=\"true\">\n <p\n v-if=\"message.length > 0\"\n :id=\"messageId\"\n class=\"mt-2 flex animate-fade-rise items-start gap-2 text-small text-destructive-text\"\n >\n <TriangleAlert class=\"mt-0.5 h-4 w-4 shrink-0\" aria-hidden=\"true\" />\n <span>{{ message }}</span>\n </p>\n </div>\n\n <ul v-if=\"files.length > 0\" class=\"mt-3 flex flex-col gap-1.5\">\n <li\n v-for=\"(file, index) in files\"\n :key=\"rowId(file)\"\n class=\"flex animate-fade-rise items-center gap-2 rounded-md border border-border bg-card px-3 py-2\"\n :style=\"{ animationDelay: listStaggerDelay(index) }\"\n >\n <FileIcon class=\"h-4 w-4 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />\n <span class=\"min-w-0 flex-1 truncate text-sm text-foreground\">{{ file.name }}</span>\n <span class=\"shrink-0 tabular text-small text-muted-foreground\">\n {{ text.size({ bytes: file.size }) }}\n </span>\n <!-- Named with the file it removes. Seven buttons all called \"Remove\"\n are seven identical announcements and one guess about which row a\n reader is on. -->\n <!-- Drained, not dimmed: `opacity-50` faded the glyph inside its own\n row card, compositing it below contrast — the failure Button\n records for its dim. The glyph-only control takes the neutral\n well, and the native attribute carries unavailability to AT. -->\n <button\n type=\"button\"\n :aria-label=\"text.remove({ file })\"\n :disabled=\"field.disabled\"\n class=\"inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-sm text-muted-foreground transition-colors duration-fast ease-out hover:bg-subtle hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo disabled:cursor-not-allowed disabled:bg-muted disabled:shadow-none\"\n @click=\"remove(index)\"\n >\n <X class=\"h-4 w-4\" />\n </button>\n </li>\n </ul>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,IAAM,aAAa;CAAC;CAAK;CAAM;CAAM;AAAI;;;;;;;;;;;;;;;AAgBzC,SAAS,YAAY,OAAuB;CAC1C,IAAI,QAAQ,KAAK,IAAI,OAAO,CAAC;CAC7B,IAAI,OAAO;CACX,OAAO,SAAS,QAAQ,OAAO,WAAW,SAAS,GAAG;EACpD,SAAS;EACT,QAAQ;CACV;CACA,MAAM,UAAU,OAAO,KAAK,QAAQ,KAAK,KAAK,MAAM,QAAQ,EAAE,IAAI,KAAK,KAAK,MAAM,KAAK;CACvF,OAAO,GAAG,OAAO,OAAO,EAAE,GAAG,WAAW,SAAS;AACnD;;;;;AAMA,SAAS,kBAAkB,WAAgC,OAAuB;CAChF,MAAM,OAAO,UAAU,KAAK;CAC5B,QAAQ,UAAU,QAAlB;EACE,KAAK,aACH,OAAO,GAAG,KAAK,kBAAkB,MAAM;EACzC,KAAK,QACH,OAAO,GAAG,KAAK;EACjB,KAAK,aACH,OAAO,GAAG,KAAK;EACjB,KAAK,YACH,OAAO,GAAG,KAAK;CACnB;AACF;;;;;AAMA,IAAa,qBAAuC;CAClD,OAAO,EAAE,eACP,WAAW,mCAAmC;CAChD,OAAO,EAAE,cAAc,SAAS,YAAY,OAAO;CACnD,OAAO,EAAE,YAAY,YAAY,KAAK;CACtC,SAAS,EAAE,WAAW,UAAU,KAAK;CACrC,WAAW,EAAE,YAAY,cAAc;EACrC,MAAM,QAAQ,YAAY,KAAA,IAAY,mBAAmB,YAAY,OAAO;EAC5E,OAAO,WAAW,KAAK,cAAc,kBAAkB,WAAW,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG;CACpF;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;EAqDA,MAAM,QAAQ;EAgDd,MAAM,OAAO;EAUb,MAAM,OAAO,UAAU,cAAc,0BAA0B,MAAM,MAAM;EAQ3E,MAAM,EAAE,OAAO,MAAM,eAAe,cAAc;EAKlD,MAAM,cAAc,MAAM;EAC1B,MAAM,YAAY,MAAM;EAExB,MAAM,WAAW,IAAY,CAAC,CAAC;EAC/B,MAAM,QAAQ,eAAe,MAAM,cAAc,SAAS,KAAK;EAE/D,MAAM,aAAa,IAA2B,CAAC,CAAC;;;;;;;;;EAUhD,MAAM,yBAAS,IAAI,QAAsB;EACzC,IAAI,YAAY;EAChB,SAAS,MAAM,MAAoB;GACjC,IAAI,KAAK,OAAO,IAAI,IAAI;GACxB,IAAI,OAAO,KAAA,GAAW;IACpB,KAAK;IACL,OAAO,IAAI,MAAM,EAAE;GACrB;GACA,OAAO;EACT;;EAGA,SAAS,UAAU,MAAoB;GACrC,OAAO,GAAG,KAAK,KAAK,GAAG,OAAO,KAAK,IAAI,EAAE,GAAG,OAAO,KAAK,YAAY;EACtE;;;;;;;;;;;EAYA,SAAS,QAAQ,MAAqB;GACpC,MAAM,SAAS,MAAM,QAAQ,KAAK;GAClC,IAAI,WAAW,KAAA,KAAa,OAAO,WAAW,GAAG,OAAO;GACxD,MAAM,OAAO,KAAK,KAAK,YAAY;GACnC,MAAM,OAAO,KAAK,KAAK,YAAY;GACnC,OAAO,OAAO,MAAM,GAAG,CAAC,CAAC,MAAM,QAAQ;IACrC,MAAM,UAAU,IAAI,KAAK,CAAC,CAAC,YAAY;IACvC,IAAI,QAAQ,WAAW,GAAG,OAAO;IACjC,IAAI,QAAQ,WAAW,GAAG,GAAG,OAAO,KAAK,SAAS,OAAO;IACzD,IAAI,QAAQ,SAAS,IAAI,GAAG,OAAO,KAAK,WAAW,QAAQ,MAAM,GAAG,EAAE,CAAC;IACvE,OAAO,SAAS;GAClB,CAAC;EACH;EAEA,SAAS,OAAO,MAAoB;GAClC,IAAI,MAAM,eAAe,KAAA,GAAW,SAAS,QAAQ;GACrD,KAAK,qBAAqB,IAAI;EAChC;;EAGA,SAAS,IAAI,UAAwB;GACnC,IAAI,MAAM,UAAU;GAEpB,MAAM,UAAU,MAAM;GACtB,MAAM,OAAO,MAAM,WAAW,CAAC,GAAG,OAAO,IAAI,CAAC;GAC9C,MAAM,OAAO,IAAI,IAAI,KAAK,IAAI,SAAS,CAAC;GACxC,MAAM,UAAiC,CAAC;GACxC,MAAM,QAAQ,MAAM;GAEpB,KAAK,MAAM,QAAQ,UACjB,IAAI,CAAC,MAAM,YAAY,KAAK,SAAS,GACnC,QAAQ,KAAK;IAAE;IAAM,QAAQ;GAAW,CAAC;QACpC,IAAI,UAAU,KAAA,KAAa,KAAK,OAAO,OAC5C,QAAQ,KAAK;IAAE;IAAM,QAAQ;GAAY,CAAC;QACrC,IAAI,CAAC,QAAQ,IAAI,GACtB,QAAQ,KAAK;IAAE;IAAM,QAAQ;GAAO,CAAC;QAChC,IAAI,KAAK,IAAI,UAAU,IAAI,CAAC,GACjC,QAAQ,KAAK;IAAE;IAAM,QAAQ;GAAY,CAAC;QACrC;IACL,KAAK,IAAI,UAAU,IAAI,CAAC;IACxB,KAAK,KAAK,IAAI;GAChB;GAGF,WAAW,QAAQ;GACnB,IAAI,QAAQ,SAAS,GAAG,KAAK,UAAU,OAAO;GAG9C,IAAI,EADc,KAAK,WAAW,QAAQ,UAAU,KAAK,OAAO,MAAM,MAAM,SAAS,QAAQ,EAAE,IAC/E,OAAO,IAAI;EAC7B;EAEA,SAAS,OAAO,OAAqB;GACnC,IAAI,MAAM,UAAU;GAKpB,WAAW,QAAQ,CAAC;GACpB,OAAO,MAAM,MAAM,QAAQ,GAAG,MAAM,MAAM,KAAK,CAAC;EAClD;EAEA,SAAS,SAAS,OAAoB;GACpC,MAAM,QAAQ,MAAM;GACpB,IAAI,MAAM,KAAK,MAAM,SAAS,CAAC,CAAC,CAAC;GAKjC,MAAM,QAAQ;EAChB;;;;;;;;;;;;;EAcA,MAAM,YAAY,IAAI,CAAC;EACvB,MAAM,WAAW,eAAe,UAAU,QAAQ,KAAK,CAAC,MAAM,QAAQ;EAEtE,SAAS,cAAoB;GAC3B,UAAU,SAAS;EACrB;EAEA,SAAS,cAAoB;GAC3B,UAAU,QAAQ,KAAK,IAAI,UAAU,QAAQ,GAAG,CAAC;EACnD;EAEA,SAAS,WAAW,OAAwB;GAI1C,MAAM,eAAe;GACrB,IAAI,MAAM,cAAc,MAAM,aAAa,aAAa,MAAM,WAAW,SAAS;EACpF;EAEA,SAAS,OAAO,OAAwB;GACtC,MAAM,eAAe;GAGrB,UAAU,QAAQ;GAClB,IAAI,MAAM,KAAK,MAAM,cAAc,SAAS,CAAC,CAAC,CAAC;EACjD;EAaA,MAAM,YAAY,eAAe,MAAM,SAAS,KAAK,MAAM,KAAK,EAAE,UAAU,MAAM,SAAS,CAAC,CAAC;EAE7F,MAAM,WAAW,eAAe;GAC9B,IAAI,MAAM,SAAS,KAAA,GAAW,OAAO,MAAM;GAI3C,OAAO,MAAM,YAAY,KAAA,IAAY,KAAA,IAAY,KAAK,MAAM,KAAK,EAAE,SAAS,MAAM,QAAQ,CAAC;EAC7F,CAAC;EAMD,MAAM,UAAU,eACd,WAAW,MAAM,WAAW,IACxB,KACA,KAAK,MAAM,SAAS;GAAE,YAAY,WAAW;GAAO,SAAS,MAAM;EAAQ,CAAC,CAClF;;;;;;;;;;;;;;;EAgBA,MAAM,OAAO,eAA4B,MAAM;EAC/C,MAAM,gBAAgB,0BAA0B,KAAK,KAAK;EAiB1D,MAAM,QAAQ,uBAAuB;GACnC,IAAI,MAAM;GACV,aAAa,CAAC,QAAQ,MAAM,SAAS,IAAI,YAAY,KAAA,GAAW,MAAM,mBAAmB,CAAA,CACtF,QAAQ,OAAqB,OAAO,OAAO,YAAY,GAAG,SAAS,CAAC,CAAA,CACpE,KAAK,GAAG;GAGX,UAAU,cAAc,QAAQ,OAAO,MAAM;GAC7C,SAAS,MAAM;EACjB,EAAE;EAKF,MAAM,UAAU,eAAe,MAAM,MAAM,WAAW;;GAIpD,OAAA,UAAA,GAAA,mBAgJM,OAAA;IAhJG,SAAA;IAAJ,KAAI;IAAQ,OAAK,eAAE,MAAA,EAAA,CAAE,CAAA,wBAAyB,MAAA,KAAA,CAAK,CAAC,KAAK,CAAA;;IAQ5D,mBAyFQ,SAAA;KAxFL,KAAK,QAAA;KACL,iBAAe,SAAA,SAAY,KAAA;KAC3B,gBAAc,MAAA,KAAA,CAAK,CAAC,WAAW,KAAA;KAC/B,iBAAe,MAAA,KAAA,CAAK,CAAC,YAAY,KAAA;KACjC,OAAK,eAAW,MAAA,EAAA,CAAE,CAAA,0IAAA,sFAAA,kFAAimC,CAAA,MAAA,KAAA,CAAK,CAAC,WAAO,4BAAA,gGAAsiC,MAAA,KAAA,CAAK,CAAC,WAAA,8CAAA,kCAAsa,MAAA,KAAA,CAAK,CAAC,WAAO,qDAAA,CAAA;KAuC/lF,aAAW;KACX,aAAW;KACX,YAAU;KACJ;;KAeP,mBASE,SATF,WASE;MAAA,GARa,MAAA,UAAA;MAAU,GAAK,MAAA,KAAA,CAAK,CAAC;KAAK,GAAA;MACtC,IAAI,QAAA;MACL,MAAK;MACJ,QAAQ,QAAA;MACR,UAAU,QAAA;MACV,UAAU,MAAA,KAAA,CAAK,CAAC;MACjB,OAAM;MACL,UAAQ;;KAIX,mBAKO,QALP,YAKO,CADL,YAA+B,MAAA,WAAA,GAAA,EAAlB,OAAM,UAAS,CAAA,CAAA,CAAA;KAO9B,mBAES,QAFT,YAES,gBADP,UAAA,KAAS,GAAA,CAAA;KAEC,SAAA,SAAZ,UAAA,GAAA,mBAAoF,QAApF,YAAoF,gBAAlB,SAAA,KAAQ,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;;IAO5E,mBASM,OATN,YASM,CAPI,QAAA,MAAQ,SAAM,KADtB,UAAA,GAAA,mBAOI,KAAA;;KALD,IAAI,MAAA,SAAA;KACL,OAAM;IAEN,GAAA,CAAA,YAAoE,MAAA,aAAA,GAAA;KAArD,OAAM;KAA0B,eAAY;IAC3D,CAAA,GAAA,mBAA0B,QAAA,MAAA,gBAAjB,QAAA,KAAO,GAAA,CAAA,CAAA,GAAA,GAAA,UAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA;IAIV,MAAA,MAAM,SAAM,KAAtB,UAAA,GAAA,mBA6BK,MA7BL,YA6BK,EA5BH,UAAA,IAAA,GAAA,mBA2BK,UAAA,MAAA,WA1BqB,MAAA,QAAhB,MAAM,UAAK;KADrB,OAAA,UAAA,GAAA,mBA2BK,MAAA;MAzBF,KAAK,MAAM,IAAI;MAChB,OAAM;MACL,OAAK,eAAA,EAAA,gBAAoB,MAAA,gBAAA,CAAgB,CAAC,KAAK,EAAA,CAAA;;MAEhD,YAA8E,MAAA,IAAA,GAAA;OAApE,OAAM;OAAyC,eAAY;;MACrE,mBAAoF,QAApF,YAAoF,gBAAnB,KAAK,IAAI,GAAA,CAAA;MAC1E,mBAEO,QAFP,aAEO,gBADF,MAAA,IAAA,CAAI,CAAC,KAAI,EAAA,OAAU,KAAK,KAAI,CAAA,CAAA,GAAA,CAAA;MASjC,mBAQS,UAAA;OAPP,MAAK;OACJ,cAAY,MAAA,IAAA,CAAI,CAAC,OAAM,EAAG,KAAI,CAAA;OAC9B,UAAU,MAAA,KAAA,CAAK,CAAC;OACjB,OAAM;OACL,UAAK,WAAE,OAAO,KAAK;MAEpB,GAAA,CAAA,YAAqB,MAAA,CAAA,GAAA,EAAlB,OAAM,UAAS,CAAA,CAAA,GAAA,GAAA,WAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HoverCard.js","names":[],"sources":["../../../../packages/primitives/hover-card/src/HoverCard.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Which edge of the trigger the card prefers, before collision flipping. The\n * members mirror Reka's own `Side`, and the template binding is what enforces\n * that: a member Reka does not accept stops `:side=\"side\"` type-checking.\n * Declared here rather than aliased so the generated props table prints the\n * four values instead of a name that tells the reader nothing.\n */\nexport type HoverCardSide = \"top\" | \"right\" | \"bottom\" | \"left\";\n\n/**\n * How the card aligns against the trigger along the cross-axis, before\n * collision flipping. Same rationale as `HoverCardSide`.\n */\nexport type HoverCardAlign = \"start\" | \"center\" | \"end\";\n</script>\n\n<script setup lang=\"ts\">\nimport {\n HoverCardRoot,\n HoverCardTrigger,\n HoverCardPortal,\n HoverCardContent,\n HoverCardArrow,\n} from \"reka-ui\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { optional } from \"@ecoma-io/loom-core\";\n\n/**\n * HoverCard — a supplementary preview surface on hover, for content the user\n * reads rather than operates.\n *\n * The pointer can travel from the trigger into the card without closing it —\n * the close delay exists for that transit, which is what makes a hover card a\n * complementary surface and a tooltip a non-interactive hint. But that reach\n * is a pointer privilege only. Reka strips `tabindex=\"-1\"` onto every tabbable\n * node inside the content on mount, and the trigger closes the card on blur\n * after `closeDelay` (300ms by default) — so by the time a keyboard user\n * tabbed toward anything inside, the card would already be gone. Interactive\n * content inside a HoverCard is unreachable by keyboard (WCAG 2.1.1), whatever\n * the markup allows.\n *\n * The honest contract: keep the card's content non-interactive — text, an\n * image, a definition — and duplicate anything actionable somewhere reachable.\n * When a preview genuinely needs its own links or buttons, it is not a hover\n * card; it is a `Popover`, whose content takes focus and whose Esc/outside\n * dismissal gives a keyboard user a way in and out.\n *\n * The content is NOT wired as `aria-describedby` — it is a supplementary panel,\n * not an accessible name supplement. A screen reader user who never hovers\n * should still have the trigger's own accessible name, and the card is extra\n * rather than essential.\n */\nwithDefaults(\n defineProps<{\n /** The edge of the trigger to anchor against, before collision flipping. */\n side?: HoverCardSide;\n /** Gap in pixels between the trigger and the card. */\n sideOffset?: number;\n /** Alignment against the trigger along the cross-axis, before collision flipping. */\n align?: HoverCardAlign;\n /** Alignment offset in pixels from the chosen alignment position. */\n alignOffset?: number;\n /** Milliseconds of hover before the card appears. */\n openDelay?: number;\n /** Milliseconds before the card disappears after the pointer leaves both trigger and content. */\n closeDelay?: number;\n /** Drive the card from the host with `v-model:open`. Omit for hover alone. */\n open?: boolean | undefined;\n }>(),\n // `open: undefined` is load-bearing, not a redundant default — it is what\n // keeps the uncontrolled third state reachable past Vue's absent-Boolean\n // casting. `optional()` in the template is the other half; its docblock\n // carries the reasoning for both.\n {\n side: \"bottom\",\n sideOffset: 6,\n align: \"start\",\n alignOffset: 0,\n openDelay: 300,\n closeDelay: 300,\n open: undefined,\n },\n);\n\ndefineEmits<{ \"update:open\": [value: boolean] }>();\n</script>\n\n<template>\n <HoverCardRoot\n :open-delay=\"openDelay\"\n :close-delay=\"closeDelay\"\n v-bind=\"optional({ open })\"\n @update:open=\"$emit('update:open', $event)\"\n >\n <!-- @slot The element that opens the card on hover. Rendered `as-child`, so\n the caller's own element *is* the trigger and keeps its own accessible\n name. -->\n <HoverCardTrigger as-child>\n <slot name=\"trigger\" />\n </HoverCardTrigger>\n\n <HoverCardPortal>\n <HoverCardContent\n :side=\"side\"\n :side-offset=\"sideOffset\"\n :align=\"align\"\n :align-offset=\"alignOffset\"\n :class=\"\n cn(\n 'z-overlay w-64 rounded-md border border-border bg-popover p-4 text-popover-foreground shadow-md outline-none',\n // Both states scoped, never unconditional. Reka's Presence\n // keeps closed content mounted until an animationend arrives, and\n // a mount-only animation never fires a second one — so an\n // unconditional animation class leaves a stray card in the page.\n // Scoped, the closed element computes `animation-name: none` and\n // Presence unmounts it at once; the paired exit is precisely what\n // Presence is waiting to hold it for.\n 'data-[state=open]:animate-scale-in data-[state=closed]:animate-scale-out',\n )\n \"\n style=\"transform-origin: var(--reka-popper-transform-origin)\"\n >\n <!-- @slot The card content. Pointer-reachable, but keep it\n non-interactive — see the component docblock for why keyboard\n users cannot reach anything focusable in here. -->\n <slot />\n <HoverCardArrow class=\"fill-popover\" :width=\"10\" :height=\"5\" />\n </HoverCardContent>\n </HoverCardPortal>\n </HoverCardRoot>\n</template>\n"],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HoverCard.vue_vue_type_script_setup_true_lang.js","names":["$emit"],"sources":["../../../../packages/primitives/hover-card/src/HoverCard.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Which edge of the trigger the card prefers, before collision flipping. The\n * members mirror Reka's own `Side`, and the template binding is what enforces\n * that: a member Reka does not accept stops `:side=\"side\"` type-checking.\n * Declared here rather than aliased so the generated props table prints the\n * four values instead of a name that tells the reader nothing.\n */\nexport type HoverCardSide = \"top\" | \"right\" | \"bottom\" | \"left\";\n\n/**\n * How the card aligns against the trigger along the cross-axis, before\n * collision flipping. Same rationale as `HoverCardSide`.\n */\nexport type HoverCardAlign = \"start\" | \"center\" | \"end\";\n</script>\n\n<script setup lang=\"ts\">\nimport {\n HoverCardRoot,\n HoverCardTrigger,\n HoverCardPortal,\n HoverCardContent,\n HoverCardArrow,\n} from \"reka-ui\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { optional } from \"@ecoma-io/loom-core\";\n\n/**\n * HoverCard — a supplementary preview surface on hover, for content the user\n * reads rather than operates.\n *\n * The pointer can travel from the trigger into the card without closing it —\n * the close delay exists for that transit, which is what makes a hover card a\n * complementary surface and a tooltip a non-interactive hint. But that reach\n * is a pointer privilege only. Reka strips `tabindex=\"-1\"` onto every tabbable\n * node inside the content on mount, and the trigger closes the card on blur\n * after `closeDelay` (300ms by default) — so by the time a keyboard user\n * tabbed toward anything inside, the card would already be gone. Interactive\n * content inside a HoverCard is unreachable by keyboard (WCAG 2.1.1), whatever\n * the markup allows.\n *\n * The honest contract: keep the card's content non-interactive — text, an\n * image, a definition — and duplicate anything actionable somewhere reachable.\n * When a preview genuinely needs its own links or buttons, it is not a hover\n * card; it is a `Popover`, whose content takes focus and whose Esc/outside\n * dismissal gives a keyboard user a way in and out.\n *\n * The content is NOT wired as `aria-describedby` — it is a supplementary panel,\n * not an accessible name supplement. A screen reader user who never hovers\n * should still have the trigger's own accessible name, and the card is extra\n * rather than essential.\n */\nwithDefaults(\n defineProps<{\n /** The edge of the trigger to anchor against, before collision flipping. */\n side?: HoverCardSide;\n /** Gap in pixels between the trigger and the card. */\n sideOffset?: number;\n /** Alignment against the trigger along the cross-axis, before collision flipping. */\n align?: HoverCardAlign;\n /** Alignment offset in pixels from the chosen alignment position. */\n alignOffset?: number;\n /** Milliseconds of hover before the card appears. */\n openDelay?: number;\n /** Milliseconds before the card disappears after the pointer leaves both trigger and content. */\n closeDelay?: number;\n /** Drive the card from the host with `v-model:open`. Omit for hover alone. */\n open?: boolean | undefined;\n }>(),\n // `open: undefined` is load-bearing, not a redundant default — it is what\n // keeps the uncontrolled third state reachable past Vue's absent-Boolean\n // casting. `optional()` in the template is the other half; its docblock\n // carries the reasoning for both.\n {\n side: \"bottom\",\n sideOffset: 6,\n align: \"start\",\n alignOffset: 0,\n openDelay: 300,\n closeDelay: 300,\n open: undefined,\n },\n);\n\ndefineEmits<{ \"update:open\": [value: boolean] }>();\n</script>\n\n<template>\n <HoverCardRoot\n :open-delay=\"openDelay\"\n :close-delay=\"closeDelay\"\n v-bind=\"optional({ open })\"\n @update:open=\"$emit('update:open', $event)\"\n >\n <!-- @slot The element that opens the card on hover. Rendered `as-child`, so\n the caller's own element *is* the trigger and keeps its own accessible\n name. -->\n <HoverCardTrigger as-child>\n <slot name=\"trigger\" />\n </HoverCardTrigger>\n\n <HoverCardPortal>\n <HoverCardContent\n :side=\"side\"\n :side-offset=\"sideOffset\"\n :align=\"align\"\n :align-offset=\"alignOffset\"\n :class=\"\n cn(\n 'z-overlay w-64 rounded-md border border-border bg-popover p-4 text-popover-foreground shadow-md outline-none',\n // Both states scoped, never unconditional. Reka's Presence\n // keeps closed content mounted until an animationend arrives, and\n // a mount-only animation never fires a second one — so an\n // unconditional animation class leaves a stray card in the page.\n // Scoped, the closed element computes `animation-name: none` and\n // Presence unmounts it at once; the paired exit is precisely what\n // Presence is waiting to hold it for.\n 'data-[state=open]:animate-scale-in data-[state=closed]:animate-scale-out',\n )\n \"\n style=\"transform-origin: var(--reka-popper-transform-origin)\"\n >\n <!-- @slot The card content. Pointer-reachable, but keep it\n non-interactive — see the component docblock for why keyboard\n users cannot reach anything focusable in here. -->\n <slot />\n <HoverCardArrow class=\"fill-popover\" :width=\"10\" :height=\"5\" />\n </HoverCardContent>\n </HoverCardPortal>\n </HoverCardRoot>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;GAyFE,OAAA,UAAA,GAAA,YAyCgB,MAAA,aAAA,GAzChB,WAyCgB;IAxCb,cAAY,QAAA;IACZ,eAAa,QAAA;GACN,GAAA,MAAA,QAAA,CAAQ,CAAA,EAAA,MAAG,QAAA,KAAI,CAAA,GAAA,EACtB,iBAAW,OAAA,OAAA,OAAA,MAAA,WAAEA,KAAAA,MAAK,eAAgB,MAAM,GAAA,CAAA,GAAA;IAKzC,SAAA,cAEmB,CAFnB,YAEmB,MAAA,gBAAA,GAAA,EAFD,YAAA,GAAQ,GAAA;KACxB,SAAA,cAAuB,CAAvB,WAAuB,KAAA,QAAA,SAAA,CAAA,CAAA;;IAGzB,CAAA,GAAA,YA2BkB,MAAA,eAAA,GAAA,MAAA;KA1BhB,SAAA,cAyBmB,CAzBnB,YAyBmB,MAAA,gBAAA,GAAA;MAxBhB,MAAM,QAAA;MACN,eAAa,QAAA;MACb,OAAO,QAAA;MACP,gBAAc,QAAA;MACd,OAAK,eAAa,MAAA,EAAA,CAAE,CAAA,gHAAA,0EAAA,CAAA;MAarB,OAAA,EAAA,oBAAA,sCAAA;;MAKA,SAAA,cAAQ,CAAR,WAAQ,KAAA,QAAA,SAAA,GACR,YAA+D,MAAA,cAAA,GAAA;OAA/C,OAAM;OAAgB,OAAO;OAAK,QAAQ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IconButton.js","names":[],"sources":["../../../../packages/primitives/icon-button/src/IconButton.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { cva } from \"class-variance-authority\";\n\nexport type IconButtonVariant = \"default\" | \"secondary\" | \"ghost\" | \"destructive\";\n\nexport type IconButtonSize = \"sm\" | \"md\" | \"lg\";\n\n/**\n * An icon-only button is a square, so every size is height-equals-width and has\n * no horizontal padding. The four variants match Button's press language — hover\n * lifts by fill, active presses down, focus blooms the primary ring — but\n * `default` here names what Button calls `primary`, because an icon button is\n * never the screen's primary action and the word would mislead.\n */\nexport const iconButtonVariants = cva(\n [\n \"relative inline-flex items-center justify-center rounded-md select-none\",\n // Button's own transition list, verbatim: transform rides --ease-spring so\n // the press squish springs, while colour and shadow stay on --ease-out.\n // A bare `transition-colors` silently dropped any transform change.\n \"[transition:transform_var(--duration-fast)_var(--ease-spring),background-color_var(--duration-fast)_var(--ease-out),color_var(--duration-fast)_var(--ease-out),box-shadow_var(--duration-fast)_var(--ease-out)]\",\n \"active:scale-press focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo\",\n \"disabled:pointer-events-none\",\n ],\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90 active:bg-primary/80\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 active:bg-secondary/70\",\n ghost: \"hover:bg-subtle text-foreground\",\n destructive:\n \"bg-destructive text-destructive-foreground hover:bg-destructive/90 active:bg-destructive/80\",\n } satisfies Record<IconButtonVariant, string>,\n size: {\n sm: \"h-8 w-8\",\n md: \"h-9 w-9\",\n lg: \"h-10 w-10\",\n } satisfies Record<IconButtonSize, string>,\n },\n defaultVariants: {\n variant: \"default\",\n size: \"md\",\n },\n },\n);\n</script>\n\n<script setup lang=\"ts\">\nimport { cn } from \"@ecoma-io/loom-core\";\n\nwithDefaults(\n defineProps<{\n /** Visual weight, matching Button's press language but without the `primary` name — an icon button is never the action a screen is asking for. */\n variant?: IconButtonVariant;\n /** Square hit area. Every size is 24px or above (WCAG 2.2 SC 2.5.8). */\n size?: IconButtonSize;\n /** The accessible name. An icon-only button without one is a WCAG failure, so this prop is required. */\n label: string;\n /** Unavailable rather than dimmed — drains to the neutral well and blocks pointer events. */\n disabled?: boolean;\n /** The native button type. Defaults to `button`, never an accidental submit. */\n type?: \"button\" | \"submit\" | \"reset\";\n }>(),\n { variant: \"default\", size: \"md\", disabled: false, type: \"button\" },\n);\n</script>\n\n<template>\n <button\n :type=\"type\"\n :class=\"\n cn(\n iconButtonVariants({ variant, size }),\n $attrs.class,\n // Drained, not dimmed — Button's rule, and for the same measured reason:\n // `opacity-50` faded the fill and the glyph together, multiplying away\n // whatever contrast either had. One neutral treatment covers all four\n // variants here exactly as it does on Button — a fill-bearing icon\n // button gives up its hue, `ghost` gains a fill — because an unavailable\n // control has no emphasis left to carry, and the native `disabled`\n // attribute above carries the state to assistive tech regardless.\n // No `border-border` companion: unlike Button's variants none of these\n // paints a border to slacken.\n disabled && 'bg-muted text-muted-foreground shadow-none',\n )\n \"\n :aria-label=\"label\"\n :disabled=\"disabled\"\n >\n <slot />\n </button>\n</template>\n"],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IconButton.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../../packages/primitives/icon-button/src/IconButton.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { cva } from \"class-variance-authority\";\n\nexport type IconButtonVariant = \"default\" | \"secondary\" | \"ghost\" | \"destructive\";\n\nexport type IconButtonSize = \"sm\" | \"md\" | \"lg\";\n\n/**\n * An icon-only button is a square, so every size is height-equals-width and has\n * no horizontal padding. The four variants match Button's press language — hover\n * lifts by fill, active presses down, focus blooms the primary ring — but\n * `default` here names what Button calls `primary`, because an icon button is\n * never the screen's primary action and the word would mislead.\n */\nexport const iconButtonVariants = cva(\n [\n \"relative inline-flex items-center justify-center rounded-md select-none\",\n // Button's own transition list, verbatim: transform rides --ease-spring so\n // the press squish springs, while colour and shadow stay on --ease-out.\n // A bare `transition-colors` silently dropped any transform change.\n \"[transition:transform_var(--duration-fast)_var(--ease-spring),background-color_var(--duration-fast)_var(--ease-out),color_var(--duration-fast)_var(--ease-out),box-shadow_var(--duration-fast)_var(--ease-out)]\",\n \"active:scale-press focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo\",\n \"disabled:pointer-events-none\",\n ],\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90 active:bg-primary/80\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 active:bg-secondary/70\",\n ghost: \"hover:bg-subtle text-foreground\",\n destructive:\n \"bg-destructive text-destructive-foreground hover:bg-destructive/90 active:bg-destructive/80\",\n } satisfies Record<IconButtonVariant, string>,\n size: {\n sm: \"h-8 w-8\",\n md: \"h-9 w-9\",\n lg: \"h-10 w-10\",\n } satisfies Record<IconButtonSize, string>,\n },\n defaultVariants: {\n variant: \"default\",\n size: \"md\",\n },\n },\n);\n</script>\n\n<script setup lang=\"ts\">\nimport { cn } from \"@ecoma-io/loom-core\";\n\nwithDefaults(\n defineProps<{\n /** Visual weight, matching Button's press language but without the `primary` name — an icon button is never the action a screen is asking for. */\n variant?: IconButtonVariant;\n /** Square hit area. Every size is 24px or above (WCAG 2.2 SC 2.5.8). */\n size?: IconButtonSize;\n /** The accessible name. An icon-only button without one is a WCAG failure, so this prop is required. */\n label: string;\n /** Unavailable rather than dimmed — drains to the neutral well and blocks pointer events. */\n disabled?: boolean;\n /** The native button type. Defaults to `button`, never an accidental submit. */\n type?: \"button\" | \"submit\" | \"reset\";\n }>(),\n { variant: \"default\", size: \"md\", disabled: false, type: \"button\" },\n);\n</script>\n\n<template>\n <button\n :type=\"type\"\n :class=\"\n cn(\n iconButtonVariants({ variant, size }),\n $attrs.class,\n // Drained, not dimmed — Button's rule, and for the same measured reason:\n // `opacity-50` faded the fill and the glyph together, multiplying away\n // whatever contrast either had. One neutral treatment covers all four\n // variants here exactly as it does on Button — a fill-bearing icon\n // button gives up its hue, `ghost` gains a fill — because an unavailable\n // control has no emphasis left to carry, and the native `disabled`\n // attribute above carries the state to assistive tech regardless.\n // No `border-border` companion: unlike Button's variants none of these\n // paints a border to slacken.\n disabled && 'bg-muted text-muted-foreground shadow-none',\n )\n \"\n :aria-label=\"label\"\n :disabled=\"disabled\"\n >\n <slot />\n </button>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;AAcA,IAAa,qBAAqB,IAChC;CACE;CAIA;CACA;CACA;AACF,GACA;CACE,UAAU;EACR,SAAS;GACP,SAAS;GACT,WACE;GACF,OAAO;GACP,aACE;EACJ;EACA,MAAM;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;CACF;CACA,iBAAiB;EACf,SAAS;EACT,MAAM;CACR;AACF,CACF;;;;;;;;;;;;;;;GAwBE,OAAA,UAAA,GAAA,mBAsBS,UAAA;IArBN,MAAM,QAAA;IACN,OAAK,eAAS,MAAA,EAAA,CAAE,CAAU,MAAA,kBAAA,CAAkB,CAAA;KAAA,SAAG,QAAA;KAAO,MAAE,QAAA;IAAI,CAAA,GAAaA,KAAAA,OAAO,OAA4qB,QAAA,YAAQ,4CAAA,CAAA;IAgBpwB,cAAY,QAAA;IACZ,UAAU,QAAA;GAEX,GAAA,CAAA,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,IAAA,UAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Indicator.js","names":[],"sources":["../../../../packages/primitives/indicator/src/Indicator.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { IndicatorLabels } from \"@ecoma-io/loom-labels\";\nimport { cva } from \"class-variance-authority\";\n\n/** A presence dot, or a number. */\nexport type IndicatorVariant = \"dot\" | \"count\";\n\n/** The four presence states a dot can report. */\nexport type IndicatorStatus = \"online\" | \"offline\" | \"busy\" | \"away\";\n\n/** Which corner of the marked element the marker straddles. */\nexport type IndicatorPlacement = \"top-right\" | \"top-left\" | \"bottom-right\" | \"bottom-left\";\n\n/**\n * The colour vocabulary, deliberately Badge's own names rather than a second\n * set — `accent` included, and it means here exactly what it means there:\n * a second semantic category distinct from primary, never decoration.\n */\nexport type IndicatorTone =\n \"neutral\" | \"primary\" | \"success\" | \"warning\" | \"info\" | \"destructive\" | \"accent\";\n\n/** The surface the marked element sits on, which the separating ring matches. */\nexport type IndicatorSurface = \"background\" | \"card\" | \"sunken\" | \"popover\";\n\nexport const indicatorVariants = cva(\n // `pointer-events-none` is load-bearing rather than tidy: the marker\n // overhangs the corner of whatever it marks, so without it the top-right\n // few pixels of a bell button stop being clickable.\n \"pointer-events-none absolute z-10 flex items-center justify-center select-none ring-2\",\n {\n variants: {\n variant: {\n // 12px leaves room for the status glyphs below to read as shapes\n // rather than as noise.\n dot: \"h-3 w-3 rounded-full\",\n // `min-w-5` and the padding together are what make one digit a circle\n // and three a pill, with no branch: \"1\" is narrower than the minimum\n // and lands on it, \"99+\" outgrows it and the radius turns the ends.\n count: \"h-5 min-w-5 rounded-full px-1.5 text-micro font-medium tabular\",\n } satisfies Record<IndicatorVariant, string>,\n placement: {\n \"top-right\": \"top-0 right-0 -translate-y-1/2 translate-x-1/2\",\n \"top-left\": \"top-0 left-0 -translate-y-1/2 -translate-x-1/2\",\n \"bottom-right\": \"right-0 bottom-0 translate-x-1/2 translate-y-1/2\",\n \"bottom-left\": \"bottom-0 left-0 -translate-x-1/2 translate-y-1/2\",\n } satisfies Record<IndicatorPlacement, string>,\n // The ring is what separates the marker from the photo, avatar or icon\n // underneath, the way a presence dot is punched out of a portrait. It\n // has to be the colour of what surrounds the pair, which only the caller\n // knows — hence a prop rather than a guess.\n surface: {\n background: \"ring-background\",\n card: \"ring-card\",\n sunken: \"ring-sunken\",\n popover: \"ring-popover\",\n } satisfies Record<IndicatorSurface, string>,\n },\n defaultVariants: { variant: \"dot\", placement: \"top-right\", surface: \"background\" },\n },\n);\n\n/**\n * The fill, keyed by Badge's colour names so a success dot and a success badge\n * are the same green. These are the solid tokens where Badge uses a 12% wash:\n * a wash reads fine across a chip and carries no signal at all across 12px.\n *\n * The paired `text-*` is what the count prints in and what the status glyph is\n * punched out in, so one entry drives both layers.\n */\nexport const indicatorToneVariants = cva(\"\", {\n variants: {\n tone: {\n neutral: \"bg-muted-foreground text-background\",\n primary: \"bg-primary text-primary-foreground\",\n success: \"bg-success text-success-foreground\",\n warning: \"bg-warning text-warning-foreground\",\n info: \"bg-info text-info-foreground\",\n destructive: \"bg-destructive text-destructive-foreground\",\n accent: \"bg-accent text-accent-foreground\",\n } satisfies Record<IndicatorTone, string>,\n },\n defaultVariants: { tone: \"primary\" },\n});\n\n/** Which colour each presence state means, so `status` alone is enough. */\nconst STATUS_TONES = {\n online: \"success\",\n offline: \"neutral\",\n busy: \"destructive\",\n away: \"warning\",\n} satisfies Record<IndicatorStatus, IndicatorTone>;\n\n/**\n\n/**\n * Loom's English, co-located with the component so it tree-shakes with it, and\n * exported so a host can build a partial vocabulary against the real thing.\n */\nexport const INDICATOR_LABELS: IndicatorLabels = {\n online: \"Online\",\n offline: \"Offline\",\n busy: \"Busy\",\n away: \"Away\",\n count: ({ count }) => `${String(count)} unread`,\n attention: \"Needs attention\",\n};\n\n/**\n * The shape layer, and it exists for the sighted reader the `sr-only` string\n * below cannot help. Three of the four states are saturated — green, amber,\n * red — which is the exact triple a red/green deficiency collapses, so `busy`\n * wears a bar and `away` a hole and no two of them differ by hue alone.\n * `offline` needs none: grey against any of the three is a saturation\n * difference, not a hue one.\n */\nconst STATUS_GLYPHS = {\n online: \"\",\n offline: \"\",\n busy: \"h-0.5 w-1.5 rounded-full bg-current\",\n away: \"h-1 w-1 rounded-full bg-current\",\n} satisfies Record<IndicatorStatus, string>;\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, useId } from \"vue\";\nimport { cn, useSplitAttrs } from \"@ecoma-io/loom-core\";\nimport { useLabels, type LabelOverrides } from \"@ecoma-io/loom-labels\";\n\n/**\n * Indicator — the small marker pinned onto the corner of something else: a\n * presence dot on an avatar, an unread count on a bell, a \"needs attention\"\n * dot on a tab. The default slot is the thing being marked, and the marker\n * positions itself over that child's corner.\n *\n * The boundary with Badge is the whole of the decision between them: **Badge\n * sits in the flow beside content; Indicator is pinned onto content.** A count\n * chip in a table cell is a Badge. The same count floating over a bell icon is\n * an Indicator. Reach for Badge whenever the marker would take up room of its\n * own, and for this whenever it would overhang something.\n *\n * What this component is by default is a bare colour, which is the one thing\n * Loom's accessibility bar forbids outright. A green dot says nothing to a\n * reader who cannot see it. So every marker that renders carries a visually\n * hidden string — `label`, or a default derived from `status` or `count` — and\n * a blank `label` falls back to that default rather than replacing it, which\n * is what makes an unnamed indicator unreachable rather than merely\n * discouraged. The shape layer in `STATUS_GLYPHS` covers the sighted reader\n * the hidden string cannot.\n *\n * There is deliberately **no `aria-live` region here**, and the reason is that\n * this component cannot know whether a change is news. An unread counter is\n * usually fed by a poll, so a live region announces every tick over whatever\n * the reader was doing; the same count is commonly pinned in two places at\n * once, so it announces twice; and a polite region speaks on first render in\n * several screen reader and browser pairs, which turns every page load into a\n * recitation of the inbox. The marker is therefore static text a reader\n * reaches on demand, and announcing a *change* stays with the consumer, who\n * knows whether it followed something the reader just did.\n *\n * One consequence to design around: when the marked child is interactive, its\n * accessible name is computed from the child, and this marker's text sits\n * outside it — a bell button announces \"Notifications, button\" on focus and\n * never mentions the three unread. The default slot exposes `labelId` for\n * exactly that: bind it to the control's `aria-describedby` and the count is\n * announced straight after the name, once, without being duplicated into it.\n */\nconst props = withDefaults(\n defineProps<{\n /** A presence dot, or a number in a pill. */\n variant?: IndicatorVariant;\n /** The number the pill prints, when `variant` is `count`. Zero hides the marker unless `showZero` is set. */\n count?: number;\n /** The highest number printed in full; anything above it prints as `<max>+`. The accessible text still carries the real figure. */\n max?: number;\n /** Presence, for a dot: it picks the colour and the shape, and names the dot for a screen reader. Omit it for a plain \"something changed\" dot. */\n status?: IndicatorStatus;\n /** The marker's colour, in Badge's own vocabulary. Defaults to whatever `status` implies, or to `primary` when there is no status. */\n tone?: IndicatorTone;\n /** Which corner of the marked element the marker straddles. */\n placement?: IndicatorPlacement;\n /** What a screen reader announces for the marker. Leave it unset for the derived default — \"Online\", \"3 unread\" — and set it whenever the count is not of unread things. Blank or whitespace falls back to the default rather than clearing it. */\n label?: string;\n /** Render the pill when the count is zero. Off by default, because a count of nothing is not news. */\n showZero?: boolean;\n /** The surface the marked element sits on, so the ring separating the marker from it matches what surrounds them. */\n surface?: IndicatorSurface;\n /**\n * Names for the markers this component derives on its own, as any subset\n * of `IndicatorLabels` — the rest stay as the host's `provideLoomLabels`\n * vocabulary left them, and then as Loom's English.\n *\n * This is the vocabulary, not the instance's name: `label` still beats it\n * and is what one bell counting drafts rather than unread mail reaches for.\n */\n labels?: LabelOverrides<IndicatorLabels>;\n }>(),\n {\n variant: \"dot\",\n count: 0,\n max: 99,\n placement: \"top-right\",\n showZero: false,\n surface: \"background\",\n },\n);\n\n// `text`, not `labels`: the prop of that name is one of the three sources this\n// resolves, and a template reading the raw prop would be reading the overrides\n// rather than the answer.\nconst text = useLabels(\"indicator\", INDICATOR_LABELS, () => props.labels);\n\n// One rendered node, and every fallthrough attribute belongs on it — but\n// `class` still has to go the long way round. A consumer replacing the root's\n// `inline-flex` with `block` cannot win by concatenation, because the winner\n// there is decided by the order of the two rules in the stylesheet rather than\n// by the order of the two names in the attribute; `cn()` is what resolves it.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest } = useSplitAttrs();\n\n// Bound to the hidden label so an interactive child can point its\n// `aria-describedby` at it through the slot prop.\nconst labelId = useId();\n\n/**\n * The count as a whole, non-negative number. A negative count is a defect in\n * the caller's data, and a pill reading \"-1 unread\" reports that defect to the\n * reader rather than to the caller — falling back to \"nothing to report\" is\n * the honest rendering of it.\n */\nconst total = computed(() => Math.max(0, Math.trunc(props.count)));\n\nconst visible = computed(() => props.variant === \"dot\" || total.value > 0 || props.showZero);\n\n/** What the pill prints — the real figure up to `max`, then `<max>+`. */\nconst printed = computed(() =>\n total.value > props.max ? `${String(props.max)}+` : String(total.value),\n);\n\nconst tone = computed<IndicatorTone>(\n () => props.tone ?? (props.status ? STATUS_TONES[props.status] : \"primary\"),\n);\n\nconst glyph = computed(() => (props.status ? STATUS_GLYPHS[props.status] : \"\"));\n\n/**\n * The accessible name, and it is never empty by construction. The count case\n * reports `total` rather than `printed`: clamping at `max` is a decision about\n * how wide the pill is allowed to get, and a reader who cannot see the pill\n * has no reason to inherit it — \"132 unread\" is the fact, \"99+\" is the layout.\n */\nconst name = computed(() => {\n const given = props.label?.trim();\n if (given) return given;\n if (props.variant === \"count\") return text.value.count({ count: total.value });\n // Keyed by the status itself rather than through a lookup table of its own:\n // `IndicatorLabels` names its four presence keys after the four members of\n // `IndicatorStatus`, so a state added to the union with no name for it stops\n // compiling here instead of rendering an unnamed dot.\n return props.status ? text.value[props.status] : text.value.attention;\n});\n</script>\n\n<template>\n <span v-bind=\"rest\" :class=\"cn('relative inline-flex align-middle', attrs.class as string)\">\n <!-- A multi-line `@slot` comment comes back from vue-docgen with no description at all, so this one stays on one line. -->\n <!-- @slot The element being marked. `labelId` is the id of the marker's own hidden text — bind it to an interactive child's `aria-describedby` so the count is announced after that control's name. -->\n <slot :label-id=\"labelId\" />\n\n <!-- Keyed on what is printed rather than on the count, so `animate-scale-in`\n replays when a number a reader can see actually changes and stays put\n when 100 becomes 132 behind the same \"99+\". A dot's key never moves, so\n a dot never animates: presence settles into place on load, it does not\n arrive as news, and it must not pulse. -->\n <span\n v-if=\"visible\"\n :key=\"printed\"\n :data-placement=\"placement\"\n :class=\"\n cn(\n indicatorVariants({ variant, placement, surface }),\n indicatorToneVariants({ tone }),\n variant === 'count' && 'animate-scale-in',\n )\n \"\n >\n <!-- Hidden from assistive tech because the label below carries the real\n figure; left visible the pair would read as \"99+ 132 unread\". -->\n <span v-if=\"variant === 'count'\" aria-hidden=\"true\">{{ printed }}</span>\n <span v-else-if=\"glyph\" :class=\"glyph\" />\n\n <span :id=\"labelId\" class=\"sr-only\">{{ name }}</span>\n </span>\n </span>\n</template>\n"],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Indicator.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../packages/primitives/indicator/src/Indicator.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { IndicatorLabels } from \"@ecoma-io/loom-labels\";\nimport { cva } from \"class-variance-authority\";\n\n/** A presence dot, or a number. */\nexport type IndicatorVariant = \"dot\" | \"count\";\n\n/** The four presence states a dot can report. */\nexport type IndicatorStatus = \"online\" | \"offline\" | \"busy\" | \"away\";\n\n/** Which corner of the marked element the marker straddles. */\nexport type IndicatorPlacement = \"top-right\" | \"top-left\" | \"bottom-right\" | \"bottom-left\";\n\n/**\n * The colour vocabulary, deliberately Badge's own names rather than a second\n * set — `accent` included, and it means here exactly what it means there:\n * a second semantic category distinct from primary, never decoration.\n */\nexport type IndicatorTone =\n \"neutral\" | \"primary\" | \"success\" | \"warning\" | \"info\" | \"destructive\" | \"accent\";\n\n/** The surface the marked element sits on, which the separating ring matches. */\nexport type IndicatorSurface = \"background\" | \"card\" | \"sunken\" | \"popover\";\n\nexport const indicatorVariants = cva(\n // `pointer-events-none` is load-bearing rather than tidy: the marker\n // overhangs the corner of whatever it marks, so without it the top-right\n // few pixels of a bell button stop being clickable.\n \"pointer-events-none absolute z-10 flex items-center justify-center select-none ring-2\",\n {\n variants: {\n variant: {\n // 12px leaves room for the status glyphs below to read as shapes\n // rather than as noise.\n dot: \"h-3 w-3 rounded-full\",\n // `min-w-5` and the padding together are what make one digit a circle\n // and three a pill, with no branch: \"1\" is narrower than the minimum\n // and lands on it, \"99+\" outgrows it and the radius turns the ends.\n count: \"h-5 min-w-5 rounded-full px-1.5 text-micro font-medium tabular\",\n } satisfies Record<IndicatorVariant, string>,\n placement: {\n \"top-right\": \"top-0 right-0 -translate-y-1/2 translate-x-1/2\",\n \"top-left\": \"top-0 left-0 -translate-y-1/2 -translate-x-1/2\",\n \"bottom-right\": \"right-0 bottom-0 translate-x-1/2 translate-y-1/2\",\n \"bottom-left\": \"bottom-0 left-0 -translate-x-1/2 translate-y-1/2\",\n } satisfies Record<IndicatorPlacement, string>,\n // The ring is what separates the marker from the photo, avatar or icon\n // underneath, the way a presence dot is punched out of a portrait. It\n // has to be the colour of what surrounds the pair, which only the caller\n // knows — hence a prop rather than a guess.\n surface: {\n background: \"ring-background\",\n card: \"ring-card\",\n sunken: \"ring-sunken\",\n popover: \"ring-popover\",\n } satisfies Record<IndicatorSurface, string>,\n },\n defaultVariants: { variant: \"dot\", placement: \"top-right\", surface: \"background\" },\n },\n);\n\n/**\n * The fill, keyed by Badge's colour names so a success dot and a success badge\n * are the same green. These are the solid tokens where Badge uses a 12% wash:\n * a wash reads fine across a chip and carries no signal at all across 12px.\n *\n * The paired `text-*` is what the count prints in and what the status glyph is\n * punched out in, so one entry drives both layers.\n */\nexport const indicatorToneVariants = cva(\"\", {\n variants: {\n tone: {\n neutral: \"bg-muted-foreground text-background\",\n primary: \"bg-primary text-primary-foreground\",\n success: \"bg-success text-success-foreground\",\n warning: \"bg-warning text-warning-foreground\",\n info: \"bg-info text-info-foreground\",\n destructive: \"bg-destructive text-destructive-foreground\",\n accent: \"bg-accent text-accent-foreground\",\n } satisfies Record<IndicatorTone, string>,\n },\n defaultVariants: { tone: \"primary\" },\n});\n\n/** Which colour each presence state means, so `status` alone is enough. */\nconst STATUS_TONES = {\n online: \"success\",\n offline: \"neutral\",\n busy: \"destructive\",\n away: \"warning\",\n} satisfies Record<IndicatorStatus, IndicatorTone>;\n\n/**\n\n/**\n * Loom's English, co-located with the component so it tree-shakes with it, and\n * exported so a host can build a partial vocabulary against the real thing.\n */\nexport const INDICATOR_LABELS: IndicatorLabels = {\n online: \"Online\",\n offline: \"Offline\",\n busy: \"Busy\",\n away: \"Away\",\n count: ({ count }) => `${String(count)} unread`,\n attention: \"Needs attention\",\n};\n\n/**\n * The shape layer, and it exists for the sighted reader the `sr-only` string\n * below cannot help. Three of the four states are saturated — green, amber,\n * red — which is the exact triple a red/green deficiency collapses, so `busy`\n * wears a bar and `away` a hole and no two of them differ by hue alone.\n * `offline` needs none: grey against any of the three is a saturation\n * difference, not a hue one.\n */\nconst STATUS_GLYPHS = {\n online: \"\",\n offline: \"\",\n busy: \"h-0.5 w-1.5 rounded-full bg-current\",\n away: \"h-1 w-1 rounded-full bg-current\",\n} satisfies Record<IndicatorStatus, string>;\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, useId } from \"vue\";\nimport { cn, useSplitAttrs } from \"@ecoma-io/loom-core\";\nimport { useLabels, type LabelOverrides } from \"@ecoma-io/loom-labels\";\n\n/**\n * Indicator — the small marker pinned onto the corner of something else: a\n * presence dot on an avatar, an unread count on a bell, a \"needs attention\"\n * dot on a tab. The default slot is the thing being marked, and the marker\n * positions itself over that child's corner.\n *\n * The boundary with Badge is the whole of the decision between them: **Badge\n * sits in the flow beside content; Indicator is pinned onto content.** A count\n * chip in a table cell is a Badge. The same count floating over a bell icon is\n * an Indicator. Reach for Badge whenever the marker would take up room of its\n * own, and for this whenever it would overhang something.\n *\n * What this component is by default is a bare colour, which is the one thing\n * Loom's accessibility bar forbids outright. A green dot says nothing to a\n * reader who cannot see it. So every marker that renders carries a visually\n * hidden string — `label`, or a default derived from `status` or `count` — and\n * a blank `label` falls back to that default rather than replacing it, which\n * is what makes an unnamed indicator unreachable rather than merely\n * discouraged. The shape layer in `STATUS_GLYPHS` covers the sighted reader\n * the hidden string cannot.\n *\n * There is deliberately **no `aria-live` region here**, and the reason is that\n * this component cannot know whether a change is news. An unread counter is\n * usually fed by a poll, so a live region announces every tick over whatever\n * the reader was doing; the same count is commonly pinned in two places at\n * once, so it announces twice; and a polite region speaks on first render in\n * several screen reader and browser pairs, which turns every page load into a\n * recitation of the inbox. The marker is therefore static text a reader\n * reaches on demand, and announcing a *change* stays with the consumer, who\n * knows whether it followed something the reader just did.\n *\n * One consequence to design around: when the marked child is interactive, its\n * accessible name is computed from the child, and this marker's text sits\n * outside it — a bell button announces \"Notifications, button\" on focus and\n * never mentions the three unread. The default slot exposes `labelId` for\n * exactly that: bind it to the control's `aria-describedby` and the count is\n * announced straight after the name, once, without being duplicated into it.\n */\nconst props = withDefaults(\n defineProps<{\n /** A presence dot, or a number in a pill. */\n variant?: IndicatorVariant;\n /** The number the pill prints, when `variant` is `count`. Zero hides the marker unless `showZero` is set. */\n count?: number;\n /** The highest number printed in full; anything above it prints as `<max>+`. The accessible text still carries the real figure. */\n max?: number;\n /** Presence, for a dot: it picks the colour and the shape, and names the dot for a screen reader. Omit it for a plain \"something changed\" dot. */\n status?: IndicatorStatus;\n /** The marker's colour, in Badge's own vocabulary. Defaults to whatever `status` implies, or to `primary` when there is no status. */\n tone?: IndicatorTone;\n /** Which corner of the marked element the marker straddles. */\n placement?: IndicatorPlacement;\n /** What a screen reader announces for the marker. Leave it unset for the derived default — \"Online\", \"3 unread\" — and set it whenever the count is not of unread things. Blank or whitespace falls back to the default rather than clearing it. */\n label?: string;\n /** Render the pill when the count is zero. Off by default, because a count of nothing is not news. */\n showZero?: boolean;\n /** The surface the marked element sits on, so the ring separating the marker from it matches what surrounds them. */\n surface?: IndicatorSurface;\n /**\n * Names for the markers this component derives on its own, as any subset\n * of `IndicatorLabels` — the rest stay as the host's `provideLoomLabels`\n * vocabulary left them, and then as Loom's English.\n *\n * This is the vocabulary, not the instance's name: `label` still beats it\n * and is what one bell counting drafts rather than unread mail reaches for.\n */\n labels?: LabelOverrides<IndicatorLabels>;\n }>(),\n {\n variant: \"dot\",\n count: 0,\n max: 99,\n placement: \"top-right\",\n showZero: false,\n surface: \"background\",\n },\n);\n\n// `text`, not `labels`: the prop of that name is one of the three sources this\n// resolves, and a template reading the raw prop would be reading the overrides\n// rather than the answer.\nconst text = useLabels(\"indicator\", INDICATOR_LABELS, () => props.labels);\n\n// One rendered node, and every fallthrough attribute belongs on it — but\n// `class` still has to go the long way round. A consumer replacing the root's\n// `inline-flex` with `block` cannot win by concatenation, because the winner\n// there is decided by the order of the two rules in the stylesheet rather than\n// by the order of the two names in the attribute; `cn()` is what resolves it.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest } = useSplitAttrs();\n\n// Bound to the hidden label so an interactive child can point its\n// `aria-describedby` at it through the slot prop.\nconst labelId = useId();\n\n/**\n * The count as a whole, non-negative number. A negative count is a defect in\n * the caller's data, and a pill reading \"-1 unread\" reports that defect to the\n * reader rather than to the caller — falling back to \"nothing to report\" is\n * the honest rendering of it.\n */\nconst total = computed(() => Math.max(0, Math.trunc(props.count)));\n\nconst visible = computed(() => props.variant === \"dot\" || total.value > 0 || props.showZero);\n\n/** What the pill prints — the real figure up to `max`, then `<max>+`. */\nconst printed = computed(() =>\n total.value > props.max ? `${String(props.max)}+` : String(total.value),\n);\n\nconst tone = computed<IndicatorTone>(\n () => props.tone ?? (props.status ? STATUS_TONES[props.status] : \"primary\"),\n);\n\nconst glyph = computed(() => (props.status ? STATUS_GLYPHS[props.status] : \"\"));\n\n/**\n * The accessible name, and it is never empty by construction. The count case\n * reports `total` rather than `printed`: clamping at `max` is a decision about\n * how wide the pill is allowed to get, and a reader who cannot see the pill\n * has no reason to inherit it — \"132 unread\" is the fact, \"99+\" is the layout.\n */\nconst name = computed(() => {\n const given = props.label?.trim();\n if (given) return given;\n if (props.variant === \"count\") return text.value.count({ count: total.value });\n // Keyed by the status itself rather than through a lookup table of its own:\n // `IndicatorLabels` names its four presence keys after the four members of\n // `IndicatorStatus`, so a state added to the union with no name for it stops\n // compiling here instead of rendering an unnamed dot.\n return props.status ? text.value[props.status] : text.value.attention;\n});\n</script>\n\n<template>\n <span v-bind=\"rest\" :class=\"cn('relative inline-flex align-middle', attrs.class as string)\">\n <!-- A multi-line `@slot` comment comes back from vue-docgen with no description at all, so this one stays on one line. -->\n <!-- @slot The element being marked. `labelId` is the id of the marker's own hidden text — bind it to an interactive child's `aria-describedby` so the count is announced after that control's name. -->\n <slot :label-id=\"labelId\" />\n\n <!-- Keyed on what is printed rather than on the count, so `animate-scale-in`\n replays when a number a reader can see actually changes and stays put\n when 100 becomes 132 behind the same \"99+\". A dot's key never moves, so\n a dot never animates: presence settles into place on load, it does not\n arrive as news, and it must not pulse. -->\n <span\n v-if=\"visible\"\n :key=\"printed\"\n :data-placement=\"placement\"\n :class=\"\n cn(\n indicatorVariants({ variant, placement, surface }),\n indicatorToneVariants({ tone }),\n variant === 'count' && 'animate-scale-in',\n )\n \"\n >\n <!-- Hidden from assistive tech because the label below carries the real\n figure; left visible the pair would read as \"99+ 132 unread\". -->\n <span v-if=\"variant === 'count'\" aria-hidden=\"true\">{{ printed }}</span>\n <span v-else-if=\"glyph\" :class=\"glyph\" />\n\n <span :id=\"labelId\" class=\"sr-only\">{{ name }}</span>\n </span>\n </span>\n</template>\n"],"mappings":";;;;;;;;;;;;;;AAwBA,IAAa,oBAAoB,IAI/B,yFACA;CACE,UAAU;EACR,SAAS;GAGP,KAAK;GAIL,OAAO;EACT;EACA,WAAW;GACT,aAAa;GACb,YAAY;GACZ,gBAAgB;GAChB,eAAe;EACjB;EAKA,SAAS;GACP,YAAY;GACZ,MAAM;GACN,QAAQ;GACR,SAAS;EACX;CACF;CACA,iBAAiB;EAAE,SAAS;EAAO,WAAW;EAAa,SAAS;CAAa;AACnF,CACF;;;;;;;;;AAUA,IAAa,wBAAwB,IAAI,IAAI;CAC3C,UAAU,EACR,MAAM;EACJ,SAAS;EACT,SAAS;EACT,SAAS;EACT,SAAS;EACT,MAAM;EACN,aAAa;EACb,QAAQ;CACV,EACF;CACA,iBAAiB,EAAE,MAAM,UAAU;AACrC,CAAC;;AAGD,IAAM,eAAe;CACnB,QAAQ;CACR,SAAS;CACT,MAAM;CACN,MAAM;AACR;;;;;;;AAQA,IAAa,mBAAoC;CAC/C,QAAQ;CACR,SAAS;CACT,MAAM;CACN,MAAM;CACN,QAAQ,EAAE,YAAY,GAAG,OAAO,KAAK,EAAE;CACvC,WAAW;AACb;;;;;;;;;AAUA,IAAM,gBAAgB;CACpB,QAAQ;CACR,SAAS;CACT,MAAM;CACN,MAAM;AACR;;;;;;;;;;;;;;;;;;;;EA8CA,MAAM,QAAQ;EA2Cd,MAAM,OAAO,UAAU,aAAa,wBAAwB,MAAM,MAAM;EAQxE,MAAM,EAAE,OAAO,SAAS,cAAc;EAItC,MAAM,UAAU,MAAM;;;;;;;EAQtB,MAAM,QAAQ,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,MAAM,KAAK,CAAC,CAAC;EAEjE,MAAM,UAAU,eAAe,MAAM,YAAY,SAAS,MAAM,QAAQ,KAAK,MAAM,QAAQ;;EAG3F,MAAM,UAAU,eACd,MAAM,QAAQ,MAAM,MAAM,GAAG,OAAO,MAAM,GAAG,EAAE,KAAK,OAAO,MAAM,KAAK,CACxE;EAEA,MAAM,OAAO,eACL,MAAM,SAAS,MAAM,SAAS,aAAa,MAAM,UAAU,UACnE;EAEA,MAAM,QAAQ,eAAgB,MAAM,SAAS,cAAc,MAAM,UAAU,EAAG;;;;;;;EAQ9E,MAAM,OAAO,eAAe;GAC1B,MAAM,QAAQ,MAAM,OAAO,KAAK;GAChC,IAAI,OAAO,OAAO;GAClB,IAAI,MAAM,YAAY,SAAS,OAAO,KAAK,MAAM,MAAM,EAAE,OAAO,MAAM,MAAM,CAAC;GAK7E,OAAO,MAAM,SAAS,KAAK,MAAM,MAAM,UAAU,KAAK,MAAM;EAC9D,CAAC;;GAIC,OAAA,UAAA,GAAA,mBA6BO,QA7BP,WAAc,MA6BP,IAAA,GA7BW,EAAG,OAAO,MAAA,EAAA,CAAE,CAAA,qCAAsC,MAAA,KAAA,CAAK,CAAC,KAAK,EAAA,CAAA,GAAA,CAG7E,WAA4B,KAAA,QAAA,WAAA,EAArB,SAAU,MAAA,OAAA,EAAO,CAAA,GAQhB,QAAA,SADR,UAAA,GAAA,mBAkBO,QAAA;IAhBJ,KAAK,QAAA;IACL,kBAAgB,QAAA;IAChB,OAAK,eAAW,MAAA,EAAA,CAAE,CAAY,MAAA,iBAAA,CAAiB,CAAA;KAAA,SAAG,QAAA;KAAO,WAAE,QAAA;KAAS,SAAE,QAAA;IAAO,CAAA,GAAe,MAAA,qBAAA,CAAqB,CAAA,EAAA,MAAG,KAAA,MAAI,CAAA,GAAe,QAAA,YAAO,WAAA,kBAAA,CAAA;GAUnI,GAAA,CAAA,QAAA,YAAO,WAAnB,UAAA,GAAA,mBAAwE,QAAxE,YAAwE,gBAAjB,QAAA,KAAO,GAAA,CAAA,KAC7C,MAAA,SAAjB,UAAA,GAAA,mBAAyC,QAAA;;IAAhB,OAAK,eAAE,MAAA,KAAK;GAErC,GAAA,MAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,GAAA,mBAAqD,QAAA;IAA9C,IAAI,MAAA,OAAA;IAAS,OAAM;GAAa,GAAA,gBAAA,KAAA,KAAI,GAAA,GAAA,UAAA,CAAA,GAAA,IAAA,UAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,GAAA,EAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InlineError.js","names":[],"sources":["../../../../packages/primitives/inline-error/src/InlineError.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { TriangleAlert } from \"@lucide/vue\";\nimport { cn } from \"@ecoma-io/loom-core\";\n\n/**\n * InlineError — the one error contract for a field or a section, instead of\n * a paragraph here and a badge there. `role=\"alert\"` on the root means a\n * screen reader announces it the instant it enters the DOM, which is also\n * why a host must mount it with `v-if` rather than hide it with `v-show`:\n * CSS visibility leaves the node in the DOM, so a message change under\n * `v-show` may not re-announce.\n *\n * Persists until the host resolves the cause it names — there is no\n * auto-dismiss timer and no built-in close button. A transient notice that\n * hides itself belongs to a toast, not here.\n */\ndefineProps<{\n /** The error text. A default-slot child overrides this when both are given. */\n message?: string;\n}>();\n</script>\n\n<template>\n <div\n role=\"alert\"\n :class=\"\n cn(\n 'flex items-start gap-2 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive-text',\n 'animate-fade-rise',\n )\n \"\n >\n <TriangleAlert class=\"mt-0.5 h-4 w-4 shrink-0\" aria-hidden=\"true\" />\n <div class=\"min-w-0 flex-1\">\n <slot>{{ message }}</slot>\n </div>\n <div v-if=\"$slots.action\" class=\"shrink-0\"><slot name=\"action\" /></div>\n </div>\n</template>\n"],"mappings":""}
|
package/dist/primitives/inline-error/src/InlineError.vue_vue_type_script_setup_true_lang.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InlineError.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../../../packages/primitives/inline-error/src/InlineError.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { TriangleAlert } from \"@lucide/vue\";\nimport { cn } from \"@ecoma-io/loom-core\";\n\n/**\n * InlineError — the one error contract for a field or a section, instead of\n * a paragraph here and a badge there. `role=\"alert\"` on the root means a\n * screen reader announces it the instant it enters the DOM, which is also\n * why a host must mount it with `v-if` rather than hide it with `v-show`:\n * CSS visibility leaves the node in the DOM, so a message change under\n * `v-show` may not re-announce.\n *\n * Persists until the host resolves the cause it names — there is no\n * auto-dismiss timer and no built-in close button. A transient notice that\n * hides itself belongs to a toast, not here.\n */\ndefineProps<{\n /** The error text. A default-slot child overrides this when both are given. */\n message?: string;\n}>();\n</script>\n\n<template>\n <div\n role=\"alert\"\n :class=\"\n cn(\n 'flex items-start gap-2 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive-text',\n 'animate-fade-rise',\n )\n \"\n >\n <TriangleAlert class=\"mt-0.5 h-4 w-4 shrink-0\" aria-hidden=\"true\" />\n <div class=\"min-w-0 flex-1\">\n <slot>{{ message }}</slot>\n </div>\n <div v-if=\"$slots.action\" class=\"shrink-0\"><slot name=\"action\" /></div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;GAuBE,OAAA,UAAA,GAAA,mBAcM,OAAA;IAbJ,MAAK;IACJ,OAAK,eAAS,MAAA,EAAA,CAAE,CAAA,4HAAA,mBAAA,CAAA;;IAOjB,YAAoE,MAAA,aAAA,GAAA;KAArD,OAAM;KAA0B,eAAY;;IAC3D,mBAEM,OAFN,YAEM,CADJ,WAA0B,KAAA,QAAA,WAAA,CAAA,SAAA,CAAjB,gBAAA,gBAAA,QAAA,OAAO,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA;IAEPA,KAAAA,OAAO,UAAlB,UAAA,GAAA,mBAAuE,OAAvE,YAAuE,CAA5B,WAAsB,KAAA,QAAA,QAAA,CAAA,CAAA,KAAA,mBAAA,IAAA,IAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Kbd.js","names":[],"sources":["../../../../packages/primitives/kbd/src/Kbd.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { cva } from \"class-variance-authority\";\n\n/**\n * Kbd — one key cap. A combination is several of these side by side, joined\n * by a visible separator the host renders (`+` or `-`), with the whole run\n * given an accessible name on its wrapper; Kbd deliberately does not parse\n * shortcut strings, because the line between \"display\" and \"shortcut\n * manager\" is exactly where this primitive should stop.\n */\nexport type KbdSize = \"sm\" | \"md\";\n\nexport const kbdVariants = cva(\n [\n \"inline-flex select-none items-center justify-center rounded-sm\",\n // The cap: a subtle well, a hairline, and a bottom-weighted edge so it\n // reads as something you could press. Tokens only — high-contrast and\n // dark both come from the same pair every surface uses.\n \"border border-border border-b-border-strong bg-subtle text-foreground shadow-sm\",\n \"font-mono tabular whitespace-nowrap\",\n ],\n {\n variants: {\n size: {\n // Display-only, so target-size rules do not bind — the floors exist\n // because inline caps sit inside sentences, and one that shifts the\n // baseline or reads as a speck is worse than a generous box.\n sm: \"min-h-6 min-w-6 px-1.5 text-xs\",\n md: \"min-h-7 min-w-7 px-2 text-small\",\n },\n },\n defaultVariants: { size: \"md\" },\n },\n);\n</script>\n\n<script setup lang=\"ts\">\nimport { cn } from \"@ecoma-io/loom-core\";\n\nwithDefaults(\n defineProps<{\n /** `sm` sits inside prose and table cells; `md` for settings pages. */\n size?: KbdSize;\n }>(),\n { size: \"md\" },\n);\n</script>\n\n<template>\n <kbd :class=\"cn(kbdVariants({ size }))\">\n <!-- @slot The key's face — a letter, a glyph like ⌘, an arrow character. -->\n <slot />\n </kbd>\n</template>\n"],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Kbd.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../packages/primitives/kbd/src/Kbd.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { cva } from \"class-variance-authority\";\n\n/**\n * Kbd — one key cap. A combination is several of these side by side, joined\n * by a visible separator the host renders (`+` or `-`), with the whole run\n * given an accessible name on its wrapper; Kbd deliberately does not parse\n * shortcut strings, because the line between \"display\" and \"shortcut\n * manager\" is exactly where this primitive should stop.\n */\nexport type KbdSize = \"sm\" | \"md\";\n\nexport const kbdVariants = cva(\n [\n \"inline-flex select-none items-center justify-center rounded-sm\",\n // The cap: a subtle well, a hairline, and a bottom-weighted edge so it\n // reads as something you could press. Tokens only — high-contrast and\n // dark both come from the same pair every surface uses.\n \"border border-border border-b-border-strong bg-subtle text-foreground shadow-sm\",\n \"font-mono tabular whitespace-nowrap\",\n ],\n {\n variants: {\n size: {\n // Display-only, so target-size rules do not bind — the floors exist\n // because inline caps sit inside sentences, and one that shifts the\n // baseline or reads as a speck is worse than a generous box.\n sm: \"min-h-6 min-w-6 px-1.5 text-xs\",\n md: \"min-h-7 min-w-7 px-2 text-small\",\n },\n },\n defaultVariants: { size: \"md\" },\n },\n);\n</script>\n\n<script setup lang=\"ts\">\nimport { cn } from \"@ecoma-io/loom-core\";\n\nwithDefaults(\n defineProps<{\n /** `sm` sits inside prose and table cells; `md` for settings pages. */\n size?: KbdSize;\n }>(),\n { size: \"md\" },\n);\n</script>\n\n<template>\n <kbd :class=\"cn(kbdVariants({ size }))\">\n <!-- @slot The key's face — a letter, a glyph like ⌘, an arrow character. -->\n <slot />\n </kbd>\n</template>\n"],"mappings":";;;;;AAYA,IAAa,cAAc,IACzB;CACE;CAIA;CACA;AACF,GACA;CACE,UAAU,EACR,MAAM;EAIJ,IAAI;EACJ,IAAI;CACN,EACF;CACA,iBAAiB,EAAE,MAAM,KAAK;AAChC,CACF;;;;;;GAgBE,OAAA,UAAA,GAAA,mBAGM,OAAA,EAHA,OAAK,eAAE,MAAA,EAAA,CAAE,CAAC,MAAA,WAAA,CAAW,CAAA,EAAA,MAAG,QAAA,KAAI,CAAA,CAAA,CAAA,EAAA,GAAA,CAEhC,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Link.js","names":[],"sources":["../../../../packages/primitives/link/src/Link.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { cva } from \"class-variance-authority\";\n\n/** The visual emphasis assigned to a link. */\nexport type LinkVariant = \"default\" | \"muted\" | \"accent\" | \"subtle\";\n\nexport const linkVariants = cva(\n \"inline-flex items-center gap-1 transition-colors duration-fast ease-out focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo\",\n {\n variants: {\n variant: {\n default: \"text-primary-text underline underline-offset-4 hover:text-primary-text/80\",\n // Underlined like its siblings. WCAG 1.4.1 asks for a non-colour\n // carrier and the underline is the one links have; `muted` used to be\n // the variant that dropped it while keeping a hover colour change,\n // which identified the link by hue alone.\n muted: \"text-muted-foreground underline underline-offset-4 hover:text-foreground\",\n accent: \"text-accent-text underline underline-offset-4 hover:text-accent-text/80\",\n subtle:\n \"text-foreground/80 hover:text-foreground underline underline-offset-4 decoration-border hover:decoration-foreground/50\",\n } satisfies Record<LinkVariant, string>,\n underline: {\n true: \"\",\n false: \"no-underline\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n underline: true,\n },\n },\n);\n</script>\n\n<script setup lang=\"ts\">\nimport { cn } from \"@ecoma-io/loom-core\";\n\nwithDefaults(\n defineProps<{\n /** Controls the link's visual emphasis. */\n variant?: LinkVariant;\n /** Draws an underline beneath the link label. */\n underline?: boolean;\n /** The destination the link navigates to. */\n href: string;\n /** Opens the destination in a new tab and marks it as an external link. */\n external?: boolean;\n /** Replaces the anchor with an unavailable, non-interactive span. */\n disabled?: boolean;\n }>(),\n {\n variant: \"default\",\n underline: true,\n external: false,\n disabled: false,\n },\n);\n</script>\n\n<template>\n <span\n v-if=\"disabled\"\n :class=\"\n cn(\n linkVariants({ variant, underline }),\n // Drained, not dimmed — the same rule Button and Chip follow. The dim\n // faded whatever hue the variant wore, taking the label's contrast\n // down with it; a link has no fill to drain, so it takes the neutral\n // well the transparent controls take, and `aria-disabled` carries the\n // state rather than colour alone.\n 'cursor-default bg-muted text-muted-foreground pointer-events-none',\n $attrs.class,\n )\n \"\n aria-disabled=\"true\"\n >\n <slot />\n </span>\n <a\n v-else\n :href=\"href\"\n :class=\"cn(linkVariants({ variant, underline }), $attrs.class)\"\n :target=\"external ? '_blank' : undefined\"\n :rel=\"external ? 'noopener noreferrer' : undefined\"\n >\n <slot />\n <svg\n v-if=\"external\"\n class=\"h-3.5 w-3.5 shrink-0\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <path d=\"M7 17 17 7\" />\n <path d=\"M7 7h10v10\" />\n </svg>\n </a>\n</template>\n"],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Link.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../../packages/primitives/link/src/Link.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { cva } from \"class-variance-authority\";\n\n/** The visual emphasis assigned to a link. */\nexport type LinkVariant = \"default\" | \"muted\" | \"accent\" | \"subtle\";\n\nexport const linkVariants = cva(\n \"inline-flex items-center gap-1 transition-colors duration-fast ease-out focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo\",\n {\n variants: {\n variant: {\n default: \"text-primary-text underline underline-offset-4 hover:text-primary-text/80\",\n // Underlined like its siblings. WCAG 1.4.1 asks for a non-colour\n // carrier and the underline is the one links have; `muted` used to be\n // the variant that dropped it while keeping a hover colour change,\n // which identified the link by hue alone.\n muted: \"text-muted-foreground underline underline-offset-4 hover:text-foreground\",\n accent: \"text-accent-text underline underline-offset-4 hover:text-accent-text/80\",\n subtle:\n \"text-foreground/80 hover:text-foreground underline underline-offset-4 decoration-border hover:decoration-foreground/50\",\n } satisfies Record<LinkVariant, string>,\n underline: {\n true: \"\",\n false: \"no-underline\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n underline: true,\n },\n },\n);\n</script>\n\n<script setup lang=\"ts\">\nimport { cn } from \"@ecoma-io/loom-core\";\n\nwithDefaults(\n defineProps<{\n /** Controls the link's visual emphasis. */\n variant?: LinkVariant;\n /** Draws an underline beneath the link label. */\n underline?: boolean;\n /** The destination the link navigates to. */\n href: string;\n /** Opens the destination in a new tab and marks it as an external link. */\n external?: boolean;\n /** Replaces the anchor with an unavailable, non-interactive span. */\n disabled?: boolean;\n }>(),\n {\n variant: \"default\",\n underline: true,\n external: false,\n disabled: false,\n },\n);\n</script>\n\n<template>\n <span\n v-if=\"disabled\"\n :class=\"\n cn(\n linkVariants({ variant, underline }),\n // Drained, not dimmed — the same rule Button and Chip follow. The dim\n // faded whatever hue the variant wore, taking the label's contrast\n // down with it; a link has no fill to drain, so it takes the neutral\n // well the transparent controls take, and `aria-disabled` carries the\n // state rather than colour alone.\n 'cursor-default bg-muted text-muted-foreground pointer-events-none',\n $attrs.class,\n )\n \"\n aria-disabled=\"true\"\n >\n <slot />\n </span>\n <a\n v-else\n :href=\"href\"\n :class=\"cn(linkVariants({ variant, underline }), $attrs.class)\"\n :target=\"external ? '_blank' : undefined\"\n :rel=\"external ? 'noopener noreferrer' : undefined\"\n >\n <slot />\n <svg\n v-if=\"external\"\n class=\"h-3.5 w-3.5 shrink-0\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <path d=\"M7 17 17 7\" />\n <path d=\"M7 7h10v10\" />\n </svg>\n </a>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAMA,IAAa,eAAe,IAC1B,uLACA;CACE,UAAU;EACR,SAAS;GACP,SAAS;GAKT,OAAO;GACP,QAAQ;GACR,QACE;EACJ;EACA,WAAW;GACT,MAAM;GACN,OAAO;EACT;CACF;CACA,iBAAiB;EACf,SAAS;EACT,WAAW;CACb;AACF,CACF;;;;;;;;;;;;;;;;;;;;;GA8BU,OAAA,QAAA,YADR,UAAA,GAAA,mBAiBO,QAAA;;IAfJ,OAAK,eAAS,MAAA,EAAA,CAAE,CAAU,MAAA,YAAA,CAAY,CAAA;KAAA,SAAG,QAAA;KAAO,WAAE,QAAA;IAAS,CAAA,GAAA,qEAA6bA,KAAAA,OAAO,KAAA,CAAA;IAYhgB,iBAAc;GAEd,GAAA,CAAA,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,CAAA,MAEV,UAAA,GAAA,mBAyBI,KAAA;;IAvBD,MAAM,QAAA;IACN,OAAK,eAAE,MAAA,EAAA,CAAE,CAAC,MAAA,YAAA,CAAY,CAAA;KAAA,SAAG,QAAA;KAAO,WAAE,QAAA;IAAS,CAAA,GAAKA,KAAAA,OAAO,KAAK,CAAA;IAC5D,QAAQ,QAAA,WAAQ,WAAc,KAAA;IAC9B,KAAK,QAAA,WAAQ,wBAA2B,KAAA;GAEzC,GAAA,CAAA,WAAQ,KAAA,QAAA,SAAA,GAEA,QAAA,YADR,UAAA,GAAA,mBAgBM,OAhBN,YAgBM,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAFJ,mBAAuB,QAAA,EAAjB,GAAE,aAAY,GAAA,MAAA,EAAA,GACpB,mBAAuB,QAAA,EAAjB,GAAE,aAAY,GAAA,MAAA,EAAA,CAAA,EAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,GAAA,IAAA,UAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"List.js","names":[],"sources":["../../../../packages/primitives/list/src/List.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * List — a generic composition of rows: leading content, a title and\n * description, trailing metadata or actions. It is the *presentational*\n * vocabulary for row-shaped content, not a navigation primitive — SidebarNav\n * owns wayfinding, Menu owns commands, Table owns columns. This owns \"a\n * titled thing per line\" wherever that appears: settings groups, pickers,\n * summaries under a page's chrome.\n */\nimport { cn } from \"@ecoma-io/loom-core\";\n\nwithDefaults(\n defineProps<{\n /** Names the list for assistive technology when surrounding prose does not already say it. */\n label?: string;\n /** Hairline dividers between rows. Off for card-stacked lists. */\n divided?: boolean;\n }>(),\n { divided: true },\n);\nvoid cn;\n</script>\n\n<template>\n <ul :aria-label=\"label\" :class=\"cn('m-0 list-none p-0', divided && 'divide-y divide-border')\">\n <!-- @slot The rows: one `ListItem` per line. -->\n <slot />\n </ul>\n</template>\n"],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"List.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../packages/primitives/list/src/List.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * List — a generic composition of rows: leading content, a title and\n * description, trailing metadata or actions. It is the *presentational*\n * vocabulary for row-shaped content, not a navigation primitive — SidebarNav\n * owns wayfinding, Menu owns commands, Table owns columns. This owns \"a\n * titled thing per line\" wherever that appears: settings groups, pickers,\n * summaries under a page's chrome.\n */\nimport { cn } from \"@ecoma-io/loom-core\";\n\nwithDefaults(\n defineProps<{\n /** Names the list for assistive technology when surrounding prose does not already say it. */\n label?: string;\n /** Hairline dividers between rows. Off for card-stacked lists. */\n divided?: boolean;\n }>(),\n { divided: true },\n);\nvoid cn;\n</script>\n\n<template>\n <ul :aria-label=\"label\" :class=\"cn('m-0 list-none p-0', divided && 'divide-y divide-border')\">\n <!-- @slot The rows: one `ListItem` per line. -->\n <slot />\n </ul>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;GAwBE,OAAA,UAAA,GAAA,mBAGK,MAAA;IAHA,cAAY,QAAA;IAAQ,OAAK,eAAE,MAAA,EAAA,CAAE,CAAA,qBAAsB,QAAA,WAAO,wBAAA,CAAA;GAE7D,GAAA,CAAA,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,IAAA,UAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListItem.js","names":[],"sources":["../../../../packages/primitives/list/src/ListItem.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { cva } from \"class-variance-authority\";\n\n/**\n * Interactive comes in exactly two shapes, the same honesty Card documents:\n * `href` makes the whole row one real anchor (nothing interactive inside),\n * `interactive` paints hover/press while the host owns role/handler. Plain\n * rows are just rows.\n */\nexport type ListItemShape = \"static\" | \"link\" | \"interactive\";\n\nexport const listItemVariants = cva(\n \"flex w-full items-center gap-3 rounded-md px-3 py-2.5 text-left transition-colors duration-fast ease-out\",\n {\n variants: {\n shape: {\n static: \"\",\n // The shared clickable-row language: lift by fill, never by shadow.\n // The soft press weight, not `scale-press` — a full-width row moving\n // the full 3% reads as the page jolting rather than the row answering.\n link: \"cursor-pointer outline-none hover:bg-subtle/60 focus-visible:bg-subtle/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo [transition:transform_var(--duration-fast)_var(--ease-spring),background-color_var(--duration-fast)_var(--ease-out)] active:scale-press-soft\",\n interactive:\n \"cursor-pointer hover:bg-subtle/60 focus-visible:bg-subtle/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo active:bg-subtle\",\n },\n dense: { true: \"px-2 py-1.5\", false: \"\" },\n },\n },\n);\n</script>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { Check } from \"@lucide/vue\";\nimport { cn } from \"@ecoma-io/loom-core\";\n\nconst props = withDefaults(\n defineProps<{\n /** The row's heading; omit when the default slot carries custom composition. */\n title?: string;\n /** Supporting line beneath the title. */\n description?: string;\n /** Trailing metadata — a count, a timestamp. Reads in tabular digits. */\n meta?: string;\n /** Makes the whole row one link. Nothing interactive may sit inside. */\n href?: string;\n /**\n * Hover/press language for a clickable row whose behaviour belongs to\n * the host; attach the handler yourself.\n */\n interactive?: boolean;\n /** Marks this row as the current choice among its peers (`aria-current`). */\n selected?: boolean;\n /** Unavailable rather than hidden: drained, inert, still announced. */\n disabled?: boolean;\n /** Tighter rhythm inside dense chrome. */\n dense?: boolean;\n }>(),\n {\n interactive: false,\n selected: false,\n disabled: false,\n dense: false,\n },\n);\n\ndefineEmits<{ activate: [] }>();\n\n// One of three shapes decides the element; a disabled row is an inert button\n// rather than a missing one, so it stays announced.\nconst shape = computed<\"link\" | \"interactive\" | \"static\">(() =>\n props.href ? \"link\" : props.interactive ? \"interactive\" : \"static\",\n);\n</script>\n\n<template>\n <li>\n <component\n :is=\"href ? 'a' : interactive ? 'button' : 'div'\"\n :href=\"disabled ? undefined : href\"\n :type=\"interactive && !href ? 'button' : undefined\"\n :disabled=\"interactive && !href ? disabled : undefined\"\n :aria-disabled=\"disabled || undefined\"\n :aria-current=\"selected || undefined\"\n :class=\"\n cn(\n listItemVariants({ shape, dense }),\n selected && !disabled && 'bg-primary-muted/40 aria-current:bg-primary-muted/40',\n disabled && 'cursor-not-allowed bg-transparent',\n )\n \"\n @click=\"interactive && !disabled && $emit('activate')\"\n >\n <!-- @slot Before the title: an icon, an Avatar. -->\n <slot name=\"leading\" />\n\n <span class=\"min-w-0 flex-1\">\n <span v-if=\"title\" class=\"block truncate text-sm font-medium\">{{ title }}</span>\n <span v-if=\"description\" class=\"mt-0.5 block text-small text-muted-foreground\">{{\n description\n }}</span>\n <!-- @slot Custom body; replaces title/description entirely. -->\n <slot />\n </span>\n\n <!-- Selection is stated twice: aria-current for technology, a glyph\n for eyes — colour alone is not a state. -->\n <Check v-if=\"selected\" class=\"h-4 w-4 shrink-0 text-primary-text\" aria-hidden=\"true\" />\n\n <!-- @slot After everything: actions, a Badge, a RowActions cluster. -->\n <slot name=\"trailing\">\n <span v-if=\"meta\" class=\"shrink-0 text-small tabular text-muted-foreground\">{{\n meta\n }}</span>\n </slot>\n </component>\n </li>\n</template>\n"],"mappings":""}
|