@webx-ui/core 0.41.0 → 0.43.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/dist/CodeEditor-pJLpkTNW.js +333 -0
- package/dist/CodeEditor-pJLpkTNW.js.map +1 -0
- package/dist/RichText-BJK1BVlM.js +805 -0
- package/dist/RichText-BJK1BVlM.js.map +1 -0
- package/dist/components/CodeEditor/CodeEditor.d.ts +25 -42
- package/dist/components/CodeEditor/index.d.ts +45 -1
- package/dist/components/CodeEditor/mustache.d.ts +66 -0
- package/dist/components/CodeEditor/types.d.ts +83 -2
- package/dist/components/DatePicker/DatePicker.d.ts +2 -2
- package/dist/components/DateRangePicker/DateRangePicker.d.ts +2 -2
- package/dist/components/DateTimePicker/DateTimePicker.d.ts +2 -2
- package/dist/components/FileCard/FileCard.d.ts +6 -6
- package/dist/components/Icon/icons.d.ts +1 -0
- package/dist/components/ImageEditor/ImageEditor.d.ts +1 -1
- package/dist/components/Input/Input.d.ts +1 -1
- package/dist/components/RichText/index.d.ts +123 -1
- package/dist/components/Statistic/Statistic.d.ts +1 -1
- package/dist/components/Textarea/Textarea.d.ts +1 -1
- package/dist/components/TimePicker/TimePicker.d.ts +2 -2
- package/dist/index-CUqx8iDY.js +15751 -0
- package/dist/index-CUqx8iDY.js.map +1 -0
- package/dist/index.js +159 -16537
- package/dist/index.js.map +1 -1
- package/dist/internal/ImageEditorDialog.d.ts +2 -2
- package/dist/style.css +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-CUqx8iDY.js","sources":["../src/composables/useAccordion.ts","../src/components/Accordion/Accordion.vue","../src/components/Icon/icons.ts","../src/components/Icon/Icon.vue","../src/components/AccordionItem/AccordionItem.vue","../src/composables/useHoverPointer.ts","../src/components/Tooltip/Tooltip.vue","../src/composables/useActions.ts","../src/components/Action/Action.vue","../src/components/ActionBar/ActionBar.vue","../src/composables/useDropdown.ts","../src/components/Dropdown/Dropdown.vue","../src/components/Actions/Actions.vue","../src/components/Affix/Affix.vue","../src/components/Alert/Alert.vue","../src/components/Aside/Aside.vue","../src/composables/useFormField.ts","../src/composables/useControlAttrs.ts","../src/components/Autocomplete/Autocomplete.vue","../src/components/Avatar/Avatar.vue","../src/internal/nodes.ts","../src/components/AvatarGroup/AvatarGroup.vue","../src/components/Backtop/Backtop.vue","../src/components/Badge/Badge.vue","../src/composables/useBreadcrumb.ts","../src/components/Breadcrumb/Breadcrumb.vue","../src/components/BreadcrumbItem/BreadcrumbItem.vue","../src/composables/useButtonGroup.ts","../src/components/Button/Button.vue","../src/components/ButtonGroup/ButtonGroup.vue","../src/components/Card/Card.vue","../src/components/Cascader/Cascader.vue","../src/components/Checkbox/Checkbox.vue","../src/components/CodeEditor/mustache.ts","../src/components/CodeEditor/index.ts","../src/components/CheckboxGroup/CheckboxGroup.vue","../src/components/Col/Col.vue","../src/components/ColorPicker/ColorPicker.vue","../src/components/Container/Container.vue","../src/components/Statistic/Statistic.vue","../src/components/Countdown/format.ts","../src/components/Countdown/Countdown.vue","../src/internal/dateLocale.ts","../src/composables/useDateLocale.ts","../src/composables/useDateTimezone.ts","../src/components/DatePicker/DatePicker.vue","../src/components/DateRangePicker/DateRangePicker.vue","../src/components/DateTimePicker/DateTimePicker.vue","../src/components/Descriptions/context.ts","../src/components/Descriptions/Descriptions.vue","../src/components/DescriptionsItem/DescriptionsItem.vue","../src/composables/useOverlayPanel.ts","../src/components/Dialog/Dialog.vue","../src/components/Divider/Divider.vue","../src/components/Drawer/Drawer.vue","../src/components/DropdownItem/DropdownItem.vue","../src/components/Empty/Empty.vue","../src/components/EntityCard/EntityCard.vue","../src/components/Lightbox/items.ts","../src/components/Lightbox/Lightbox.vue","../src/composables/useImageGroup.ts","../src/components/Image/Image.vue","../src/composables/useLocalized.ts","../src/components/Locales/LocalePicker.vue","../src/internal/TokenButton.vue","../src/composables/useTokens.ts","../src/internal/TokenMenu.vue","../src/components/Input/Input.vue","../src/components/Popconfirm/Popconfirm.vue","../src/components/Popover/Popover.vue","../src/composables/useElementWidth.ts","../src/components/FileCard/files.ts","../src/components/FileCard/FileCard.vue","../src/components/Footer/Footer.vue","../src/components/Form/Form.vue","../src/components/FormItem/FormItem.vue","../src/components/Header/Header.vue","../src/components/Heading/Heading.vue","../src/components/IconPicker/IconPicker.vue","../src/components/InputNumber/InputNumber.vue","../src/components/Segmented/Segmented.vue","../src/components/Slider/Slider.vue","../src/components/Switch/Switch.vue","../src/components/ImageEditor/crop.ts","../src/components/ImageEditor/filters.ts","../src/components/ImageEditor/ImageEditor.vue","../src/components/ImageGroup/ImageGroup.vue","../src/components/Indicator/Indicator.vue","../../../node_modules/.pnpm/vue-draggable-plus@0.6.1_@types+sortablejs@1.15.9/node_modules/vue-draggable-plus/dist/vue-draggable-plus.js","../src/components/Kanban/Kanban.vue","../src/components/Link/Link.vue","../src/components/Locales/Locales.vue","../src/components/ListDetail/ListDetail.vue","../src/components/Loading/Loading.vue","../src/components/Main/Main.vue","../src/composables/useMenu.ts","../src/components/Submenu/Submenu.vue","../src/components/Menu/Menu.vue","../src/components/MenuGroup/MenuGroup.vue","../src/components/MenuItem/MenuItem.vue","../src/components/Pagination/Pagination.vue","../src/components/Progress/Progress.vue","../src/components/Prose/Prose.vue","../src/components/Radio/Radio.vue","../src/components/RadioGroup/RadioGroup.vue","../src/components/Rate/Rate.vue","../src/components/SortableList/SortableList.vue","../src/internal/FormScope.ts","../src/components/Repeater/Repeater.vue","../src/components/Result/Result.vue","../src/components/RichText/index.ts","../src/components/Row/Row.vue","../src/components/Scrollbar/Scrollbar.vue","../src/components/Select/Select.vue","../src/components/SelectionArea/directive.ts","../src/components/SelectionArea/SelectionArea.vue","../src/components/SkeletonItem/SkeletonItem.vue","../src/components/Skeleton/Skeleton.vue","../src/components/Space/Space.vue","../src/components/Steps/context.ts","../src/components/Step/Step.vue","../src/components/Steps/Steps.vue","../src/components/Tab/Tab.vue","../src/composables/useTreeNodes.ts","../src/components/Table/Table.vue","../src/components/Tabs/Tabs.vue","../src/components/TagsInput/TagsInput.vue","../src/components/Text/Text.vue","../src/components/Textarea/Textarea.vue","../src/components/ThemeSwitch/ThemeSwitch.vue","../src/composables/useTimeline.ts","../src/components/Timeline/Timeline.vue","../src/components/TimelineItem/TimelineItem.vue","../src/components/TimePicker/TimePicker.vue","../src/composables/useToast.ts","../src/components/Toaster/Toaster.vue","../src/components/Transfer/Transfer.vue","../src/components/Tree/Tree.vue","../src/components/TreeSelect/TreeSelect.vue","../src/components/Upload/Upload.vue","../src/composables/useModal.ts","../src/plugin.ts","../src/internal/ConfirmDialog.vue","../src/composables/confirm.ts","../src/internal/ImageEditorDialog.vue","../src/composables/imageEditor.ts","../src/internal/LightboxModal.vue","../src/composables/lightbox.ts","../src/composables/useResponsiveShell.ts"],"sourcesContent":["import { inject, type ComputedRef, type InjectionKey } from 'vue'\n\nexport type AccordionSize = 'sm' | 'md'\n\n/** Boxed as one list, each panel its own card, or nothing but rules between them. */\nexport type AccordionVariant = 'bordered' | 'separated' | 'plain'\n\n/** Which side of the header the chevron sits on. */\nexport type AccordionIconPosition = 'start' | 'end'\n\n/** What `WxAccordion` hands down to the items inside it. */\nexport interface AccordionContext {\n size: ComputedRef<AccordionSize>\n variant: ComputedRef<AccordionVariant>\n iconPosition: ComputedRef<AccordionIconPosition>\n /** The element each header is written as, so a page keeps one heading outline. */\n headingTag: ComputedRef<string>\n}\n\nexport const accordionKey: InjectionKey<AccordionContext> = Symbol('wx-accordion')\n\nexport function useAccordion(): AccordionContext | null {\n return inject(accordionKey, null)\n}\n","<script setup lang=\"ts\">\nimport { computed, provide, watch } from 'vue'\nimport { AccordionRoot } from 'reka-ui'\nimport { accordionKey } from '../../composables/useAccordion'\nimport type { AccordionEmits, AccordionModelValue, AccordionProps } from './types'\n\ndefineOptions({ name: 'WxAccordion' })\n\nconst props = withDefaults(defineProps<AccordionProps>(), {\n multiple: false,\n collapsible: true,\n variant: 'bordered',\n size: 'md',\n iconPosition: 'end',\n headingTag: 'h3',\n disabled: false,\n})\n\nconst emit = defineEmits<AccordionEmits>()\n\ndefineSlots<{\n /** The `WxAccordionItem`s. */\n default?: () => unknown\n}>()\n\n/**\n * One value or a list of them, depending on `multiple` — the same shape Reka uses, and\n * the same shape a backend would store it in.\n */\nconst model = defineModel<AccordionModelValue>({ default: undefined })\n\nprovide(accordionKey, {\n size: computed(() => props.size),\n variant: computed(() => props.variant),\n iconPosition: computed(() => props.iconPosition),\n headingTag: computed(() => props.headingTag),\n})\n\nwatch(model, (value) => emit('change', value))\n\nconst classes = computed(() => [\n 'wx-accordion',\n `wx-accordion--${props.variant}`,\n `wx-accordion--${props.size}`,\n])\n</script>\n\n<template>\n <accordion-root\n v-model=\"model\"\n :class=\"classes\"\n :type=\"multiple ? 'multiple' : 'single'\"\n :collapsible=\"collapsible\"\n :disabled=\"disabled\"\n >\n <slot />\n </accordion-root>\n</template>\n\n<style scoped>\n.wx-accordion {\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n}\n\n.wx-accordion--bordered {\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n /* The items square off their own corners; the box rounds what sticks out. */\n overflow: hidden;\n}\n\n/* Each item is its own card, with air between them. */\n.wx-accordion--separated {\n gap: var(--wx-space-8);\n}\n</style>\n","/*\n * The file family is a page with a mark on it. The page is drawn once here and the marks\n * sit in the room it leaves: roughly x 8.5–15.5, y 12–18, the lower half under the folded\n * corner. They are declared before the set below because that is where they are used.\n */\nconst PAGE = '<path d=\"M13.5 3.5H7a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V9zm0 0V9H19\"/>'\n\n/** Lines of prose. */\nconst TEXT = PAGE + '<path d=\"M8.5 12.8h7M8.5 15.4h7M8.5 18h4\"/>'\n/** A little grid. */\nconst SHEET = PAGE + '<path d=\"M8.5 12.6h7v5.4h-7z\"/><path d=\"M8.5 15.3h7M12 12.6V18\"/>'\n/** Bars, which is what a deck is full of. */\nconst SLIDES = PAGE + '<path d=\"M9.3 18v-2.6M12 18v-5.2M14.7 18v-3.6\"/>'\n/*\n * A P, because a red page with three letters on it is not available here. One letter and\n * not two: a P beside a bare stroke for the D read as \"PI\".\n */\nconst PDF = PAGE + '<path d=\"M10.2 18v-5.4h2.1a1.7 1.7 0 0 1 0 3.4h-2.1\"/>'\n/** The slider of a zip. */\nconst ARCHIVE =\n PAGE + '<rect x=\"10.4\" y=\"12.4\" width=\"3.2\" height=\"5.6\" rx=\"1.4\"/><path d=\"M12 14.4v1.6\"/>'\n/** A note with its stem. */\nconst AUDIO =\n PAGE +\n '<path d=\"M10.4 17.3v-4.4l4.6-1v4.4\"/><circle cx=\"9.3\" cy=\"17.4\" r=\"1.15\"/><circle cx=\"13.9\" cy=\"16.4\" r=\"1.15\"/>'\n/** A play triangle. */\nconst VIDEO = PAGE + '<path d=\"M10.4 12.9v4.8l4.4-2.4z\"/>'\n/** Hills and a sun — the same picture the `image` icon draws, at a sixth of the room. */\nconst PICTURE =\n PAGE + '<path d=\"M8.6 17.8 11 14.9l1.7 1.9 1.3-1.5 2.1 2.5\"/><circle cx=\"10\" cy=\"13.4\" r=\"1.05\"/>'\n/** A curve between two nodes. */\nconst VECTOR =\n PAGE +\n '<path d=\"M9.4 17.4c0-3.2 5.2-3.2 5.2 0\"/><circle cx=\"9.4\" cy=\"17.7\" r=\"1\"/><circle cx=\"14.6\" cy=\"17.7\" r=\"1\"/>'\n/** Sheets stacked on sheets. */\nconst LAYERED =\n PAGE + '<path d=\"m12 12.4-3.5 1.8 3.5 1.8 3.5-1.8z\"/><path d=\"m8.5 16.6 3.5 1.8 3.5-1.8\"/>'\n/** Angle brackets. */\nconst CODE = PAGE + '<path d=\"m10.5 13.3-2 2 2 2M13.5 13.3l2 2-2 2\"/>'\n/** A serif A, as close as a stroke gets to a specimen. */\nconst FONT = PAGE + '<path d=\"M9.6 18l2.4-5.4 2.4 5.4M10.5 16.2h3\"/>'\n\n/** The folder, drawn once: `folder-move` is this shape with an arrow going into it. */\nconst FOLDER =\n '<path d=\"M3.5 7a2 2 0 0 1 2-2h3.2a2 2 0 0 1 1.5.7l1.3 1.5h7a2 2 0 0 1 2 2v8.3a2 2 0 0 1-2 2h-13a2 2 0 0 1-2-2z\"/>'\n\n/**\n * The built-in icon set.\n *\n * Every entry is the *inside* of a 24×24 `<svg>` drawn in `currentColor` with a\n * stroke — the wrapper in `Icon.vue` supplies the viewBox, the stroke width and the\n * colour, so an icon inherits the text it sits next to. Shapes that read better\n * filled (dots, pips) set `fill=\"currentColor\" stroke=\"none\"` themselves.\n */\nexport const builtinIcons = {\n // --- actions -------------------------------------------------------------\n check: '<path d=\"m5 13 4.5 4.5L19 7\"/>',\n 'check-circle': '<circle cx=\"12\" cy=\"12\" r=\"8.5\"/><path d=\"m8.2 12.2 2.6 2.6 5-5.2\"/>',\n close: '<path d=\"M18 6 6 18M6 6l12 12\"/>',\n 'close-circle': '<circle cx=\"12\" cy=\"12\" r=\"8.5\"/><path d=\"m9 9 6 6m0-6-6 6\"/>',\n plus: '<path d=\"M12 5v14M5 12h14\"/>',\n minus: '<path d=\"M5 12h14\"/>',\n edit: '<path d=\"M4 20h4L19.5 8.5a2.83 2.83 0 0 0-4-4L4 16v4Z\"/><path d=\"m14.5 5.5 4 4\"/>',\n trash:\n '<path d=\"M4 7h16M10 7V5.5A1.5 1.5 0 0 1 11.5 4h1A1.5 1.5 0 0 1 14 5.5V7M6.5 7l.8 11.6a2 2 0 0 0 2 1.9h5.4a2 2 0 0 0 2-1.9L17.5 7\"/><path d=\"M10 11v5.5M14 11v5.5\"/>',\n copy: '<rect x=\"8.5\" y=\"8.5\" width=\"11\" height=\"11\" rx=\"2.2\"/><path d=\"M15.5 8.5v-2a2 2 0 0 0-2-2h-7a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h2\"/>',\n /* A board with its clip: something kept to be put down elsewhere. */\n clipboard:\n '<rect x=\"8.5\" y=\"2.8\" width=\"7\" height=\"3.6\" rx=\"1\"/><path d=\"M15.5 4.6H17a2 2 0 0 1 2 2V19a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6.6a2 2 0 0 1 2-2h1.5\"/>',\n /* The same board with what it holds coming down off it. */\n 'clipboard-paste':\n '<rect x=\"8.5\" y=\"2.8\" width=\"7\" height=\"3.6\" rx=\"1\"/><path d=\"M15.5 4.6H17a2 2 0 0 1 2 2V19a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6.6a2 2 0 0 1 2-2h1.5\"/><path d=\"M12 10v7M9.2 14.4 12 17.2l2.8-2.8\"/>',\n search: '<circle cx=\"11\" cy=\"11\" r=\"6.5\"/><path d=\"m16 16 4.5 4.5\"/>',\n 'zoom-in': '<circle cx=\"11\" cy=\"11\" r=\"6.5\"/><path d=\"m16 16 4.5 4.5M8.5 11h5M11 8.5v5\"/>',\n 'zoom-out': '<circle cx=\"11\" cy=\"11\" r=\"6.5\"/><path d=\"m16 16 4.5 4.5M8.5 11h5\"/>',\n play: '<path d=\"M8 5.5v13a1 1 0 0 0 1.5.86l10.6-6.5a1 1 0 0 0 0-1.72L9.5 4.64A1 1 0 0 0 8 5.5Z\"/>',\n filter: '<path d=\"M4 5.5h16l-6.2 7.2v5.1l-3.6 2v-7.1z\"/>',\n crop: '<path d=\"M6.5 2.5v13a2 2 0 0 0 2 2h13\"/><path d=\"M2.5 6.5h13a2 2 0 0 1 2 2v13\"/>',\n /*\n * A quarter turn each way: a ring open at its upper corner, with the corner mark for a\n * head. The arc is a single sweep between two points a chord apart — endpoints closer\n * to the diameter come out as two crescents instead of a ring.\n */\n 'rotate-left': '<path d=\"M4.5 9.5A8 8 0 1 1 4 13.5\"/><path d=\"M9.5 9.5h-5v-5\"/>',\n 'rotate-right': '<path d=\"M19.5 9.5A8 8 0 1 0 20 13.5\"/><path d=\"M14.5 9.5h5v-5\"/>',\n /*\n * The mirror line, a shape, and its reflection — filled on one side and drawn on the\n * other, since two identical shapes read as a pair rather than as a mirroring.\n */\n 'flip-horizontal':\n '<path d=\"M12 3.5v17\" stroke-dasharray=\"2.5 2.5\"/><path d=\"M9.5 7.5v9L4 14.5v-5z\" fill=\"currentColor\" stroke=\"none\"/><path d=\"M14.5 7.5v9l5.5-2v-5z\"/>',\n 'flip-vertical':\n '<path d=\"M3.5 12h17\" stroke-dasharray=\"2.5 2.5\"/><path d=\"M7.5 9.5h9L14.5 4h-5z\" fill=\"currentColor\" stroke=\"none\"/><path d=\"M7.5 14.5h9L14.5 20h-5z\"/>',\n refresh:\n '<path d=\"M4 12a8 8 0 0 1 13.7-5.6L20 8.5\"/><path d=\"M20 4.5v4h-4\"/><path d=\"M20 12a8 8 0 0 1-13.7 5.6L4 15.5\"/><path d=\"M4 19.5v-4h4\"/>',\n upload:\n '<path d=\"M12 16V4m0 0-4.5 4.5M12 4l4.5 4.5\"/><path d=\"M4 15v3.5A1.5 1.5 0 0 0 5.5 20h13a1.5 1.5 0 0 0 1.5-1.5V15\"/>',\n download:\n '<path d=\"M12 4v12m0 0-4.5-4.5M12 16l4.5-4.5\"/><path d=\"M4 15v3.5A1.5 1.5 0 0 0 5.5 20h13a1.5 1.5 0 0 0 1.5-1.5V15\"/>',\n logout:\n '<path d=\"M14 6V5a1.5 1.5 0 0 0-1.5-1.5h-6A1.5 1.5 0 0 0 5 5v14a1.5 1.5 0 0 0 1.5 1.5h6A1.5 1.5 0 0 0 14 19v-1\"/><path d=\"M10 12h10m0 0-3-3m3 3-3 3\"/>',\n\n // --- direction -----------------------------------------------------------\n 'chevron-down': '<path d=\"m6 9.5 6 6 6-6\"/>',\n 'chevron-up': '<path d=\"m6 14.5 6-6 6 6\"/>',\n 'chevron-left': '<path d=\"m14.5 6-6 6 6 6\"/>',\n 'chevron-right': '<path d=\"m9.5 6 6 6-6 6\"/>',\n 'arrow-up': '<path d=\"M12 20V4m0 0 6 6m-6-6-6 6\"/>',\n 'arrow-down': '<path d=\"M12 4v16m0 0 6-6m-6 6-6-6\"/>',\n 'arrow-left': '<path d=\"M20 12H4m0 0 6-6m-6 6 6 6\"/>',\n 'arrow-right': '<path d=\"M4 12h16m0 0-6-6m6 6-6 6\"/>',\n menu: '<path d=\"M4 7h16M4 12h16M4 17h16\"/>',\n /* The sidebar toggle: a page with a column down its left. */\n sidebar: '<rect x=\"3\" y=\"4.5\" width=\"18\" height=\"15\" rx=\"2.5\"/><path d=\"M9.5 4.5v15\"/>',\n /*\n * The three screens, and they are told apart by their proportions rather than by any\n * detail: at 1em a tablet and a phone are the same rounded rectangle, so the tablet is\n * drawn wide enough that the difference survives the size — 13 against 8. The desktop\n * gets its stand for the same reason.\n */\n monitor: '<rect x=\"3\" y=\"4\" width=\"18\" height=\"12.5\" rx=\"2.5\"/><path d=\"M12 16.5v3.5M8.5 20h7\"/>',\n tablet: '<rect x=\"5.5\" y=\"3\" width=\"13\" height=\"18\" rx=\"2.5\"/><path d=\"M10.7 17.6h2.6\"/>',\n smartphone: '<rect x=\"8\" y=\"2.5\" width=\"8\" height=\"19\" rx=\"2.2\"/><path d=\"M10.9 18.7h2.2\"/>',\n /* Four corners, pointing out of the picture and back into it. */\n maximize:\n '<path d=\"M9 4H5.5A1.5 1.5 0 0 0 4 5.5V9\"/><path d=\"M15 4h3.5A1.5 1.5 0 0 1 20 5.5V9\"/><path d=\"M20 15v3.5a1.5 1.5 0 0 1-1.5 1.5H15\"/><path d=\"M4 15v3.5A1.5 1.5 0 0 0 5.5 20H9\"/>',\n minimize:\n '<path d=\"M4 9h3.5A1.5 1.5 0 0 0 9 7.5V4\"/><path d=\"M20 9h-3.5A1.5 1.5 0 0 1 15 7.5V4\"/><path d=\"M15 20v-3.5a1.5 1.5 0 0 1 1.5-1.5H20\"/><path d=\"M9 20v-3.5A1.5 1.5 0 0 0 7.5 15H4\"/>',\n 'more-horizontal':\n '<circle cx=\"5.5\" cy=\"12\" r=\"1.6\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"12\" cy=\"12\" r=\"1.6\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"18.5\" cy=\"12\" r=\"1.6\" fill=\"currentColor\" stroke=\"none\"/>',\n 'more-vertical':\n '<circle cx=\"12\" cy=\"5.5\" r=\"1.6\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"12\" cy=\"12\" r=\"1.6\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"12\" cy=\"18.5\" r=\"1.6\" fill=\"currentColor\" stroke=\"none\"/>',\n drag: '<circle cx=\"9\" cy=\"6\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"15\" cy=\"6\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"9\" cy=\"12\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"15\" cy=\"12\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"9\" cy=\"18\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"15\" cy=\"18\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/>',\n\n // --- objects -------------------------------------------------------------\n user: '<circle cx=\"12\" cy=\"8\" r=\"3.75\"/><path d=\"M4.5 20a7.5 7.5 0 0 1 15 0\"/>',\n users:\n '<circle cx=\"9.5\" cy=\"8.5\" r=\"3.4\"/><path d=\"M2.5 20a7 7 0 0 1 14 0\"/><path d=\"M16 5.5a3.4 3.4 0 0 1 0 6.6M17.5 14.2A6.3 6.3 0 0 1 21.5 20\"/>',\n settings:\n '<circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M12 4v2.5M12 17.5V20M4 12h2.5M17.5 12H20M6.34 6.34l1.77 1.77M15.89 15.89l1.77 1.77M17.66 6.34l-1.77 1.77M6.34 17.66l1.77-1.77\"/>',\n gear: '<path stroke-linejoin=\"round\" d=\"M10.6 4.7L10.7 2.5L13.3 2.5L13.4 4.7L16.1 5.8L17.8 4.4L19.6 6.2L18.2 7.9L19.3 10.6L21.5 10.7L21.5 13.3L19.3 13.4L18.2 16.1L19.6 17.8L17.8 19.6L16.1 18.2L13.4 19.3L13.3 21.5L10.7 21.5L10.6 19.3L7.9 18.2L6.2 19.6L4.4 17.8L5.8 16.1L4.7 13.4L2.5 13.3L2.5 10.7L4.7 10.6L5.8 7.9L4.4 6.2L6.2 4.4L7.9 5.8Z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/>',\n sliders:\n '<path d=\"M4 7h9M17 7h3M4 17h3M11 17h9\"/><circle cx=\"15\" cy=\"7\" r=\"2\"/><circle cx=\"9\" cy=\"17\" r=\"2\"/>',\n home: '<path d=\"M4 10.5 12 4l8 6.5V19a1.5 1.5 0 0 1-1.5 1.5H15V14H9v6.5H5.5A1.5 1.5 0 0 1 4 19Z\"/>',\n file: '<path d=\"M13.5 3.5H7a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V9zm0 0V9H19\"/>',\n /*\n * A page with prose on it — the same picture `file-txt` draws, under the name a section\n * full of writing asks for. The two are deliberately one drawing: an article and a text\n * file are the same thing to a reader glancing at a 16 px menu.\n */\n 'file-text': TEXT,\n /*\n * A folded newspaper: the sheet, the one behind it curling out at the bottom left, a\n * masthead and two lines of column. Drawn at this size because a paper without the fold\n * is a document, and the fold is the only thing that tells the two apart.\n */\n newspaper:\n '<path d=\"M5 20.5h13.5a2 2 0 0 0 2-2v-13a2 2 0 0 0-2-2H9a2 2 0 0 0-2 2v13a2 2 0 0 1-2 2Z\"/><path d=\"M5 20.5a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2\"/><path d=\"M9.8 6.8h8.2v3.6h-8.2z\"/><path d=\"M9.8 13.6h8.2M9.8 16.6h5.2\"/>',\n folder: FOLDER,\n /*\n * Moving something into a folder. The arrow points down into the folder rather than\n * sideways at it: a folder small enough to leave room beside it for an arrow is a folder\n * nobody recognises at 16 px, which is the only size this is ever drawn at.\n */\n 'folder-move': FOLDER + '<path d=\"M12 9.2v6.4m0 0-2.6-2.6M12 15.6l2.6-2.6\"/>',\n image:\n '<rect x=\"3.5\" y=\"4.5\" width=\"17\" height=\"15\" rx=\"2.5\"/><circle cx=\"8.75\" cy=\"9.75\" r=\"1.75\"/><path d=\"m4 17 4.5-4.2a2 2 0 0 1 2.7 0l3 2.8 1.6-1.5a2 2 0 0 1 2.7 0L20 16\"/>',\n calendar:\n '<rect x=\"3.5\" y=\"5.5\" width=\"17\" height=\"15\" rx=\"2.5\"/><path d=\"M3.5 10h17M8 3.5V7M16 3.5V7\"/>',\n clock: '<circle cx=\"12\" cy=\"12\" r=\"8.5\"/><path d=\"M12 7.5V12l3 2\"/>',\n mail: '<rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2.5\"/><path d=\"m4 7.5 6.9 5a2 2 0 0 0 2.2 0l6.9-5\"/>',\n /* A paper plane: a message sent — a test, a chat bot. */\n send: '<path d=\"M20.5 3.5 3.8 10.4a.6.6 0 0 0 0 1.1l6.3 2.4 2.4 6.3a.6.6 0 0 0 1.1 0Z\"/><path d=\"m10.1 13.9 4.6-4.6\"/>',\n phone:\n '<path d=\"M7 3.5 9.5 4l1.2 3.4-1.9 1.6a11 11 0 0 0 5.2 5.2l1.6-1.9 3.4 1.2.5 2.5a2 2 0 0 1-2 2.3A15.5 15.5 0 0 1 4.7 5.5a2 2 0 0 1 2.3-2Z\"/>',\n bell: '<path d=\"M7 10a5 5 0 0 1 10 0c0 4 1.5 5.5 1.5 5.5h-13S7 14 7 10Z\"/><path d=\"M10.2 18.5a2 2 0 0 0 3.6 0\"/>',\n /*\n * A pin on a map: the teardrop and the hole in it. A set for a CMS without one is a set a\n * contacts page cannot use, and the drop is the one shape everybody reads as \"here\".\n */\n 'map-pin':\n '<path d=\"M12 21s6.5-6 6.5-10.5a6.5 6.5 0 0 0-13 0C5.5 15 12 21 12 21Z\"/><circle cx=\"12\" cy=\"10.3\" r=\"2.4\"/>',\n /*\n * A megaphone, for the block every site has that asks for something. The horn points up\n * and to the right — level, it reads as a traffic cone on its side.\n */\n megaphone:\n '<path d=\"M4.5 10.2v3.6a1.6 1.6 0 0 0 1.6 1.6h2.2l8.4 4.1a1 1 0 0 0 1.4-.9V5.4a1 1 0 0 0-1.4-.9L8.3 8.6H6.1a1.6 1.6 0 0 0-1.6 1.6Z\"/><path d=\"M8.3 15.4v2.8a2 2 0 0 0 2 2h.4a1 1 0 0 0 1-1.2l-.7-3.2\"/>',\n cart: '<path d=\"M3 4.5h2.2l2.3 10.2a1.6 1.6 0 0 0 1.6 1.3h7.4a1.6 1.6 0 0 0 1.6-1.2L20 8H6\"/><circle cx=\"10\" cy=\"19.5\" r=\"1.5\"/><circle cx=\"17\" cy=\"19.5\" r=\"1.5\"/>',\n tag: '<path d=\"M4 11.2V5.5A1.5 1.5 0 0 1 5.5 4h5.7a2 2 0 0 1 1.4.6l7 7a2 2 0 0 1 0 2.8l-5.2 5.2a2 2 0 0 1-2.8 0l-7-7a2 2 0 0 1-.6-1.4Z\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.4\" fill=\"currentColor\" stroke=\"none\"/>',\n link: '<path d=\"M10 14a4 4 0 0 0 5.7 0l3-3a4 4 0 0 0-5.7-5.7L11.5 7\"/><path d=\"M14 10a4 4 0 0 0-5.7 0l-3 3A4 4 0 0 0 11 18.7L12.5 17\"/>',\n 'external-link':\n '<path d=\"M13.5 4.5H20V11\"/><path d=\"m11 13 9-8.5\"/><path d=\"M19 14.5v4a1.5 1.5 0 0 1-1.5 1.5h-11A1.5 1.5 0 0 1 5 18.5v-11A1.5 1.5 0 0 1 6.5 6h4\"/>',\n lock: '<rect x=\"4.5\" y=\"10\" width=\"15\" height=\"10\" rx=\"2.5\"/><path d=\"M8 10V7.8a4 4 0 0 1 8 0V10\"/>',\n unlock:\n '<rect x=\"4.5\" y=\"10\" width=\"15\" height=\"10\" rx=\"2.5\"/><path d=\"M8 10V7.8a4 4 0 0 1 7.6-1.8\"/>',\n grid: '<rect x=\"4\" y=\"4\" width=\"7\" height=\"7\" rx=\"1.8\"/><rect x=\"13\" y=\"4\" width=\"7\" height=\"7\" rx=\"1.8\"/><rect x=\"4\" y=\"13\" width=\"7\" height=\"7\" rx=\"1.8\"/><rect x=\"13\" y=\"13\" width=\"7\" height=\"7\" rx=\"1.8\"/>',\n list: '<path d=\"M9 6h11M9 12h11M9 18h11\"/><circle cx=\"5\" cy=\"6\" r=\"1.4\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"5\" cy=\"12\" r=\"1.4\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"5\" cy=\"18\" r=\"1.4\" fill=\"currentColor\" stroke=\"none\"/>',\n eye: '<path d=\"M2.5 12S6.8 5.5 12 5.5 21.5 12 21.5 12 17.2 18.5 12 18.5 2.5 12 2.5 12Z\"/><circle cx=\"12\" cy=\"12\" r=\"2.75\"/>',\n 'eye-off':\n '<path d=\"M10.2 6a9.9 9.9 0 0 1 1.8-.2c5.2 0 9.5 6.2 9.5 6.2a18 18 0 0 1-3.3 3.8M6.6 7.9A17.8 17.8 0 0 0 2.5 12s4.3 6.5 9.5 6.5a9.4 9.4 0 0 0 3.3-.6\"/><path d=\"m4 4 16 16\"/>',\n star: '<path d=\"m12 4 2.5 5.1 5.6.8-4 4 .9 5.6-5-2.7-5 2.7.9-5.6-4-4 5.6-.8z\"/>',\n briefcase:\n '<rect x=\"3.5\" y=\"7.5\" width=\"17\" height=\"12\" rx=\"2.5\"/><path d=\"M9 7.5V6a1.5 1.5 0 0 1 1.5-1.5h3A1.5 1.5 0 0 1 15 6v1.5M3.5 13h17\"/>',\n factory:\n '<path d=\"M3.5 19.5V11l5 3.2V11l5 3.2V11l5 3.2V4.5h2.5v15Z\"/><path d=\"M7 16.5h2M11.5 16.5h2\"/>',\n heart:\n '<path d=\"M12 19.5S4 15 4 9.8A4.3 4.3 0 0 1 12 7.4 4.3 4.3 0 0 1 20 9.8c0 5.2-8 9.7-8 9.7Z\"/>',\n sun: '<circle cx=\"12\" cy=\"12\" r=\"4\"/><path d=\"M12 3v2M12 19v2M3 12h2M19 12h2M5.6 5.6 7 7M17 17l1.4 1.4M18.4 5.6 17 7M7 17l-1.4 1.4\"/>',\n moon: '<path d=\"M20 14.5A8.5 8.5 0 0 1 9.5 4a8.5 8.5 0 1 0 10.5 10.5Z\"/>',\n\n // --- status --------------------------------------------------------------\n info: '<circle cx=\"12\" cy=\"12\" r=\"8.5\"/><path d=\"M12 11v5\"/><circle cx=\"12\" cy=\"7.75\" r=\"1.05\" fill=\"currentColor\" stroke=\"none\"/>',\n warning:\n '<path d=\"M10.3 4.9a2 2 0 0 1 3.4 0l7 12.1a2 2 0 0 1-1.7 3H5a2 2 0 0 1-1.7-3z\"/><path d=\"M12 9.5v4\"/><circle cx=\"12\" cy=\"16.6\" r=\"1.05\" fill=\"currentColor\" stroke=\"none\"/>',\n question:\n '<circle cx=\"12\" cy=\"12\" r=\"8.5\"/><path d=\"M9.6 9.4a2.5 2.5 0 0 1 4.9.6c0 1.7-2.5 2-2.5 3.5\"/><circle cx=\"12\" cy=\"16.6\" r=\"1.05\" fill=\"currentColor\" stroke=\"none\"/>',\n loader:\n '<path d=\"M12 3.5v4M12 16.5v4M3.5 12h4M16.5 12h4M6 6l2.8 2.8M15.2 15.2 18 18M18 6l-2.8 2.8M8.8 15.2 6 18\"/>',\n\n /*\n * --- files ---------------------------------------------------------------\n *\n * A name per extension, so `file-docx` is a name whether or not it draws\n * something of its own, and a screen never has to map an extension to a family\n * before it can ask for an icon. Extensions that are the same kind of file share\n * a drawing: a `.docx` and an `.odt` are both a page of prose, and pretending\n * otherwise would mean twelve marks nobody can tell apart.\n *\n * `file-generic` is what an unknown extension gets. `WxFileCard` writes the\n * extension under it, which is the part that tells a `.sketch` from a `.dwg`.\n */\n 'file-generic': PAGE,\n\n 'file-txt': TEXT,\n 'file-md': TEXT,\n 'file-rtf': TEXT,\n 'file-doc': TEXT,\n 'file-docx': TEXT,\n 'file-odt': TEXT,\n 'file-pages': TEXT,\n\n 'file-csv': SHEET,\n 'file-xls': SHEET,\n 'file-xlsx': SHEET,\n 'file-ods': SHEET,\n 'file-numbers': SHEET,\n\n 'file-ppt': SLIDES,\n 'file-pptx': SLIDES,\n 'file-odp': SLIDES,\n 'file-key': SLIDES,\n\n 'file-pdf': PDF,\n\n 'file-zip': ARCHIVE,\n 'file-rar': ARCHIVE,\n 'file-7z': ARCHIVE,\n 'file-tar': ARCHIVE,\n 'file-gz': ARCHIVE,\n 'file-bz2': ARCHIVE,\n\n 'file-mp3': AUDIO,\n 'file-wav': AUDIO,\n 'file-ogg': AUDIO,\n 'file-flac': AUDIO,\n 'file-aac': AUDIO,\n 'file-m4a': AUDIO,\n\n 'file-mp4': VIDEO,\n 'file-mov': VIDEO,\n 'file-avi': VIDEO,\n 'file-webm': VIDEO,\n 'file-mkv': VIDEO,\n 'file-m4v': VIDEO,\n\n 'file-jpg': PICTURE,\n 'file-jpeg': PICTURE,\n 'file-png': PICTURE,\n 'file-gif': PICTURE,\n 'file-webp': PICTURE,\n 'file-avif': PICTURE,\n 'file-bmp': PICTURE,\n 'file-tiff': PICTURE,\n 'file-ico': PICTURE,\n\n 'file-svg': VECTOR,\n 'file-ai': VECTOR,\n 'file-eps': VECTOR,\n\n 'file-psd': LAYERED,\n 'file-xcf': LAYERED,\n 'file-fig': LAYERED,\n 'file-sketch': LAYERED,\n\n 'file-js': CODE,\n 'file-ts': CODE,\n 'file-jsx': CODE,\n 'file-tsx': CODE,\n 'file-vue': CODE,\n 'file-json': CODE,\n 'file-xml': CODE,\n 'file-yml': CODE,\n 'file-yaml': CODE,\n 'file-html': CODE,\n 'file-css': CODE,\n 'file-scss': CODE,\n 'file-php': CODE,\n 'file-py': CODE,\n 'file-rb': CODE,\n 'file-go': CODE,\n 'file-java': CODE,\n 'file-sh': CODE,\n 'file-sql': CODE,\n\n 'file-ttf': FONT,\n 'file-otf': FONT,\n 'file-woff': FONT,\n 'file-woff2': FONT,\n} as const satisfies Record<string, string>\n\n/** Every name the library ships with. */\nexport type BuiltinIconName = keyof typeof builtinIcons\n\nconst customIcons = new Map<string, string>()\n\n/**\n * Adds icons to the set, so `<wx-icon name=\"my-logo\" />` works anywhere in the app.\n *\n * ```ts\n * registerIcons({ 'my-logo': '<path d=\"M4 4h16v16H4z\" />' })\n * ```\n *\n * The markup is injected as-is, so register only icons you author or control —\n * never a string that arrived from a user or an API.\n */\nexport function registerIcons(icons: Record<string, string>): void {\n for (const [name, content] of Object.entries(icons)) customIcons.set(name, content)\n}\n\n/** The markup of an icon, or `undefined` when nothing is registered under that name. */\nexport function resolveIcon(name: string): string | undefined {\n return customIcons.get(name) ?? (builtinIcons as Record<string, string>)[name]\n}\n\n/** Names currently available, built-in plus registered — handy for a docs gallery. */\nexport function iconNames(): string[] {\n return [...new Set([...Object.keys(builtinIcons), ...customIcons.keys()])].sort()\n}\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { resolveIcon } from './icons'\nimport type { IconProps } from './types'\n\ndefineOptions({ name: 'WxIcon' })\n\nconst props = withDefaults(defineProps<IconProps>(), {\n size: undefined,\n strokeWidth: 1.7,\n spin: false,\n label: undefined,\n})\n\nconst keywordSizes: Record<string, string> = {\n sm: 'var(--wx-font-size-sm)',\n md: 'var(--wx-font-size-lg)',\n lg: 'var(--wx-font-size-2xl)',\n}\n\n/**\n * The markup is authored in `icons.ts` or handed to `registerIcons` by the app —\n * both are developer-controlled, which is what makes `v-html` safe here.\n */\nconst content = computed(() => resolveIcon(props.name))\n\n/*\n * The rule cannot tell an icon registry from a request body, so it is switched off\n * for this file rather than left as a warning somebody would eventually \"fix\" by\n * deleting the directive. It is switched off here, in the script, because a comment\n * above the template's root element would make that template a fragment.\n */\n/* eslint-disable vue/no-v-html */\n\nconst boxSize = computed(() => {\n const { size } = props\n if (size === undefined) return '1em'\n if (typeof size === 'number') return `${size}px`\n return keywordSizes[size] ?? size\n})\n\nconst classes = computed(() => ['wx-icon', { 'wx-icon--spin': props.spin }])\n</script>\n\n<template>\n <svg\n v-if=\"content\"\n :class=\"classes\"\n :style=\"{ '--wx-icon-size': boxSize }\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n :stroke-width=\"strokeWidth\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n :role=\"label ? 'img' : undefined\"\n :aria-label=\"label\"\n :aria-hidden=\"label ? undefined : 'true'\"\n focusable=\"false\"\n v-html=\"content\"\n />\n</template>\n\n<style scoped>\n.wx-icon {\n display: inline-block;\n flex: 0 0 auto;\n width: var(--wx-icon-size, 1em);\n height: var(--wx-icon-size, 1em);\n /* Sits on the text baseline rather than hanging below it. */\n vertical-align: -0.125em;\n overflow: visible;\n}\n\n/*\n * A turn a second. The duration tokens size transitions, not loops: even the slow one\n * is 320ms, which spins an icon three times a second and reads as a blur.\n */\n.wx-icon--spin {\n animation: wx-icon-spin var(--wx-icon-spin-duration, 1s) linear infinite;\n}\n\n@keyframes wx-icon-spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-icon--spin {\n animation-duration: 2s;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { AccordionContent, AccordionHeader, AccordionItem, AccordionTrigger } from 'reka-ui'\nimport WxIcon from '../Icon/Icon.vue'\nimport { useAccordion } from '../../composables/useAccordion'\nimport type { AccordionItemProps } from './types'\n\ndefineOptions({ name: 'WxAccordionItem' })\n\nconst props = withDefaults(defineProps<AccordionItemProps>(), {\n title: undefined,\n subtitle: undefined,\n icon: undefined,\n disabled: false,\n})\n\ndefineSlots<{\n /** The panel. */\n default?: () => unknown\n /** Replaces `title`. */\n title?: () => unknown\n /**\n * Sits at the end of the header, outside the button — so a switch or a menu there\n * can be operated without opening the item.\n */\n extra?: () => unknown\n}>()\n\nconst accordion = useAccordion()\n\nconst size = computed(() => accordion?.size.value ?? 'md')\nconst iconPosition = computed(() => accordion?.iconPosition.value ?? 'end')\nconst headingTag = computed(() => accordion?.headingTag.value ?? 'h3')\n\nconst classes = computed(() => [\n 'wx-accordion-item',\n `wx-accordion-item--${accordion?.variant.value ?? 'bordered'}`,\n `wx-accordion-item--${size.value}`,\n `wx-accordion-item--chevron-${iconPosition.value}`,\n // Everything standing before the title moves the panel text under it as well.\n { 'wx-accordion-item--icon': Boolean(props.icon) },\n])\n</script>\n\n<template>\n <accordion-item :class=\"classes\" :value=\"value\" :disabled=\"disabled\">\n <!--\n The heading holds the button and nothing else, which is what a screen reader\n reads out when it walks the headings of a page. Whatever the `extra` slot carries\n — a switch, a menu — sits beside the heading rather than inside it.\n -->\n <div class=\"wx-accordion-item__row\">\n <accordion-header class=\"wx-accordion-item__header\" :as=\"headingTag\">\n <accordion-trigger class=\"wx-accordion-item__trigger\">\n <wx-icon class=\"wx-accordion-item__chevron\" name=\"chevron-down\" />\n\n <wx-icon v-if=\"icon\" class=\"wx-accordion-item__icon\" :name=\"icon\" />\n\n <span class=\"wx-accordion-item__titles\">\n <span class=\"wx-accordion-item__title\">\n <slot name=\"title\">{{ title }}</slot>\n </span>\n <span v-if=\"subtitle\" class=\"wx-accordion-item__subtitle\">{{ subtitle }}</span>\n </span>\n </accordion-trigger>\n </accordion-header>\n\n <span v-if=\"$slots.extra\" class=\"wx-accordion-item__extra\">\n <slot name=\"extra\" />\n </span>\n </div>\n\n <accordion-content class=\"wx-accordion-item__content\">\n <div class=\"wx-accordion-item__body\">\n <slot />\n </div>\n </accordion-content>\n </accordion-item>\n</template>\n\n<style scoped>\n.wx-accordion-item {\n --wx-accordion-padding-x: var(--wx-space-16);\n --wx-accordion-padding-y: var(--wx-space-14);\n /* Air between the header and what it opened — see the body's padding. */\n --wx-accordion-gap: var(--wx-space-8);\n /* One mark — the chevron, or the icon — plus the gap after it. */\n --wx-accordion-mark: calc(var(--wx-font-size-lg) + var(--wx-space-10));\n --wx-accordion-chevron-indent: 0px;\n --wx-accordion-icon-indent: 0px;\n\n min-width: 0;\n}\n\n/* The panel text lines up with the title, not with whatever stands to its left. */\n.wx-accordion-item--chevron-start {\n --wx-accordion-chevron-indent: var(--wx-accordion-mark);\n}\n\n.wx-accordion-item--icon {\n --wx-accordion-icon-indent: var(--wx-accordion-mark);\n}\n\n.wx-accordion-item--sm {\n --wx-accordion-padding-x: var(--wx-space-12);\n --wx-accordion-padding-y: var(--wx-space-8);\n --wx-accordion-gap: var(--wx-space-4);\n}\n\n/* Inside one box the items are told apart by a rule, not by a border each. */\n.wx-accordion-item--bordered + .wx-accordion-item--bordered,\n.wx-accordion-item--plain + .wx-accordion-item--plain {\n border-top: 1px solid var(--wx-border-muted);\n}\n\n.wx-accordion-item--separated {\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-sm);\n overflow: hidden;\n}\n\n.wx-accordion-item__row {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n transition: background var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-accordion-item__header {\n flex: 1 1 auto;\n min-width: 0;\n margin: 0;\n font-size: inherit;\n font-weight: inherit;\n}\n\n.wx-accordion-item__trigger {\n display: flex;\n align-items: center;\n flex: 1 1 auto;\n gap: var(--wx-space-10);\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n padding: var(--wx-accordion-padding-y) var(--wx-accordion-padding-x);\n background: none;\n border: none;\n color: inherit;\n font: inherit;\n text-align: left;\n cursor: pointer;\n}\n\n/*\n * The tint belongs to the row, not to the button: the `extra` slot sits beside the\n * button, and a highlight that stopped at its edge left a seam down the header. It is\n * still the button that is being hovered — pointing at a switch in the `extra` must not\n * suggest that the section is about to open.\n */\n.wx-accordion-item__row:has(.wx-accordion-item__trigger:hover:not(:disabled)) {\n background: var(--wx-bg-subtle);\n}\n\n.wx-accordion-item__trigger:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-accordion-item__trigger:disabled {\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n/* The chevron is written first and moved by order, so the button's text order holds. */\n.wx-accordion-item--chevron-end .wx-accordion-item__chevron {\n order: 2;\n margin-left: auto;\n}\n\n.wx-accordion-item__chevron {\n flex: 0 0 auto;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-lg);\n transition: transform var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-accordion-item__trigger[data-state='open'] .wx-accordion-item__chevron {\n transform: rotate(180deg);\n}\n\n.wx-accordion-item__icon {\n flex: 0 0 auto;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-lg);\n}\n\n.wx-accordion-item__titles {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.wx-accordion-item__title {\n color: var(--wx-text-strong);\n font-size: var(--wx-font-size-md);\n font-weight: var(--wx-font-weight-medium);\n line-height: var(--wx-font-line-height-tight);\n}\n\n.wx-accordion-item--sm .wx-accordion-item__title {\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-accordion-item__subtitle {\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n font-weight: var(--wx-font-weight-regular);\n line-height: var(--wx-font-line-height-normal);\n}\n\n.wx-accordion-item__extra {\n display: flex;\n align-items: center;\n flex: 0 0 auto;\n gap: var(--wx-space-6);\n padding-right: var(--wx-accordion-padding-x);\n}\n\n/*\n * Reka measures the panel and publishes the height as a custom property, which is what\n * makes an animation from nothing to \"however tall this turns out to be\" possible.\n * The padding lives on the body inside, so the height being animated is only content.\n */\n.wx-accordion-item__content {\n overflow: hidden;\n}\n\n.wx-accordion-item__content[data-state='open'] {\n animation: wx-accordion-open var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-accordion-item__content[data-state='closed'] {\n animation: wx-accordion-close var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n/*\n * The header's own padding ends at the edge of the row it highlights, so without this\n * the panel starts flush against that edge and the two read as one block. The gap is\n * the panel's, and it is measured into the height that is animated.\n */\n.wx-accordion-item__body {\n padding-top: var(--wx-accordion-gap);\n padding-right: var(--wx-accordion-padding-x);\n padding-bottom: var(--wx-accordion-padding-y);\n padding-left: calc(\n var(--wx-accordion-padding-x) + var(--wx-accordion-chevron-indent) +\n var(--wx-accordion-icon-indent)\n );\n color: var(--wx-text-default);\n font-size: var(--wx-font-size-sm);\n line-height: var(--wx-font-line-height-normal);\n}\n\n@keyframes wx-accordion-open {\n from {\n height: 0;\n }\n\n to {\n height: var(--reka-accordion-content-height);\n }\n}\n\n@keyframes wx-accordion-close {\n from {\n height: var(--reka-accordion-content-height);\n }\n\n to {\n height: 0;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-accordion-item__content[data-state='open'],\n .wx-accordion-item__content[data-state='closed'] {\n animation: none;\n }\n\n .wx-accordion-item__chevron,\n .wx-accordion-item__row {\n transition: none;\n }\n}\n\n/* A header is a tap target; on a touch screen it needs the height of one. */\n@media (pointer: coarse) {\n .wx-accordion-item__trigger {\n min-height: 48px;\n }\n}\n</style>\n","import { ref, type Ref } from 'vue'\n\n/**\n * Whether the pointer on this device can hover.\n *\n * `false` on a touch screen, and that is the whole point: a tip that opens on hover has no\n * hover to open on. What a phone does instead is open it on the tap that was meant for the\n * button — so the reader taps, a black label appears over what they were aiming at, and the\n * button does its job underneath. A tooltip there is never information, only interference.\n *\n * One query and one listener for the whole application, because every `WxAction` on a screen\n * would otherwise register its own. A device that gains a mouse — a tablet with a keyboard\n * folded on — changes the answer, so this is a ref and not a constant read once.\n */\nlet hoverable: Ref<boolean> | null = null\n\nexport function useHoverPointer(): Ref<boolean> {\n if (hoverable !== null) return hoverable\n\n // Assume hover where the question cannot be asked — on the server and in jsdom, where the\n // answer would otherwise be \"touch\" for every test that has never seen a screen at all.\n const state = ref(true)\n\n if (typeof window !== 'undefined' && typeof window.matchMedia === 'function') {\n const query = window.matchMedia('(hover: hover)')\n\n state.value = query.matches\n query.addEventListener('change', (event) => {\n state.value = event.matches\n })\n }\n\n hoverable = state\n\n return hoverable\n}\n","<script setup lang=\"ts\">\nimport { computed, useTemplateRef } from 'vue'\nimport {\n TooltipArrow,\n TooltipContent,\n TooltipPortal,\n TooltipProvider,\n TooltipRoot,\n TooltipTrigger,\n} from 'reka-ui'\nimport { useHoverPointer } from '../../composables/useHoverPointer'\nimport type { TooltipProps } from './types'\n\ndefineOptions({ name: 'WxTooltip', inheritAttrs: false })\n\n/*\n * A tip, not a panel. It says what a control is and nothing more: it cannot be\n * clicked into, it never holds a button, and it is gone the moment the pointer\n * leaves. Anything a reader has to reach for is a `WxPopover`.\n *\n * Its own provider rather than one at the root of the app, so a tooltip works\n * wherever it is dropped. Reka's providers nest without fighting, and the grouping\n * that skips the delay for the second tip is per provider — which is the right\n * scope anyway: a toolbar's tips are a group, the page's tips are not.\n */\nconst props = withDefaults(defineProps<TooltipProps>(), {\n content: undefined,\n side: 'top',\n align: 'center',\n offset: 6,\n delay: 150,\n arrow: true,\n maxWidth: 260,\n disabled: false,\n teleport: true,\n})\n\ndefineSlots<{\n /** The control the tip belongs to. Exactly one element. */\n default?: () => unknown\n /** The tip itself, when the text is not enough. */\n content?: () => unknown\n}>()\n\n/* Left alone, the tip opens itself on hover and on focus; the model is for the\n * rare case of showing one from somewhere else — a hint after a failed save. */\nconst open = defineModel<boolean | undefined>('open', { default: undefined })\n\nconst width = computed(() =>\n typeof props.maxWidth === 'number' ? `${props.maxWidth}px` : props.maxWidth,\n)\n\n/*\n * Nothing opens by itself on a touch screen. The tap that would open a tip is the tap that\n * was meant for the button under it, so the reader gets a black label over the thing they\n * were aiming at — every icon button in the panel, on every phone.\n *\n * A tip somebody opens from code is left alone: `open` is the rare hint shown after a failed\n * save, and that one is deliberate rather than a side effect of pointing.\n */\nconst hoverable = useHoverPointer()\n\nconst shut = computed(() => props.disabled || (!hoverable.value && open.value === undefined))\n\n/*\n * Focus opens a tip for the keyboard, which has no other way of asking what an icon is. Focus\n * also comes back on its own: a dialog that closes hands it to the button that opened it, and\n * the tip then stood over the page until the pointer moved — over the very tree the person was\n * about to look at. So a focus the browser would not draw a ring for (`:focus-visible` — the\n * way back from a mouse click) opens nothing, unless the pointer really is over the control.\n */\nconst trigger = useTemplateRef<{ $el?: unknown }>('trigger')\n\nfunction quietFocus(): boolean {\n const el = trigger.value?.$el\n\n if (!(el instanceof HTMLElement) || el !== document.activeElement || el.matches(':hover')) {\n return false\n }\n\n try {\n return !el.matches(':focus-visible')\n } catch {\n /* A browser that does not know the selector: the tip as it always was. */\n return false\n }\n}\n\nfunction request(next: boolean) {\n if (next && quietFocus()) return\n open.value = next\n}\n</script>\n\n<template>\n <tooltip-provider\n :delay-duration=\"delay\"\n :skip-delay-duration=\"300\"\n :disable-hoverable-content=\"true\"\n >\n <tooltip-root :open=\"open ?? false\" :disabled=\"shut\" @update:open=\"request\">\n <!--\n `as-child`: the trigger is the control that was passed in. Wrapping it in a\n span of our own would put a box in the layout that nobody asked for, and\n would take the tip off the thing that is actually focused.\n -->\n <tooltip-trigger ref=\"trigger\" as-child>\n <slot />\n </tooltip-trigger>\n\n <tooltip-portal :disabled=\"!teleport\">\n <tooltip-content\n v-bind=\"$attrs\"\n class=\"wx-tooltip\"\n :side=\"side\"\n :align=\"align\"\n :side-offset=\"offset\"\n :style=\"{ '--wx-tooltip-max-width': width }\"\n >\n <slot name=\"content\">{{ content }}</slot>\n <tooltip-arrow v-if=\"arrow\" class=\"wx-tooltip__arrow\" :width=\"10\" :height=\"5\" />\n </tooltip-content>\n </tooltip-portal>\n </tooltip-root>\n </tooltip-provider>\n</template>\n\n<style>\n/* Teleported, so the styles cannot be scoped to the component. */\n.wx-tooltip {\n z-index: var(--wx-z-index-tooltip);\n box-sizing: border-box;\n max-width: var(--wx-tooltip-max-width, 260px);\n padding: var(--wx-space-6) var(--wx-space-8);\n background: var(--wx-bg-inverse);\n border-radius: var(--wx-radius-xs);\n color: var(--wx-text-inverse);\n font-family: var(--wx-font-family-sans);\n font-size: var(--wx-font-size-xs);\n line-height: var(--wx-font-line-height-normal);\n /* The tip belongs to whatever is under the pointer, never to the pointer. */\n pointer-events: none;\n}\n\n.wx-tooltip__arrow {\n fill: var(--wx-bg-inverse);\n}\n\n.wx-tooltip[data-state='delayed-open'] {\n animation: wx-tooltip-in var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n@keyframes wx-tooltip-in {\n from {\n opacity: 0;\n transform: scale(0.96);\n }\n\n to {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-tooltip[data-state='delayed-open'] {\n animation: none;\n }\n}\n</style>\n","import { inject, type ComputedRef, type InjectionKey } from 'vue'\nimport type { ActionSize } from '../components/Action/types'\n\n/** What a `WxActions` row hands down to the actions inside it. */\nexport interface ActionsContext {\n size: ComputedRef<ActionSize | undefined>\n}\n\nexport const actionsKey: InjectionKey<ActionsContext> = Symbol('wx-actions')\n\nexport function useActions(): ActionsContext | null {\n return inject(actionsKey, null)\n}\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport WxTooltip from '../Tooltip/Tooltip.vue'\nimport { useActions } from '../../composables/useActions'\nimport type { ActionEmits, ActionProps, ActionTone, ActionType } from './types'\nimport type { IconName } from '../Icon/types'\n\ndefineOptions({ name: 'WxAction', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<ActionProps>(), {\n type: 'edit',\n icon: undefined,\n tone: undefined,\n title: undefined,\n label: undefined,\n href: undefined,\n target: undefined,\n as: undefined,\n disabled: false,\n hidden: false,\n size: undefined,\n tooltipSide: 'top',\n})\n\nconst emit = defineEmits<ActionEmits>()\n\n/** Icon, colour and English fallback name for each kind of action. */\nconst presets: Record<ActionType, { icon: IconName; tone: ActionTone; label: string }> = {\n add: { icon: 'plus', tone: 'primary', label: 'Add' },\n edit: { icon: 'edit', tone: 'primary', label: 'Edit' },\n remove: { icon: 'trash', tone: 'danger', label: 'Delete' },\n copy: { icon: 'copy', tone: 'primary', label: 'Copy' },\n link: { icon: 'link', tone: 'primary', label: 'Link' },\n goto: { icon: 'external-link', tone: 'primary', label: 'Open' },\n details: { icon: 'info', tone: 'primary', label: 'Details' },\n view: { icon: 'eye', tone: 'primary', label: 'View' },\n hide: { icon: 'eye-off', tone: 'neutral', label: 'Hide' },\n upload: { icon: 'upload', tone: 'primary', label: 'Upload' },\n download: { icon: 'download', tone: 'primary', label: 'Download' },\n sort: { icon: 'drag', tone: 'neutral', label: 'Reorder' },\n search: { icon: 'search', tone: 'primary', label: 'Search' },\n restore: { icon: 'refresh', tone: 'success', label: 'Restore' },\n settings: { icon: 'settings', tone: 'neutral', label: 'Settings' },\n send: { icon: 'mail', tone: 'primary', label: 'Send' },\n more: { icon: 'more-horizontal', tone: 'neutral', label: 'More' },\n}\n\nconst group = useActions()\n\nconst preset = computed(() => presets[props.type] ?? presets.edit)\nconst icon = computed(() => props.icon ?? preset.value.icon)\nconst tone = computed(() => props.tone ?? preset.value.tone)\nconst size = computed(() => props.size ?? group?.size.value ?? 'md')\nconst accessibleName = computed(() => props.label ?? props.title ?? preset.value.label)\n\nconst tag = computed(() => props.as ?? (props.href ? 'a' : 'button'))\n\n/*\n * About the tooltip in the template below.\n *\n * It is ours rather than the browser's `title`: one shape for the whole panel, a delay we\n * choose and a side that can be pointed away from the edge of a dialog. It gives no\n * accessible name of its own, which is why `aria-label` stays on the control either way.\n * It is always mounted and switched off rather than added only when there is something to\n * say, so that an action with a tip and one without are the same markup.\n *\n * What it costs: the action is no longer a single root node. The tooltip draws nothing of its\n * own — the DOM is the same button in the same place — but the tip lives beside the control in\n * the component tree, so Vue's root here is a fragment and `$el` is its anchor rather than the\n * button. Nothing in a template notices; `wrapper.element` in a test does, and asks for\n * `wrapper.get('button')` instead.\n */\n\n/*\n * A disabled button says so with `aria-disabled`, the way the link and the `as` forms here\n * already do, and leaves the tab order with `tabindex` instead of with the attribute. The\n * attribute does both — and a third thing: the browser stops dispatching pointer events\n * anywhere near a disabled control, and a button nobody can hover is a button whose tooltip\n * never comes. An icon is at its least readable exactly when it is greyed out, so that tip is\n * the one worth keeping. Clicks and keys are turned away in `onClick`.\n */\nconst nativeAttrs = computed(() => {\n if (props.href) {\n return {\n href: props.disabled ? undefined : props.href,\n target: props.target,\n 'aria-disabled': props.disabled ? 'true' : undefined,\n tabindex: props.disabled ? -1 : undefined,\n }\n }\n if (props.as) return { 'aria-disabled': props.disabled ? 'true' : undefined }\n return {\n type: 'button' as const,\n 'aria-disabled': props.disabled ? 'true' : undefined,\n tabindex: props.disabled ? -1 : undefined,\n }\n})\n\nconst classes = computed(() => [\n 'wx-action',\n `wx-action--${size.value}`,\n `wx-action--${tone.value}`,\n { 'is-disabled': props.disabled },\n])\n\nfunction onClick(event: MouseEvent) {\n if (props.disabled) {\n event.preventDefault()\n event.stopPropagation()\n return\n }\n emit('click', event)\n}\n</script>\n\n<template>\n <span\n v-if=\"hidden\"\n class=\"wx-action wx-action--placeholder\"\n :class=\"`wx-action--${size}`\"\n aria-hidden=\"true\"\n />\n\n <wx-tooltip v-else :content=\"title\" :disabled=\"!title\" :side=\"tooltipSide\">\n <component\n :is=\"tag\"\n v-bind=\"{ ...nativeAttrs, ...$attrs }\"\n :class=\"classes\"\n :aria-label=\"accessibleName\"\n @click=\"onClick\"\n >\n <slot>\n <wx-icon :name=\"icon\" />\n </slot>\n </component>\n </wx-tooltip>\n</template>\n\n<style scoped>\n.wx-action {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n box-sizing: border-box;\n width: var(--wx-action-size, 36px);\n height: var(--wx-action-size, 36px);\n padding: 0;\n background: var(--wx-action-bg, var(--wx-bg-fill));\n border: 1px solid transparent;\n border-radius: var(--wx-radius-control);\n color: var(--wx-action-color, var(--wx-color-primary));\n font-size: var(--wx-action-icon, 18px);\n line-height: 1;\n text-decoration: none;\n cursor: pointer;\n transition:\n background-color var(--wx-duration-fast) var(--wx-easing-standard),\n color var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-action:hover:not(.is-disabled) {\n background: var(--wx-bg-fill-hover);\n}\n\n.wx-action:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-action.is-disabled {\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n/* An empty square: no background, no pointer, just the space. */\n.wx-action--placeholder {\n background: transparent;\n cursor: default;\n pointer-events: none;\n}\n\n/* sizes */\n.wx-action--sm {\n --wx-action-size: 30px;\n --wx-action-icon: 16px;\n}\n\n.wx-action--md {\n --wx-action-size: 36px;\n --wx-action-icon: 18px;\n}\n\n.wx-action--lg {\n --wx-action-size: 42px;\n --wx-action-icon: 20px;\n}\n\n/* tones */\n.wx-action--primary {\n --wx-action-color: var(--wx-color-primary);\n}\n\n.wx-action--danger {\n --wx-action-color: var(--wx-color-danger);\n}\n\n.wx-action--success {\n --wx-action-color: var(--wx-color-success-active);\n}\n\n.wx-action--warning {\n --wx-action-color: var(--wx-color-warning-active);\n}\n\n.wx-action--neutral {\n --wx-action-color: var(--wx-text-muted);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport type { ActionBarProps } from './types'\n\ndefineOptions({ name: 'WxActionBar' })\n\n/**\n * The row of a screen's own actions, along the bottom.\n *\n * A screen's buttons live in its head, and the head scrolls away with everything else — so a\n * form long enough to need saving is a form whose save button is off the top of the window by\n * the time it is needed. This is that button, brought back: the state of the work on the left,\n * what can be done about it on the right.\n *\n * It is part of the screen rather than of the shell — a list has none, a form has one — and it\n * is in the flow, as the last row of the screen, rather than laid over it. That is the whole of\n * why it never covers anything: at the end of a page it is the last thing on it, and above that\n * it sticks to the bottom of the window without taking the room it would need to be there.\n */\nconst props = withDefaults(defineProps<ActionBarProps>(), {\n sticky: true,\n bordered: true,\n})\n\nconst classes = computed(() => [\n 'wx-action-bar',\n {\n 'wx-action-bar--sticky': props.sticky,\n 'wx-action-bar--bordered': props.bordered,\n },\n])\n\n/*\n * How much of the bottom of the window the bar takes while it sticks there, told to the screen\n * it sits in as `--wx-action-bar-room`.\n *\n * Anything else in that screen that stands still against the window — the column of blocks\n * beside the page preview — would otherwise run its foot under the bar, and its own scroll with\n * it: the last field of a long form was out of reach behind the buttons. The bar's height is\n * whatever its buttons and its wrapped state make it (59.6px measured, not the 56 its minimum\n * says), so it is measured rather than assumed. It is written on the parent, the one element\n * that is sure to be above both the bar and whatever reads it.\n */\nconst root = ref<HTMLElement | null>(null)\nlet observer: ResizeObserver | null = null\nlet host: HTMLElement | null = null\n\nfunction publish() {\n if (!root.value || !host) return\n const bottom = Number.parseFloat(getComputedStyle(root.value).bottom) || 0\n host.style.setProperty(\n '--wx-action-bar-room',\n `${root.value.getBoundingClientRect().height + bottom}px`,\n )\n}\n\nfunction release() {\n observer?.disconnect()\n observer = null\n host?.style.removeProperty('--wx-action-bar-room')\n host = null\n}\n\nfunction track() {\n release()\n if (!props.sticky || !root.value?.parentElement || typeof ResizeObserver === 'undefined') {\n return\n }\n host = root.value.parentElement\n observer = new ResizeObserver(publish)\n observer.observe(root.value)\n publish()\n}\n\nonMounted(track)\nwatch(() => props.sticky, track, { flush: 'post' })\nonBeforeUnmount(release)\n</script>\n\n<template>\n <div ref=\"root\" :class=\"classes\">\n <div class=\"wx-action-bar__state\">\n <slot name=\"state\" />\n </div>\n\n <div class=\"wx-action-bar__actions\">\n <slot />\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-action-bar {\n display: flex;\n align-items: center;\n gap: var(--wx-space-12);\n /*\n * Two lines rather than one, once the buttons no longer leave the state room to be read.\n *\n * Without this there is nowhere for the state to go once the buttons have taken the width,\n * and what it does instead is overflow them: measured on a 375px screen with \"Saved · goes\n * out on 25 September at 17:06\" beside two buttons, the words ran over the top of \"Save\n * draft\". Nothing about that looks like a layout that ran out of room; it looks like the bar\n * is broken. The `min-width` on the state box below is the other half of the same fix.\n */\n flex-wrap: wrap;\n box-sizing: border-box;\n /* Never squeezed by a screen that is exactly as tall as the window: the bar keeps its\n height and the content above it is what shrinks. */\n flex: none;\n /* Down at the bottom of whatever room the screen has, rather than directly under the last\n card: in a flex column an auto margin eats the free space, and a screen kept at least as\n tall as its column has free space to give whenever the form is short. Anywhere else it\n computes to nothing. */\n margin-block-start: auto;\n min-height: var(--wx-action-bar-height, 56px);\n padding: var(--wx-space-8) var(--wx-space-12);\n border-radius: var(--wx-radius-md);\n background: var(--wx-bg-surface);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n}\n\n.wx-action-bar--bordered {\n border: 1px solid var(--wx-border-default);\n}\n\n/*\n * A floating card, and it casts the shadow of one, all the way round.\n *\n * It used to paint a strip of the body colour in the gap it keeps above the bottom of the\n * window, so that the page scrolling past did not show through. That strip is gone. An\n * element's outer shadow is painted with its background, before any of its descendants, so a\n * pseudo-element under the bar erased the part of the shadow that fell there — a flat band\n * with a stub of it left showing at each corner — and no stacking order fixes that, because a\n * descendant is always on top of its ancestor's shadow.\n *\n * What is seen through the gap instead is a sliver of the page still moving, which is honest:\n * the bar is floating over a page that scrolls, and that is what it looks like.\n */\n.wx-action-bar--sticky {\n position: sticky;\n bottom: var(--wx-action-bar-bottom, 0px);\n z-index: var(--wx-z-index-sticky);\n box-shadow: var(--wx-shadow-card);\n}\n\n/* The left side is whatever the screen says about the state of the work — saved, a draft,\n a version number. It gives way as the row narrows, down to the width of a short sentence;\n past that the buttons take a line of their own rather than the words giving way to nothing. */\n/*\n * As wide as what it holds, and never narrower than the longest word in it.\n *\n * It used to ask for 220px whatever it was given — which is right for a sentence and wrong for\n * everything else: a state that is one small mark took a line of its own on a phone and left an\n * empty strip above the buttons, because 220 plus two buttons does not fit 375. The basis is\n * the content now, so a mark sits beside the buttons and a sentence still pushes itself onto\n * the next line the moment it no longer fits.\n *\n * `min-width` is what the sentence is saved by, and it replaces the `0` that used to be here:\n * at zero the box was shrunk to nothing while its words went on being painted where the box no\n * longer was, straight across the buttons — measured on a 375px screen, the box 0 wide and the\n * words over the top of \"Save draft\". At `min-content` it cannot be shrunk past its longest\n * word, so it wraps instead of overflowing.\n */\n.wx-action-bar__state {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n flex: 1 1 auto;\n min-width: min-content;\n flex-wrap: wrap;\n}\n\n/* Against the end of the bar on one line and on two: on a line of its own the buttons would\n otherwise start at the left, under the words, which reads as a second, unrelated row. */\n/*\n * The buttons wrap too, for the same reason the bar does.\n *\n * `flex: 0 0 auto` kept them on one line whatever the width, and a line of five was 815px inside\n * a bar 359 wide — measured on a 375px screen, where it took the whole page sideways with it and\n * left a scrollbar under a list that fitted perfectly well. They keep the end of the bar while\n * there is room and fold into rows when there is not; `justify-content` is what keeps the fold\n * aligned with the edge the buttons came from.\n */\n.wx-action-bar__actions {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n flex-wrap: wrap;\n gap: var(--wx-space-8);\n flex: 0 1 auto;\n min-width: 0;\n margin-inline-start: auto;\n}\n</style>\n","import { inject, type InjectionKey } from 'vue'\n\n/** What a `WxDropdown` hands down, so an item inside it can close the panel. */\nexport interface DropdownContext {\n close: () => void\n /** Whether a click on an item closes the panel — the dropdown's `closeOnClick`. */\n closeOnSelect: () => boolean\n}\n\nexport const dropdownKey: InjectionKey<DropdownContext> = Symbol('wx-dropdown')\n\nexport function useDropdown(): DropdownContext | null {\n return inject(dropdownKey, null)\n}\n","<script setup lang=\"ts\">\nimport { provide, watch } from 'vue'\nimport { PopoverContent, PopoverPortal, PopoverRoot, PopoverTrigger } from 'reka-ui'\nimport { dropdownKey } from '../../composables/useDropdown'\nimport type { DropdownEmits, DropdownProps } from './types'\n\ndefineOptions({ name: 'WxDropdown', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<DropdownProps>(), {\n side: 'bottom',\n align: 'start',\n offset: 6,\n alignOffset: 0,\n closeOnClick: true,\n matchTriggerWidth: false,\n teleport: true,\n modal: false,\n disabled: false,\n})\n\nconst emit = defineEmits<DropdownEmits>()\n\nconst open = defineModel<boolean>('open', { default: false })\n\nfunction close() {\n open.value = false\n}\n\nprovide(dropdownKey, { close, closeOnSelect: () => props.closeOnClick })\n\nwatch(open, (value) => {\n if (value) emit('open')\n else emit('close')\n})\n\n/**\n * A click anywhere in the panel closes it, the way a menu behaves. Items that run\n * their own logic still close through the same path, and a panel that should stay\n * open while it is worked in turns this off with `:close-on-click=\"false\"`.\n */\nfunction onPanelClick() {\n if (props.closeOnClick) close()\n}\n</script>\n\n<template>\n <popover-root v-model:open=\"open\" :modal=\"modal\">\n <!--\n `as-child` rather than a button of our own: the trigger is nearly always a\n control that is already a button — WxButton, WxAction — and nesting one button\n inside another is invalid HTML. The slot must hold exactly one element.\n -->\n <popover-trigger as-child :disabled=\"disabled\">\n <slot name=\"trigger\" :open=\"open\" />\n </popover-trigger>\n\n <popover-portal :disabled=\"!teleport\">\n <popover-content\n v-bind=\"$attrs\"\n class=\"wx-dropdown\"\n :class=\"{ 'wx-dropdown--match-width': matchTriggerWidth }\"\n :side=\"side\"\n :align=\"align\"\n :side-offset=\"offset\"\n :align-offset=\"alignOffset\"\n @click=\"onPanelClick\"\n >\n <slot :close=\"close\" />\n </popover-content>\n </popover-portal>\n </popover-root>\n</template>\n\n<style>\n/* The panel is teleported, so its styles cannot be scoped to the component. */\n.wx-dropdown {\n /* One layer for every floating panel, so the one opened last is the one on top. */\n z-index: var(--wx-z-index-popover);\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 160px;\n max-width: min(90vw, 320px);\n padding: var(--wx-space-6);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-sm);\n box-shadow: var(--wx-shadow-popover);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-dropdown:focus-visible {\n outline: none;\n}\n\n.wx-dropdown--match-width {\n min-width: var(--reka-popover-trigger-width);\n}\n\n/* A rule between groups of items. */\n.wx-dropdown hr,\n.wx-dropdown .wx-dropdown__divider {\n height: 0;\n margin: var(--wx-space-4) 0;\n border: none;\n border-top: 1px solid var(--wx-border-muted);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, provide, ref, watch } from 'vue'\nimport WxAction from '../Action/Action.vue'\nimport WxDropdown from '../Dropdown/Dropdown.vue'\nimport { actionsKey } from '../../composables/useActions'\nimport type { ActionsEmits, ActionsProps } from './types'\n\ndefineOptions({ name: 'WxActions' })\n\nconst props = withDefaults(defineProps<ActionsProps>(), {\n align: 'start',\n size: undefined,\n collapse: false,\n ariaLabel: undefined,\n moreLabel: undefined,\n})\n\nconst emit = defineEmits<ActionsEmits>()\n\n/*\n * Whether the folded-up menu is showing. It is a model rather than a secret because the\n * panel is teleported: a row that hides itself until the pointer is over it loses that\n * pointer the moment the menu opens, and has no other way of knowing to stay.\n */\nconst menuOpen = defineModel<boolean>('menuOpen', { default: false })\n\nprovide(actionsKey, { size: computed(() => props.size) })\n\nconst root = ref<HTMLElement | null>(null)\nconst row = ref<HTMLElement | null>(null)\nconst tooWide = ref(false)\n\n/** Asked for outright, or arrived at by measuring. */\nconst collapsed = computed(() => props.collapse === 'always' || tooWide.value)\n\n/**\n * The row is measured against the space its container gives it. When it collapses\n * the row is not unmounted, only taken out of the flow — it keeps its natural width,\n * which is the only way to know when there is room for it again.\n */\nfunction measure() {\n const rowEl = row.value\n const parent = root.value?.parentElement\n if (props.collapse !== true || !rowEl || !parent) return\n\n /* `|| 0`: a padding that was never set reads as an empty string, not as `0px`. */\n const style = getComputedStyle(parent)\n const padding = (parseFloat(style.paddingLeft) || 0) + (parseFloat(style.paddingRight) || 0)\n const available = parent.clientWidth - padding\n\n /* jsdom and a container that has not been laid out yet both report zero. */\n if (available <= 0) return\n\n tooWide.value = rowEl.scrollWidth > available\n}\n\nlet observer: ResizeObserver | undefined\n\nfunction observe() {\n observer?.disconnect()\n if (props.collapse !== true) return\n\n observer = new ResizeObserver(() => measure())\n if (root.value?.parentElement) observer.observe(root.value.parentElement)\n if (row.value) observer.observe(row.value)\n measure()\n}\n\nonMounted(observe)\nwatch(() => props.collapse, observe)\nwatch(collapsed, (value) => emit('collapse', value))\nonBeforeUnmount(() => observer?.disconnect())\n\nconst classes = computed(() => [\n 'wx-actions',\n `wx-actions--${props.align}`,\n { 'is-collapsed': collapsed.value },\n])\n\ndefineExpose({ collapsed, measure })\n</script>\n\n<template>\n <div ref=\"root\" :class=\"classes\" role=\"group\" :aria-label=\"ariaLabel\">\n <!--\n Told to be a menu, the row is never drawn. Kept around it would be a second copy of\n every action — hidden, but still in the document — for a measurement nobody asked for.\n -->\n <div v-if=\"collapse !== 'always'\" ref=\"row\" class=\"wx-actions__row\">\n <slot />\n </div>\n\n <!-- The dropdown teleports its panel, so the class that hides it lives on a wrapper. -->\n <span v-if=\"collapse\" class=\"wx-actions__menu\">\n <wx-dropdown v-model:open=\"menuOpen\" align=\"end\">\n <template #trigger>\n <slot name=\"trigger\">\n <wx-action type=\"more\" :size=\"size\" :label=\"moreLabel\" />\n </slot>\n </template>\n\n <!-- Falls back to the row itself, so a plain list of actions needs no second copy. -->\n <slot name=\"collapsed\">\n <slot />\n </slot>\n </wx-dropdown>\n </span>\n </div>\n</template>\n\n<style scoped>\n.wx-actions {\n display: flex;\n align-items: center;\n /* The row is taken out of the flow when collapsed, so it anchors here. */\n position: relative;\n}\n\n.wx-actions--start {\n justify-content: flex-start;\n}\n\n.wx-actions--center {\n justify-content: center;\n}\n\n.wx-actions--end {\n justify-content: flex-end;\n}\n\n.wx-actions__row {\n display: flex;\n align-items: center;\n gap: var(--wx-actions-gap, var(--wx-space-6));\n}\n\n/* Hidden, but still measurable: that is what lets the row come back. */\n.wx-actions.is-collapsed .wx-actions__row {\n position: absolute;\n z-index: -1;\n visibility: hidden;\n height: 0;\n overflow: hidden;\n pointer-events: none;\n}\n\n.wx-actions:not(.is-collapsed) .wx-actions__menu {\n display: none;\n}\n\n/*\n * Folded up, the menu is the only way into what the row offers, so it has to be a target a\n * finger can hit.\n *\n * The property is set on the action itself, not on the wrapper for it to inherit: `WxAction`\n * declares its own `--wx-action-size` per size class, and a value declared on an element beats\n * one it would have inherited, whatever the specificity of the rule that set it upstream.\n * Measured on a phone: inherited it stayed 30 px and read as working.\n */\n@media (pointer: coarse) {\n .wx-actions__menu :deep(.wx-action) {\n --wx-action-size: 44px;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport type { AffixEmits, AffixProps } from './types'\n\ndefineOptions({ name: 'WxAffix' })\n\n/*\n * `position: sticky` does the sticking; the JavaScript here is only to report it.\n *\n * That is the whole design. Every implementation that measures scroll offsets and\n * switches to `position: fixed` inherits the same two bugs — the page jumps by the\n * height of the element the moment it leaves the flow, and it sticks to the window\n * rather than to whatever is actually scrolling. Sticky has neither, and it works\n * without a single listener.\n */\nconst props = withDefaults(defineProps<AffixProps>(), {\n offset: 0,\n position: 'top',\n disabled: false,\n zIndex: undefined,\n})\n\nconst emit = defineEmits<AffixEmits>()\n\ndefineSlots<{ default?: (props: { stuck: boolean }) => unknown }>()\n\nconst stuck = ref(false)\n\n/*\n * A sentinel one pixel outside the sticky element, watched by an observer: while it\n * is on screen the element is in its place, and the moment it is not, the element\n * has stuck. It is the one way to be told about sticky without polling the scroll.\n */\nconst sentinel = ref<HTMLElement | null>(null)\n\nlet observer: IntersectionObserver | null = null\n\nfunction watchSentinel() {\n observer?.disconnect()\n observer = null\n\n if (props.disabled || !sentinel.value || typeof IntersectionObserver === 'undefined') {\n if (stuck.value) {\n stuck.value = false\n emit('change', false)\n }\n return\n }\n\n /*\n * The viewport is shrunk by the resting offset, so the sentinel stops intersecting\n * at exactly the moment the element above it would have been pushed past its\n * resting place — which is the moment it sticks.\n */\n const margin =\n props.position === 'top'\n ? `${-props.offset - 1}px 0px 0px 0px`\n : `0px 0px ${-props.offset - 1}px 0px`\n\n observer = new IntersectionObserver(\n ([entry]) => {\n const next = !entry.isIntersecting\n if (next === stuck.value) return\n stuck.value = next\n emit('change', next)\n },\n { rootMargin: margin, threshold: 0 },\n )\n\n observer.observe(sentinel.value)\n}\n\nonMounted(watchSentinel)\nwatch([() => props.disabled, () => props.offset, () => props.position], watchSentinel)\n\nonBeforeUnmount(() => {\n observer?.disconnect()\n observer = null\n})\n\nconst style = computed(() => {\n if (props.disabled) return undefined\n return {\n position: 'sticky' as const,\n [props.position]: `${props.offset}px`,\n zIndex: props.zIndex,\n }\n})\n</script>\n\n<template>\n <div class=\"wx-affix\">\n <div\n v-if=\"!disabled\"\n ref=\"sentinel\"\n class=\"wx-affix__sentinel\"\n :class=\"`wx-affix__sentinel--${position}`\"\n aria-hidden=\"true\"\n />\n\n <div class=\"wx-affix__content\" :class=\"{ 'is-stuck': stuck }\" :style=\"style\">\n <slot :stuck=\"stuck\" />\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-affix {\n position: relative;\n}\n\n/*\n * A pixel tall and invisible, sitting exactly where the element will come to rest.\n * It is only ever looked at by the observer.\n */\n.wx-affix__sentinel {\n position: absolute;\n inset-inline: 0;\n height: 1px;\n pointer-events: none;\n visibility: hidden;\n}\n\n.wx-affix__sentinel--top {\n top: 0;\n}\n\n.wx-affix__sentinel--bottom {\n bottom: 0;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport type { AlertEmits, AlertProps } from './types'\nimport type { IconName } from '../Icon/types'\n\ndefineOptions({ name: 'WxAlert' })\n\nconst props = withDefaults(defineProps<AlertProps>(), {\n type: 'info',\n variant: 'soft',\n title: undefined,\n description: undefined,\n icon: undefined,\n closable: false,\n closeLabel: 'Dismiss',\n live: false,\n})\n\nconst emit = defineEmits<AlertEmits>()\n\n/**\n * Kept as a model so `<wx-alert closable />` dismisses itself, while a page that\n * needs the alert back — a validation summary, say — binds `v-model:visible`.\n */\nconst visible = defineModel<boolean>('visible', { default: true })\n\nconst typeIcons: Record<string, IconName> = {\n info: 'info',\n success: 'check-circle',\n warning: 'warning',\n danger: 'close-circle',\n}\n\nconst iconName = computed(() => {\n if (props.icon === false) return undefined\n return props.icon ?? typeIcons[props.type]\n})\n\nconst classes = computed(() => [\n 'wx-alert',\n `wx-alert--${props.type}`,\n `wx-alert--${props.variant}`,\n { 'wx-alert--titled': Boolean(props.title) },\n])\n\nfunction onClose(event: MouseEvent) {\n visible.value = false\n emit('close', event)\n}\n</script>\n\n<template>\n <div v-if=\"visible\" :class=\"classes\" :role=\"live ? 'alert' : undefined\">\n <span v-if=\"iconName || $slots.icon\" class=\"wx-alert__icon\">\n <slot name=\"icon\">\n <wx-icon v-if=\"iconName\" :name=\"iconName\" size=\"1.15em\" />\n </slot>\n </span>\n\n <div class=\"wx-alert__content\">\n <p v-if=\"title || $slots.title\" class=\"wx-alert__title\">\n <slot name=\"title\">{{ title }}</slot>\n </p>\n <div v-if=\"description || $slots.default\" class=\"wx-alert__body\">\n <slot>{{ description }}</slot>\n </div>\n </div>\n\n <div v-if=\"$slots.actions\" class=\"wx-alert__actions\">\n <slot name=\"actions\" />\n </div>\n\n <button\n v-if=\"closable\"\n class=\"wx-alert__close\"\n type=\"button\"\n :aria-label=\"closeLabel\"\n @click=\"onClose\"\n >\n <wx-icon name=\"close\" />\n </button>\n </div>\n</template>\n\n<style scoped>\n.wx-alert {\n display: flex;\n align-items: flex-start;\n gap: var(--wx-space-10);\n box-sizing: border-box;\n padding: var(--wx-space-12) var(--wx-space-14);\n border: 1px solid transparent;\n border-radius: var(--wx-radius-sm);\n font-family: var(--wx-font-family-sans);\n font-size: var(--wx-font-size-sm);\n line-height: var(--wx-font-line-height-normal);\n}\n\n/* Each type names its colours once; the variants below stay type-agnostic. */\n.wx-alert--info {\n --wx-alert-accent: var(--wx-color-info-active);\n --wx-alert-soft: var(--wx-color-info-soft);\n --wx-alert-solid: var(--wx-color-info);\n --wx-alert-contrast: var(--wx-color-info-contrast);\n}\n\n.wx-alert--success {\n --wx-alert-accent: var(--wx-color-success-active);\n --wx-alert-soft: var(--wx-color-success-soft);\n --wx-alert-solid: var(--wx-color-success);\n --wx-alert-contrast: var(--wx-color-success-contrast);\n}\n\n.wx-alert--warning {\n --wx-alert-accent: var(--wx-color-warning-active);\n --wx-alert-soft: var(--wx-color-warning-soft);\n --wx-alert-solid: var(--wx-color-warning);\n --wx-alert-contrast: var(--wx-color-warning-contrast);\n}\n\n.wx-alert--danger {\n --wx-alert-accent: var(--wx-color-danger);\n --wx-alert-soft: var(--wx-color-danger-soft);\n --wx-alert-solid: var(--wx-color-danger);\n --wx-alert-contrast: var(--wx-color-danger-contrast);\n}\n\n/* variants */\n.wx-alert--soft {\n background: var(--wx-alert-soft);\n color: var(--wx-text-default);\n}\n\n.wx-alert--outline {\n background: var(--wx-bg-surface);\n border-color: var(--wx-alert-accent);\n color: var(--wx-text-default);\n}\n\n.wx-alert--solid {\n background: var(--wx-alert-solid);\n color: var(--wx-alert-contrast);\n}\n\n/* The icon carries the colour in the quiet variants; in `solid` everything already has it. */\n.wx-alert--soft .wx-alert__icon,\n.wx-alert--outline .wx-alert__icon {\n color: var(--wx-alert-accent);\n}\n\n.wx-alert__icon {\n display: inline-flex;\n flex: 0 0 auto;\n /* Lines the icon up with the first line of text rather than the box. */\n padding-top: 0.1em;\n}\n\n/*\n * A zero basis rather than the text's own width: on a narrow screen the alert wraps, and a long\n * title measured at its full width would wrap below the icon instead of beside it.\n */\n.wx-alert__content {\n flex: 1 1 0;\n min-width: 0;\n}\n\n.wx-alert__title {\n margin: 0;\n font-size: var(--wx-font-size-sm);\n font-weight: var(--wx-font-weight-semibold);\n line-height: var(--wx-font-line-height-tight);\n}\n\n.wx-alert--titled .wx-alert__body {\n margin-top: var(--wx-space-4);\n}\n\n.wx-alert--soft .wx-alert__body,\n.wx-alert--outline .wx-alert__body {\n color: var(--wx-text-muted);\n}\n\n.wx-alert__body :deep(p) {\n margin: 0;\n}\n\n.wx-alert__body :deep(p + p) {\n margin-top: var(--wx-space-8);\n}\n\n/* Wrapping: three buttons under a narrow alert go onto a second line rather than past its edge. */\n.wx-alert__actions {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-8);\n flex: 0 0 auto;\n}\n\n.wx-alert__close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n padding: 0;\n background: transparent;\n border: none;\n border-radius: var(--wx-radius-xs);\n color: inherit;\n font-size: var(--wx-font-size-lg);\n line-height: 1;\n opacity: 0.65;\n cursor: pointer;\n}\n\n.wx-alert__close:hover {\n opacity: 1;\n}\n\n.wx-alert__close:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n/* A stack of alerts on a narrow screen reads better with the actions on their own line. */\n@media (max-width: 480px) {\n .wx-alert {\n flex-wrap: wrap;\n }\n\n .wx-alert__actions {\n box-sizing: border-box;\n width: 100%;\n padding-left: calc(1.15em + var(--wx-space-10));\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, useSlots } from 'vue'\nimport type { AsideProps } from './types'\n\ndefineOptions({ name: 'WxAside' })\n\nconst props = withDefaults(defineProps<AsideProps>(), {\n width: undefined,\n collapsedWidth: undefined,\n collapsed: false,\n side: 'start',\n bordered: true,\n scroll: false,\n sticky: false,\n floating: false,\n})\n\nconst slots = useSlots()\n\n/*\n * A sidebar with zones is a different column from a sidebar with a menu in it: the\n * middle one grows and scrolls, and the two around it stay where they are. Whether\n * it is one or the other is not a prop — it is whether the caller filled the zones.\n */\nconst zoned = computed(() => slots.top !== undefined || slots.bottom !== undefined)\n\nfunction toLength(value: number | string | undefined) {\n if (value === undefined) return undefined\n return typeof value === 'number' ? `${value}px` : value\n}\n\nconst style = computed(() => {\n const vars: Record<string, string> = {}\n const width = toLength(props.width)\n const collapsedWidth = toLength(props.collapsedWidth)\n if (width) vars['--wx-aside-width'] = width\n if (collapsedWidth) vars['--wx-aside-collapsed-width'] = collapsedWidth\n return vars\n})\n\nconst classes = computed(() => [\n 'wx-aside',\n `wx-aside--${props.side}`,\n {\n 'wx-aside--bordered': props.bordered,\n 'wx-aside--collapsed': props.collapsed,\n 'wx-aside--scroll': props.scroll,\n 'wx-aside--sticky': props.sticky,\n 'wx-aside--floating': props.floating,\n 'wx-aside--zoned': zoned.value,\n },\n])\n</script>\n\n<template>\n <aside :class=\"classes\" :style=\"style\">\n <div v-if=\"$slots.top\" class=\"wx-aside__top\">\n <slot name=\"top\" />\n </div>\n\n <!--\n Wrapped only where there is something to wrap it against. An element between\n the column and its menu is one more thing for a caller's own layout to reckon\n with, and a sidebar that is nothing but a menu has no use for it.\n -->\n <div v-if=\"zoned\" class=\"wx-aside__body\">\n <slot />\n </div>\n\n <slot v-else />\n\n <div v-if=\"$slots.bottom\" class=\"wx-aside__bottom\">\n <slot name=\"bottom\" />\n </div>\n </aside>\n</template>\n\n<style scoped>\n.wx-aside {\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n /* Fixed width, and it never shrinks when the main column is crowded. */\n flex: 0 0 var(--wx-aside-width, 240px);\n width: var(--wx-aside-width, 240px);\n min-height: 0;\n background: var(--wx-bg-surface);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n transition: flex-basis var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n/*\n * The rail is one icon wide plus the air around it — 56px, not the 64 it started\n * at, which left the icons floating in a column of their own.\n */\n.wx-aside--collapsed {\n flex-basis: var(--wx-aside-collapsed-width, 56px);\n width: var(--wx-aside-collapsed-width, 56px);\n}\n\n.wx-aside--bordered.wx-aside--start {\n border-right: 1px solid var(--wx-border-default);\n}\n\n.wx-aside--bordered.wx-aside--end {\n border-left: 1px solid var(--wx-border-default);\n}\n\n/*\n * A sidebar that scrolls on its own sticks to the viewport, so a long menu can be\n * reached while a long page scrolls behind it.\n *\n * `max-height` rather than `height`: the column has to answer to both shapes it is\n * used in. Under a header in a shell that fills the screen it is already the height\n * of its row, and a hard `100dvh` there is a header taller than the window — the\n * whole layout then overflows by exactly the header. On a page that scrolls, the row\n * is as tall as the content, and the cap is what keeps the sticky column in view.\n */\n.wx-aside--scroll:not(.wx-aside--zoned) {\n position: sticky;\n top: 0;\n max-height: 100dvh;\n overflow-y: auto;\n overscroll-behavior: contain;\n}\n\n/* The zones stay; only what is between them moves. */\n.wx-aside__top,\n.wx-aside__bottom {\n flex: 0 0 auto;\n}\n\n.wx-aside__body {\n display: flex;\n flex-direction: column;\n flex: 1 1 auto;\n /* Without this the menu is as tall as its content and nothing ever scrolls. */\n min-height: 0;\n}\n\n/*\n * The menu scrolls when it does not fit, and shows no bar for it. A menu is narrow, and the bar\n * is a sixth of it: kept as room, it stood as a gap on the right of every item even when nothing\n * overflowed; shown, it pushed the icons sideways when a branch opened. The wheel, a finger and\n * the keyboard all still scroll it, and an item brought into focus scrolls into view.\n */\n.wx-aside--zoned.wx-aside--scroll .wx-aside__body {\n overflow-y: auto;\n overscroll-behavior: contain;\n scrollbar-width: none;\n}\n\n.wx-aside--zoned.wx-aside--scroll .wx-aside__body::-webkit-scrollbar {\n display: none;\n}\n\n/*\n * The column stands still and the page moves past it. Its height is its own — it is\n * not the height of a row it shares with the content any more, so it has to be told\n * one, and `100dvh` is the answer unless a shell insets it.\n */\n.wx-aside--sticky {\n position: sticky;\n top: var(--wx-aside-top, 0px);\n height: var(--wx-aside-height, 100dvh);\n}\n\n/*\n * A card rather than a wall. No `overflow` of its own: a rail opens its section\n * names in flyouts beside itself, and a box that clips is a box they cannot leave.\n */\n.wx-aside--floating {\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n box-shadow: var(--wx-shadow-card);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-aside {\n transition: none;\n }\n}\n</style>\n","import { computed, inject, provide, type ComputedRef, type InjectionKey, type Ref } from 'vue'\n\nexport type ControlSize = 'sm' | 'md' | 'lg'\nexport type ControlStatus = 'default' | 'success' | 'warning' | 'error'\n\n/** Field name -> messages, the shape Laravel returns on a 422. */\nexport type ValidationErrors = Record<string, string[]>\n\nexport interface FormContext {\n /** Server-side errors, keyed by field name. */\n errors: Ref<ValidationErrors>\n disabled: Ref<boolean>\n size: Ref<ControlSize>\n labelPosition: Ref<'top' | 'left'>\n labelWidth: Ref<string | undefined>\n}\n\nexport interface FormItemContext {\n /** Id given to the control, so the label's `for` matches. */\n id: ComputedRef<string>\n /** Ids of the help and error nodes, for `aria-describedby`. */\n describedBy: ComputedRef<string | undefined>\n status: ComputedRef<ControlStatus>\n disabled: ComputedRef<boolean>\n size: ComputedRef<ControlSize | undefined>\n /** Set by grouped controls so the label points at the group, not one input. */\n registerLabelTarget: (id: string | undefined) => void\n}\n\nexport const formContextKey: InjectionKey<FormContext> = Symbol('wx-form')\nexport const formItemContextKey: InjectionKey<FormItemContext> = Symbol('wx-form-item')\n\nlet uid = 0\nexport function useId(prefix = 'wx'): string {\n uid += 1\n return `${prefix}-${uid}`\n}\n\nexport interface FormFieldProps {\n disabled?: boolean\n size?: ControlSize\n status?: ControlStatus\n id?: string\n}\n\n/**\n * Resolves what a control should render as, given its own props, the enclosing\n * `WxFormItem` and the enclosing `WxForm`. The control's own prop always wins;\n * `WxFormItem` beats `WxForm`.\n */\nexport function useFormField(props: FormFieldProps) {\n const form = inject(formContextKey, null)\n const item = inject(formItemContextKey, null)\n const fallbackId = useId('wx-control')\n\n const id = computed(() => props.id ?? item?.id.value ?? fallbackId)\n\n const disabled = computed(\n () => props.disabled || item?.disabled.value || form?.disabled.value || false,\n )\n\n const size = computed<ControlSize>(\n () => props.size ?? item?.size.value ?? form?.size.value ?? 'md',\n )\n\n const status = computed<ControlStatus>(() => {\n if (props.status && props.status !== 'default') return props.status\n return item?.status.value ?? 'default'\n })\n\n const describedBy = computed(() => item?.describedBy.value)\n\n return { id, disabled, size, status, describedBy, form, item }\n}\n\n/**\n * What a checkbox, radio or switch may carry. Deliberately narrower than `unknown`:\n * a `v-model` that hands back `unknown` is useless to the caller, and object values\n * would need identity comparison rather than `===`.\n */\nexport type ChoiceValue = string | number | boolean | null\n\n/** Used by `WxCheckboxGroup` / `WxRadioGroup` to share state with their children. */\nexport interface ChoiceGroupContext<T> {\n name: ComputedRef<string | undefined>\n modelValue: Ref<T>\n disabled: ComputedRef<boolean>\n size: ComputedRef<ControlSize>\n toggle: (value: ChoiceValue, checked: boolean) => void\n /**\n * Whether one choice cannot be changed right now — a box left unchecked once a group holds its\n * `max`, a checked one at its `min`. Drawn disabled, rather than a click that does nothing.\n */\n locked?: (value: ChoiceValue) => boolean\n}\n\nexport const checkboxGroupKey: InjectionKey<ChoiceGroupContext<ChoiceValue[]>> =\n Symbol('wx-checkbox-group')\nexport const radioGroupKey: InjectionKey<ChoiceGroupContext<ChoiceValue | undefined>> =\n Symbol('wx-radio-group')\n\nexport function provideFormItem(context: FormItemContext): void {\n provide(formItemContextKey, context)\n}\n","import { computed, useAttrs, type ComputedRef } from 'vue'\n\n/**\n * Splits what the caller wrote on a control between its two halves.\n *\n * Every control here sets `inheritAttrs: false` and hands `$attrs` to the element\n * inside it, so that `placeholder`, `autocomplete`, `data-*` and the ARIA attributes\n * reach the real `<input>` rather than the wrapper around it. Taken literally that\n * sends `class` and `style` there too, and both are then in the wrong place:\n *\n * - The caller means the control, not its input. `class=\"w-60\"` on a `<wx-select>` is\n * asking for a narrower select, and the select is the wrapper.\n * - A parent's scoped CSS cannot reach it. Scoped styles carry an attribute that is\n * stamped on a child component's *root*, so a class that lands three elements deep\n * matches nothing — silently.\n * - And where `$attrs` is bound to an element that is only sometimes rendered — the\n * search field of a filterable `WxSelect` — the class disappears altogether.\n *\n * So `class` and `style` go on the root, and everything else goes on the control.\n *\n * ```ts\n * const { rootAttrs, controlAttrs } = useControlAttrs()\n * ```\n * ```vue\n * <div :class=\"classes\" v-bind=\"rootAttrs\">\n * <input v-bind=\"controlAttrs\" />\n * </div>\n * ```\n */\nexport interface ControlAttrs {\n /** `class` and `style` — for the wrapper the caller can see. */\n rootAttrs: ComputedRef<Record<string, unknown>>\n /** Everything else — for the element the browser focuses and reads out. */\n controlAttrs: ComputedRef<Record<string, unknown>>\n}\n\nexport function useControlAttrs(): ControlAttrs {\n const attrs = useAttrs()\n\n const rootAttrs = computed(() => {\n const picked: Record<string, unknown> = {}\n if (attrs.class !== undefined) picked.class = attrs.class\n if (attrs.style !== undefined) picked.style = attrs.style\n return picked\n })\n\n const controlAttrs = computed(() => {\n const rest: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(attrs)) {\n if (key !== 'class' && key !== 'style') rest[key] = value\n }\n return rest\n })\n\n return { rootAttrs, controlAttrs }\n}\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, ref, watch } from 'vue'\nimport {\n AutocompleteAnchor,\n AutocompleteContent,\n AutocompleteEmpty,\n AutocompleteInput,\n AutocompleteItem,\n AutocompletePortal,\n AutocompleteRoot,\n AutocompleteViewport,\n} from 'reka-ui'\nimport WxIcon from '../Icon/Icon.vue'\nimport { useFormField } from '../../composables/useFormField'\nimport type { AutocompleteEmits, AutocompleteOption, AutocompleteProps } from './types'\nimport { useControlAttrs } from '../../composables/useControlAttrs'\n\ndefineOptions({ name: 'WxAutocomplete', inheritAttrs: false })\n\n/* `class` and `style` belong to the control; the rest belongs to its input. */\nconst { rootAttrs, controlAttrs } = useControlAttrs()\n\nconst props = withDefaults(defineProps<AutocompleteProps>(), {\n options: () => [],\n remote: false,\n debounce: 300,\n loading: false,\n loadingText: 'Searching…',\n emptyText: 'Nothing found',\n minLength: 0,\n placeholder: undefined,\n clearable: false,\n openOnFocus: true,\n teleport: true,\n disabled: undefined,\n size: undefined,\n status: undefined,\n id: undefined,\n name: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<AutocompleteEmits>()\n\n/** The model is the text in the field — an autocomplete suggests, it does not constrain. */\nconst model = defineModel<string>({ default: '' })\n\n/*\n * The text as a string, whatever came in. The default covers a missing value, not a null one —\n * and a record says null for a field it has no text in (a screen's row that reads a setting, then\n * switched to it). Reading `.length` of that threw in render, and Vue drew the root without its\n * input until something else re-rendered it. The model stays typed as text: that is what goes out.\n */\nconst text = computed<string>(() => (model.value as string | null) ?? '')\n\nconst field = useFormField(props)\nconst open = ref(false)\n\nlet debounceTimer: ReturnType<typeof setTimeout> | undefined\n/** Set while a pick is being applied, so choosing a suggestion does not search for it. */\nlet picking = false\n\nfunction cancelSearch() {\n if (debounceTimer === undefined) return\n clearTimeout(debounceTimer)\n debounceTimer = undefined\n}\n\nwatch(text, (value) => {\n emit('change', value)\n\n if (picking) {\n picking = false\n cancelSearch()\n return\n }\n\n cancelSearch()\n if (value.length < props.minLength) {\n open.value = false\n return\n }\n\n debounceTimer = setTimeout(() => {\n debounceTimer = undefined\n emit('search', value)\n }, props.debounce)\n})\n\nwatch(open, (value) => {\n if (value) emit('open')\n else emit('close')\n})\n\nonBeforeUnmount(cancelSearch)\n\nconst showClear = computed(() => props.clearable && !field.disabled.value && text.value.length > 0)\n\n/** Nothing to drop down yet: below `min-length`, or still waiting on the first response. */\nconst hasList = computed(\n () => props.options.length > 0 || props.loading || text.value.length >= props.minLength,\n)\n\nconst classes = computed(() => [\n 'wx-autocomplete',\n `wx-autocomplete--${field.size.value}`,\n {\n [`wx-autocomplete--${field.status.value}`]: field.status.value !== 'default',\n 'is-open': open.value,\n 'is-disabled': field.disabled.value,\n },\n])\n\nfunction onSelect(option: AutocompleteOption) {\n picking = true\n emit('select', option)\n}\n\nfunction clear() {\n picking = true\n model.value = ''\n open.value = false\n emit('clear')\n}\n</script>\n\n<template>\n <autocomplete-root\n v-model=\"model\"\n v-model:open=\"open\"\n as=\"div\"\n :class=\"classes\"\n v-bind=\"rootAttrs\"\n :disabled=\"field.disabled.value\"\n :name=\"name\"\n :ignore-filter=\"remote\"\n :open-on-focus=\"openOnFocus\"\n :open-on-click=\"openOnFocus\"\n >\n <autocomplete-anchor class=\"wx-autocomplete__anchor\" as=\"div\">\n <span v-if=\"$slots.prefix\" class=\"wx-autocomplete__affix\">\n <slot name=\"prefix\" />\n </span>\n\n <autocomplete-input\n :id=\"field.id.value\"\n v-bind=\"controlAttrs\"\n class=\"wx-autocomplete__input\"\n :placeholder=\"placeholder\"\n :disabled=\"field.disabled.value\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"field.describedBy.value\"\n :aria-invalid=\"field.status.value === 'error' || undefined\"\n />\n\n <wx-icon v-if=\"loading\" class=\"wx-autocomplete__spinner\" name=\"loader\" spin />\n\n <button\n v-else-if=\"showClear\"\n class=\"wx-autocomplete__clear\"\n type=\"button\"\n tabindex=\"-1\"\n aria-label=\"Clear\"\n @click=\"clear\"\n >\n <wx-icon name=\"close\" />\n </button>\n\n <span v-if=\"$slots.suffix\" class=\"wx-autocomplete__affix\">\n <slot name=\"suffix\" />\n </span>\n </autocomplete-anchor>\n\n <autocomplete-portal :disabled=\"!teleport\">\n <autocomplete-content\n v-if=\"hasList\"\n class=\"wx-autocomplete__content\"\n position=\"popper\"\n :side-offset=\"4\"\n >\n <autocomplete-viewport class=\"wx-autocomplete__viewport\">\n <div v-if=\"loading && options.length === 0\" class=\"wx-autocomplete__status\">\n {{ loadingText }}\n </div>\n <autocomplete-empty v-else class=\"wx-autocomplete__status\">\n {{ emptyText }}\n </autocomplete-empty>\n\n <autocomplete-item\n v-for=\"option in options\"\n :key=\"option.value\"\n class=\"wx-autocomplete__option\"\n :value=\"option.value\"\n :disabled=\"option.disabled\"\n @select=\"onSelect(option)\"\n >\n <slot name=\"option\" :option=\"option\">\n <span class=\"wx-autocomplete__option-label\">{{ option.label ?? option.value }}</span>\n <span v-if=\"option.description\" class=\"wx-autocomplete__option-description\">\n {{ option.description }}\n </span>\n </slot>\n </autocomplete-item>\n </autocomplete-viewport>\n </autocomplete-content>\n </autocomplete-portal>\n </autocomplete-root>\n</template>\n\n<style scoped>\n.wx-autocomplete {\n display: block;\n width: 100%;\n}\n\n.wx-autocomplete__anchor {\n display: flex;\n align-items: center;\n gap: var(--wx-space-6);\n box-sizing: border-box;\n height: var(--wx-size-control-md);\n padding: 0 var(--wx-space-10) 0 var(--wx-space-12);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-control);\n color: var(--wx-text-default);\n font-size: var(--wx-font-size-control-md);\n transition: border-color var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-autocomplete--sm .wx-autocomplete__anchor {\n height: var(--wx-size-control-sm);\n font-size: var(--wx-font-size-control-sm);\n}\n\n.wx-autocomplete--lg .wx-autocomplete__anchor {\n height: var(--wx-size-control-lg);\n font-size: var(--wx-font-size-control-lg);\n}\n\n.wx-autocomplete__anchor:hover {\n border-color: var(--wx-border-strong);\n}\n\n.wx-autocomplete.is-open .wx-autocomplete__anchor,\n.wx-autocomplete__anchor:focus-within {\n border-color: var(--wx-border-focus);\n}\n\n.wx-autocomplete--error .wx-autocomplete__anchor,\n.wx-autocomplete--error.is-open .wx-autocomplete__anchor {\n border-color: var(--wx-color-danger);\n}\n\n.wx-autocomplete--success .wx-autocomplete__anchor {\n border-color: var(--wx-color-success);\n}\n\n.wx-autocomplete--warning .wx-autocomplete__anchor {\n border-color: var(--wx-color-warning);\n}\n\n.wx-autocomplete.is-disabled .wx-autocomplete__anchor {\n background: var(--wx-bg-disabled);\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n.wx-autocomplete__input {\n flex: 1 1 auto;\n min-width: 0;\n height: 100%;\n padding: 0;\n background: transparent;\n border: none;\n outline: none;\n color: inherit;\n font-family: inherit;\n font-size: inherit;\n}\n\n.wx-autocomplete__input::placeholder {\n color: var(--wx-text-placeholder);\n}\n\n.wx-autocomplete__input:disabled {\n cursor: not-allowed;\n}\n\n.wx-autocomplete__affix,\n.wx-autocomplete__spinner {\n display: inline-flex;\n align-items: center;\n flex: 0 0 auto;\n color: var(--wx-text-muted);\n}\n\n.wx-autocomplete__clear {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 20px;\n height: 20px;\n padding: 0;\n background: transparent;\n border: none;\n border-radius: var(--wx-radius-full);\n color: var(--wx-text-muted);\n cursor: pointer;\n}\n\n.wx-autocomplete__clear:hover {\n color: var(--wx-text-default);\n}\n</style>\n\n<style>\n/* The list is teleported, so its styles cannot be scoped to the component. */\n.wx-autocomplete__content {\n /* One layer for every floating panel, so the one opened last is the one on top. */\n z-index: var(--wx-z-index-popover);\n box-sizing: border-box;\n width: var(--reka-combobox-trigger-width);\n max-height: 300px;\n padding: var(--wx-space-4);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-sm);\n box-shadow: var(--wx-shadow-popover);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n font-size: var(--wx-font-size-control-md);\n overflow: hidden;\n}\n\n.wx-autocomplete__viewport {\n max-height: 292px;\n overflow-y: auto;\n}\n\n.wx-autocomplete__option {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: var(--wx-space-6) var(--wx-space-10);\n border-radius: var(--wx-radius-xs);\n cursor: pointer;\n user-select: none;\n}\n\n.wx-autocomplete__option[data-highlighted] {\n background: var(--wx-bg-fill);\n outline: none;\n}\n\n.wx-autocomplete__option[data-disabled] {\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n.wx-autocomplete__option-label {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wx-autocomplete__option-description {\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n line-height: var(--wx-font-line-height-normal);\n}\n\n.wx-autocomplete__status {\n padding: var(--wx-space-10);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n text-align: center;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport type { AvatarEmits, AvatarProps, AvatarTone } from './types'\n\ndefineOptions({ name: 'WxAvatar' })\n\nconst props = withDefaults(defineProps<AvatarProps>(), {\n src: undefined,\n alt: undefined,\n name: undefined,\n icon: undefined,\n size: 'md',\n shape: 'circle',\n tone: 'auto',\n fit: 'cover',\n})\n\nconst emit = defineEmits<AvatarEmits>()\n\n/** The tints `auto` chooses between. The order is the answer, so it stays put. */\nconst TONES: Exclude<AvatarTone, 'auto'>[] = [\n 'primary',\n 'success',\n 'warning',\n 'danger',\n 'info',\n 'neutral',\n]\n\n/**\n * Two letters out of a name: the first of the first word and the first of the last.\n * One word gives its first two, so `Nova` is `NO` rather than a lonely `N`.\n */\nfunction initialsOf(name: string) {\n const words = name.trim().split(/\\s+/).filter(Boolean)\n if (words.length === 0) return ''\n if (words.length === 1) return [...words[0]].slice(0, 2).join('').toUpperCase()\n return ([...words[0]][0] + [...words[words.length - 1]][0]).toUpperCase()\n}\n\n/**\n * A number from the name, so the same person keeps the same colour everywhere —\n * across pages, across reloads, and on somebody else's screen.\n */\nfunction hash(value: string) {\n let total = 0\n for (const character of value) total = (total * 31 + character.codePointAt(0)!) % 1_000_003\n return total\n}\n\nconst initials = computed(() => (props.name ? initialsOf(props.name) : ''))\n\nconst tone = computed<Exclude<AvatarTone, 'auto'>>(() => {\n if (props.tone !== 'auto') return props.tone\n if (!props.name) return 'neutral'\n return TONES[hash(props.name) % TONES.length]\n})\n\nconst failed = ref(false)\n\n/* A new picture deserves its own chance; the last one's failure is not its fault. */\nwatch(\n () => props.src,\n () => {\n failed.value = false\n },\n)\n\nfunction onError(event: Event) {\n failed.value = true\n emit('error', event)\n}\n\nconst classes = computed(() => [\n 'wx-avatar',\n `wx-avatar--${props.size}`,\n `wx-avatar--${props.shape}`,\n `wx-avatar--${tone.value}`,\n])\n\n/*\n * The fallback is always in the markup and the picture lies on top of it. A picture\n * that is still arriving is a transparent box, so the initials show through and are\n * covered the moment it lands — no flash of one followed by the other, and no timer\n * deciding how long to wait before admitting there is nothing to show.\n */\n</script>\n\n<template>\n <span :class=\"classes\">\n <span class=\"wx-avatar__fallback\">\n <slot>\n <wx-icon v-if=\"icon\" :name=\"icon\" />\n <span v-else-if=\"initials\" class=\"wx-avatar__initials\">{{ initials }}</span>\n <wx-icon v-else name=\"user\" />\n </slot>\n </span>\n\n <img\n v-if=\"src && !failed\"\n class=\"wx-avatar__image\"\n :src=\"src\"\n :alt=\"alt ?? name ?? ''\"\n :style=\"{ objectFit: fit }\"\n @error=\"onError\"\n />\n </span>\n</template>\n\n<style scoped>\n.wx-avatar {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n flex: 0 0 auto;\n width: var(--wx-avatar-size);\n height: var(--wx-avatar-size);\n overflow: hidden;\n background: var(--wx-avatar-bg);\n color: var(--wx-avatar-fg);\n font-family: var(--wx-font-family-sans);\n font-size: var(--wx-avatar-text);\n font-weight: var(--wx-font-weight-semibold);\n line-height: 1;\n /* Initials are read, not selected. */\n user-select: none;\n vertical-align: middle;\n}\n\n.wx-avatar--xs {\n --wx-avatar-size: 20px;\n --wx-avatar-text: 9px;\n}\n\n.wx-avatar--sm {\n --wx-avatar-size: 26px;\n --wx-avatar-text: var(--wx-font-size-xs);\n}\n\n.wx-avatar--md {\n --wx-avatar-size: 32px;\n --wx-avatar-text: var(--wx-font-size-xs);\n}\n\n.wx-avatar--lg {\n --wx-avatar-size: 40px;\n --wx-avatar-text: var(--wx-font-size-sm);\n}\n\n.wx-avatar--xl {\n --wx-avatar-size: 56px;\n --wx-avatar-text: var(--wx-font-size-lg);\n}\n\n.wx-avatar--circle {\n border-radius: var(--wx-radius-full);\n}\n\n.wx-avatar--square {\n border-radius: var(--wx-radius-xs);\n}\n\n.wx-avatar--neutral {\n --wx-avatar-bg: var(--wx-bg-fill);\n --wx-avatar-fg: var(--wx-text-muted);\n}\n\n.wx-avatar--primary {\n --wx-avatar-bg: var(--wx-color-primary-soft);\n --wx-avatar-fg: var(--wx-color-primary);\n}\n\n.wx-avatar--success {\n --wx-avatar-bg: var(--wx-color-success-soft);\n --wx-avatar-fg: var(--wx-color-success-active);\n}\n\n.wx-avatar--warning {\n --wx-avatar-bg: var(--wx-color-warning-soft);\n --wx-avatar-fg: var(--wx-color-warning-active);\n}\n\n.wx-avatar--danger {\n --wx-avatar-bg: var(--wx-color-danger-soft);\n --wx-avatar-fg: var(--wx-color-danger);\n}\n\n.wx-avatar--info {\n --wx-avatar-bg: var(--wx-color-info-soft);\n --wx-avatar-fg: var(--wx-color-info-active);\n}\n\n.wx-avatar__fallback {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n}\n\n.wx-avatar__image {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n /* Inherits the circle from the box it fills, so a photograph is not a square. */\n border-radius: inherit;\n}\n\n/* The glyph is sized against the circle rather than against the initials. */\n.wx-avatar__fallback :deep(.wx-icon) {\n width: 60%;\n height: 60%;\n}\n</style>\n","import {\n Comment,\n Fragment,\n Text,\n cloneVNode,\n defineComponent,\n type PropType,\n type VNode,\n} from 'vue'\n\n/**\n * The children a slot was given, as a flat list, so they can be counted and split —\n * the entries a menu bar has no room for, the avatars a group shows past its limit.\n *\n * A `v-for` arrives as one fragment holding many entries, and a `v-if` that is false\n * arrives as a comment. Both have to go: the list is lined up index for index against\n * the `<li>` elements the browser actually laid out, and a comment is not one.\n */\nexport function flattenNodes(nodes: VNode[]): VNode[] {\n return nodes.flatMap((node) => {\n if (node.type === Fragment) return flattenNodes((node.children ?? []) as VNode[])\n if (node.type === Comment || node.type === Text) return []\n return [node]\n })\n}\n\n/**\n * Renders vnodes that have already been created — the two halves of a split slot.\n *\n * It exists because a template can render a slot but not a slice of one, and the\n * children must be rendered *once*: an entry that appeared in both halves would\n * register itself twice and report the wrong branch to the menu above it.\n *\n * The vnodes are cloned on the way out, and that is not a nicety. A vnode belongs to\n * the place it was mounted, and a slice that moves between two of them — the bar and\n * the overflow branch — would be asking Vue to mount the same one twice. Vue does this\n * cloning itself for a slot rendered in a template; vnodes handed along as a prop skip\n * that path. In a development build the compiler hands back a fresh vnode per render\n * and the reuse never shows; in a production build an entry with nothing dynamic about\n * it is cached and handed back as the very same object, and the second place it is\n * rendered comes out empty. That was an open, empty \"More\" on a phone, and nothing at\n * all in dev.\n */\nexport const WxNodes = defineComponent({\n name: 'WxNodes',\n props: {\n nodes: { type: Array as PropType<VNode[]>, required: true },\n },\n setup(props) {\n return () => props.nodes.map((node) => cloneVNode(node))\n },\n})\n","<script setup lang=\"ts\">\nimport { computed, useSlots, type VNode } from 'vue'\nimport WxAvatar from '../Avatar/Avatar.vue'\nimport { flattenNodes, WxNodes } from '../../internal/nodes'\nimport type { AvatarGroupProps } from './types'\n\ndefineOptions({ name: 'WxAvatarGroup' })\n\nconst props = withDefaults(defineProps<AvatarGroupProps>(), {\n max: 0,\n size: 'md',\n shape: 'circle',\n overlap: 0.3,\n})\n\nconst slots = useSlots()\n\n/*\n * The avatars are split rather than hidden, for the same reason the menu bar splits\n * its entries: what is over the limit is not rendered at all, so eight hundred people\n * in a room cost three avatars and a number.\n */\nconst avatars = computed<VNode[]>(() => flattenNodes(slots.default?.() ?? []))\n\nconst shown = computed(() => (props.max > 0 ? avatars.value.slice(0, props.max) : avatars.value))\n\nconst hidden = computed(() => Math.max(0, avatars.value.length - shown.value.length))\n\nconst style = computed(() => ({\n '--wx-avatar-group-overlap': `${-props.overlap}em`,\n}))\n</script>\n\n<template>\n <div class=\"wx-avatar-group\" :class=\"`wx-avatar-group--${size}`\" :style=\"style\">\n <wx-nodes :nodes=\"shown\" />\n\n <wx-avatar\n v-if=\"hidden > 0\"\n class=\"wx-avatar-group__rest\"\n :size=\"size\"\n :shape=\"shape\"\n tone=\"neutral\"\n :name=\"`+${hidden}`\"\n >\n +{{ hidden }}\n </wx-avatar>\n </div>\n</template>\n\n<style scoped>\n.wx-avatar-group {\n display: inline-flex;\n align-items: center;\n vertical-align: middle;\n}\n\n/*\n * The overlap is stated in `em` against the avatar's own text size, so a row of\n * large avatars overlaps proportionally rather than by a number chosen for small\n * ones. The ring is the page behind them, which is what makes the stack read as a\n * stack rather than as one wide smudge.\n */\n.wx-avatar-group :deep(.wx-avatar) {\n box-shadow: 0 0 0 2px var(--wx-bg-surface);\n}\n\n.wx-avatar-group :deep(.wx-avatar:not(:first-child)) {\n margin-inline-start: var(--wx-avatar-group-overlap, -0.3em);\n}\n\n.wx-avatar-group--xs {\n font-size: 20px;\n}\n\n.wx-avatar-group--sm {\n font-size: 26px;\n}\n\n.wx-avatar-group--md {\n font-size: 32px;\n}\n\n.wx-avatar-group--lg {\n font-size: 40px;\n}\n\n.wx-avatar-group--xl {\n font-size: 56px;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref } from 'vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport type { BacktopProps } from './types'\n\ndefineOptions({ name: 'WxBacktop' })\n\n/*\n * The scrolling thing is named rather than assumed. In an admin the page rarely\n * scrolls — the main column does — so a control that only ever listens to the window\n * would be a button that appears when nothing has happened and does nothing when\n * pressed.\n */\nconst props = withDefaults(defineProps<BacktopProps>(), {\n target: undefined,\n visibilityHeight: 200,\n right: 24,\n bottom: 24,\n smooth: true,\n ariaLabel: 'Back to top',\n})\n\nconst emit = defineEmits<{ click: [event: MouseEvent] }>()\n\ndefineSlots<{ default?: () => unknown }>()\n\nconst visible = ref(false)\n\nfunction scroller(): HTMLElement | Window | null {\n if (typeof document === 'undefined') return null\n if (!props.target) return window\n return typeof props.target === 'string'\n ? document.querySelector<HTMLElement>(props.target)\n : (props.target ?? null)\n}\n\nfunction offsetOf(element: HTMLElement | Window) {\n return element === window ? window.scrollY : (element as HTMLElement).scrollTop\n}\n\nfunction onScroll() {\n const element = scroller()\n if (!element) return\n visible.value = offsetOf(element) > props.visibilityHeight\n}\n\nfunction toTop(event: MouseEvent) {\n const element = scroller()\n if (!element) return\n\n element.scrollTo({ top: 0, behavior: props.smooth ? 'smooth' : 'auto' })\n emit('click', event)\n}\n\nlet watched: HTMLElement | Window | null = null\n\nonMounted(() => {\n watched = scroller()\n watched?.addEventListener('scroll', onScroll, { passive: true })\n onScroll()\n})\n\nonBeforeUnmount(() => {\n watched?.removeEventListener('scroll', onScroll)\n watched = null\n})\n\nconst style = computed(() => ({\n insetInlineEnd: `${props.right}px`,\n bottom: `${props.bottom}px`,\n}))\n</script>\n\n<template>\n <Transition name=\"wx-backtop\">\n <button\n v-if=\"visible\"\n type=\"button\"\n class=\"wx-backtop\"\n :style=\"style\"\n :aria-label=\"ariaLabel\"\n @click=\"toTop\"\n >\n <slot>\n <wx-icon name=\"arrow-up\" />\n </slot>\n </button>\n </Transition>\n</template>\n\n<style scoped>\n.wx-backtop {\n position: fixed;\n z-index: var(--wx-z-index-sticky);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n padding: 0;\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-full);\n box-shadow: var(--wx-shadow-popover);\n color: var(--wx-text-muted);\n cursor: pointer;\n transition:\n color var(--wx-duration-fast) var(--wx-easing-standard),\n transform var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-backtop:hover {\n color: var(--wx-color-primary);\n transform: translateY(-2px);\n}\n\n.wx-backtop:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-backtop-enter-active,\n.wx-backtop-leave-active {\n transition:\n opacity var(--wx-duration-fast) var(--wx-easing-standard),\n transform var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-backtop-enter-from,\n.wx-backtop-leave-to {\n opacity: 0;\n transform: translateY(8px);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-backtop,\n .wx-backtop-enter-active,\n .wx-backtop-leave-active {\n transition: none;\n }\n\n .wx-backtop:hover {\n transform: none;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport type { BadgeEmits, BadgeProps } from './types'\n\ndefineOptions({ name: 'WxBadge' })\n\nconst props = withDefaults(defineProps<BadgeProps>(), {\n type: 'default',\n variant: 'soft',\n size: 'md',\n round: false,\n dot: false,\n closable: false,\n closeLabel: 'Remove',\n})\n\nconst emit = defineEmits<BadgeEmits>()\n\nconst classes = computed(() => [\n 'wx-badge',\n `wx-badge--${props.type}`,\n `wx-badge--${props.variant}`,\n `wx-badge--${props.size}`,\n {\n 'wx-badge--round': props.round,\n 'wx-badge--closable': props.closable,\n },\n])\n</script>\n\n<template>\n <span :class=\"classes\">\n <span v-if=\"dot\" class=\"wx-badge__dot\" aria-hidden=\"true\" />\n <span v-if=\"$slots.icon\" class=\"wx-badge__icon\">\n <slot name=\"icon\" />\n </span>\n <span class=\"wx-badge__label\">\n <slot />\n </span>\n <button\n v-if=\"closable\"\n class=\"wx-badge__close\"\n type=\"button\"\n :aria-label=\"closeLabel\"\n @click=\"emit('close', $event)\"\n >\n <wx-icon name=\"close\" />\n </button>\n </span>\n</template>\n\n<style scoped>\n.wx-badge {\n display: inline-flex;\n align-items: center;\n gap: var(--wx-space-4);\n box-sizing: border-box;\n max-width: 100%;\n border: 1px solid transparent;\n border-radius: var(--wx-radius-xs);\n font-family: inherit;\n font-weight: var(--wx-font-weight-medium);\n line-height: var(--wx-font-line-height-tight);\n white-space: nowrap;\n vertical-align: middle;\n}\n\n/* sizes */\n.wx-badge--sm {\n padding: 1px var(--wx-space-6);\n font-size: var(--wx-font-size-xs);\n}\n\n.wx-badge--md {\n padding: 3px var(--wx-space-8);\n font-size: var(--wx-font-size-xs);\n}\n\n.wx-badge--lg {\n padding: 5px var(--wx-space-10);\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-badge--round {\n border-radius: var(--wx-radius-full);\n}\n\n/* Each type names its colours once; the variants below stay type-agnostic. */\n.wx-badge--default {\n --wx-badge-accent: var(--wx-text-muted);\n --wx-badge-soft: var(--wx-bg-fill);\n --wx-badge-solid: var(--wx-bg-inverse);\n --wx-badge-contrast: var(--wx-text-inverse);\n --wx-badge-border: var(--wx-border-default);\n}\n\n.wx-badge--primary {\n --wx-badge-accent: var(--wx-color-primary);\n --wx-badge-soft: var(--wx-color-primary-soft);\n --wx-badge-solid: var(--wx-color-primary);\n --wx-badge-contrast: var(--wx-color-primary-contrast);\n --wx-badge-border: var(--wx-color-primary);\n}\n\n.wx-badge--success {\n --wx-badge-accent: var(--wx-color-success-active);\n --wx-badge-soft: var(--wx-color-success-soft);\n --wx-badge-solid: var(--wx-color-success);\n --wx-badge-contrast: var(--wx-color-success-contrast);\n --wx-badge-border: var(--wx-color-success);\n}\n\n.wx-badge--warning {\n --wx-badge-accent: var(--wx-color-warning-active);\n --wx-badge-soft: var(--wx-color-warning-soft);\n --wx-badge-solid: var(--wx-color-warning);\n --wx-badge-contrast: var(--wx-color-warning-contrast);\n --wx-badge-border: var(--wx-color-warning);\n}\n\n.wx-badge--danger {\n --wx-badge-accent: var(--wx-color-danger);\n --wx-badge-soft: var(--wx-color-danger-soft);\n --wx-badge-solid: var(--wx-color-danger);\n --wx-badge-contrast: var(--wx-color-danger-contrast);\n --wx-badge-border: var(--wx-color-danger);\n}\n\n.wx-badge--info {\n --wx-badge-accent: var(--wx-color-info-active);\n --wx-badge-soft: var(--wx-color-info-soft);\n --wx-badge-solid: var(--wx-color-info);\n --wx-badge-contrast: var(--wx-color-info-contrast);\n --wx-badge-border: var(--wx-color-info);\n}\n\n/* variants */\n.wx-badge--soft {\n background: var(--wx-badge-soft);\n color: var(--wx-badge-accent);\n}\n\n.wx-badge--solid {\n background: var(--wx-badge-solid);\n color: var(--wx-badge-contrast);\n}\n\n.wx-badge--outline {\n background: transparent;\n border-color: var(--wx-badge-border);\n color: var(--wx-badge-accent);\n}\n\n.wx-badge__dot {\n width: 6px;\n height: 6px;\n flex: 0 0 auto;\n background: currentcolor;\n border-radius: var(--wx-radius-full);\n}\n\n.wx-badge__icon {\n display: inline-flex;\n align-items: center;\n}\n\n.wx-badge__label {\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.wx-badge__close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n /* Keeps the badge from growing taller than its text. */\n margin-right: -2px;\n padding: 0;\n /* The cross is as big as the words it stands beside, which is a twelve-pixel target: what\n is drawn stays that size and what can be pressed grows around it. Four pixels and not\n more, because badges sit six apart and a bigger reach would take its neighbour's. */\n position: relative;\n background: transparent;\n border: none;\n border-radius: var(--wx-radius-full);\n color: inherit;\n font-size: 1em;\n line-height: 1;\n opacity: 0.65;\n cursor: pointer;\n}\n\n.wx-badge__close::after {\n content: '';\n position: absolute;\n inset: -4px;\n}\n\n.wx-badge__close:hover {\n opacity: 1;\n}\n\n.wx-badge__close:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n</style>\n","import { inject, type ComputedRef, type InjectionKey } from 'vue'\nimport type { IconName } from '../components/Icon/types'\n\nexport type BreadcrumbSize = 'sm' | 'md'\n\n/** What `WxBreadcrumb` hands down to the items inside it. */\nexport interface BreadcrumbContext {\n /** The character drawn between items. */\n separator: ComputedRef<string>\n /** An icon drawn instead of that character. */\n separatorIcon: ComputedRef<IconName | undefined>\n size: ComputedRef<BreadcrumbSize>\n}\n\nexport const breadcrumbKey: InjectionKey<BreadcrumbContext> = Symbol('wx-breadcrumb')\n\nexport function useBreadcrumb(): BreadcrumbContext | null {\n return inject(breadcrumbKey, null)\n}\n","<script setup lang=\"ts\">\nimport { computed, provide } from 'vue'\nimport { breadcrumbKey } from '../../composables/useBreadcrumb'\nimport type { BreadcrumbProps } from './types'\n\ndefineOptions({ name: 'WxBreadcrumb' })\n\nconst props = withDefaults(defineProps<BreadcrumbProps>(), {\n separator: '/',\n separatorIcon: undefined,\n size: 'md',\n label: 'Breadcrumb',\n})\n\nprovide(breadcrumbKey, {\n separator: computed(() => props.separator),\n separatorIcon: computed(() => props.separatorIcon),\n size: computed(() => props.size),\n})\n</script>\n\n<template>\n <nav class=\"wx-breadcrumb\" :class=\"`wx-breadcrumb--${size}`\" :aria-label=\"label\">\n <!-- An ordered list, because a trail read out of order is not a trail. -->\n <ol class=\"wx-breadcrumb__list\">\n <slot />\n </ol>\n </nav>\n</template>\n\n<style scoped>\n.wx-breadcrumb {\n color: var(--wx-text-muted);\n font-family: var(--wx-font-family-sans);\n font-size: var(--wx-font-size-sm);\n line-height: var(--wx-font-line-height-tight);\n}\n\n.wx-breadcrumb--sm {\n font-size: var(--wx-font-size-xs);\n}\n\n.wx-breadcrumb__list {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-6);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport { useBreadcrumb } from '../../composables/useBreadcrumb'\nimport type { BreadcrumbItemEmits, BreadcrumbItemProps } from './types'\n\ndefineOptions({ name: 'WxBreadcrumbItem', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<BreadcrumbItemProps>(), {\n href: undefined,\n target: undefined,\n as: undefined,\n icon: undefined,\n current: undefined,\n})\n\nconst emit = defineEmits<BreadcrumbItemEmits>()\n\nconst breadcrumb = useBreadcrumb()\n\nconst isLink = computed(() => Boolean(props.href || props.as))\n\n/*\n * A crumb that links nowhere is where you already are. Saying so with `aria-current`\n * is the whole reason a screen reader can tell the trail from a row of links.\n */\nconst isCurrent = computed(() => props.current ?? !isLink.value)\n\nconst tag = computed(() => props.as ?? (props.href ? 'a' : 'span'))\n\nconst linkAttrs = computed(() => {\n const attrs: Record<string, unknown> = {}\n if (props.href) attrs.href = props.href\n if (props.target) attrs.target = props.target\n if (props.target === '_blank') attrs.rel = 'noopener noreferrer'\n if (isCurrent.value) attrs['aria-current'] = 'page'\n return attrs\n})\n\nconst separatorIcon = computed(() => breadcrumb?.separatorIcon.value)\nconst separator = computed(() => breadcrumb?.separator.value ?? '/')\n</script>\n\n<template>\n <li class=\"wx-breadcrumb-item\" :class=\"{ 'is-current': isCurrent }\">\n <component\n :is=\"tag\"\n v-bind=\"{ ...linkAttrs, ...$attrs }\"\n class=\"wx-breadcrumb-item__link\"\n @click=\"emit('click', $event)\"\n >\n <wx-icon v-if=\"icon\" class=\"wx-breadcrumb-item__icon\" :name=\"icon\" />\n <slot />\n </component>\n\n <!--\n The separator belongs to the item before it, and the stylesheet drops it on the\n last one — which is the only way an item can know it is last without the list\n counting its children.\n -->\n <span class=\"wx-breadcrumb-item__separator\" aria-hidden=\"true\">\n <wx-icon v-if=\"separatorIcon\" :name=\"separatorIcon\" />\n <template v-else>{{ separator }}</template>\n </span>\n </li>\n</template>\n\n<style scoped>\n.wx-breadcrumb-item {\n display: inline-flex;\n align-items: center;\n gap: var(--wx-space-6);\n min-width: 0;\n /*\n * The crumb owns its margins. A host stylesheet that spaces list items — VitePress\n * puts 8px between every `li + li`, and a CMS theme will have its own — otherwise\n * walks the trail down the page like a staircase.\n */\n margin: 0;\n}\n\n.wx-breadcrumb-item__link {\n display: inline-flex;\n align-items: center;\n gap: var(--wx-space-4);\n min-width: 0;\n padding: 0;\n background: none;\n border: 0;\n border-radius: var(--wx-radius-xs);\n color: inherit;\n font: inherit;\n text-decoration: none;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\na.wx-breadcrumb-item__link,\nbutton.wx-breadcrumb-item__link {\n cursor: pointer;\n transition: color var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\na.wx-breadcrumb-item__link:hover,\nbutton.wx-breadcrumb-item__link:hover {\n color: var(--wx-text-link);\n}\n\n.wx-breadcrumb-item__link:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-breadcrumb-item.is-current .wx-breadcrumb-item__link {\n color: var(--wx-text-default);\n font-weight: var(--wx-font-weight-medium);\n cursor: default;\n}\n\n.wx-breadcrumb-item__icon {\n flex: 0 0 auto;\n opacity: 0.9;\n}\n\n.wx-breadcrumb-item__separator {\n display: inline-flex;\n align-items: center;\n color: var(--wx-text-placeholder);\n user-select: none;\n}\n\n.wx-breadcrumb-item:last-child .wx-breadcrumb-item__separator {\n display: none;\n}\n</style>\n","import { inject, type ComputedRef, type InjectionKey } from 'vue'\nimport type { ButtonSize, ButtonType, ButtonVariant } from '../components/Button/types'\n\n/**\n * What a `WxButtonGroup` hands down to the buttons inside it. Every field is\n * optional: a button's own prop always wins, the group only fills the gaps.\n */\nexport interface ButtonGroupContext {\n type: ComputedRef<ButtonType | undefined>\n variant: ComputedRef<ButtonVariant | undefined>\n size: ComputedRef<ButtonSize | undefined>\n disabled: ComputedRef<boolean>\n vertical: ComputedRef<boolean>\n}\n\nexport const buttonGroupKey: InjectionKey<ButtonGroupContext> = Symbol('wx-button-group')\n\nexport function useButtonGroup(): ButtonGroupContext | null {\n return inject(buttonGroupKey, null)\n}\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport { useButtonGroup } from '../../composables/useButtonGroup'\nimport type { ButtonEmits, ButtonProps } from './types'\n\ndefineOptions({ name: 'WxButton', inheritAttrs: false })\n\n/*\n * The look defaults to `undefined` rather than to its documented value: inside a\n * `WxButtonGroup` the button has to tell \"caller said default\" from \"caller said\n * nothing\", and a prop default would erase that difference.\n */\nconst props = withDefaults(defineProps<ButtonProps>(), {\n type: undefined,\n icon: undefined,\n variant: undefined,\n size: undefined,\n disabled: false,\n loading: false,\n block: false,\n round: false,\n href: undefined,\n target: undefined,\n nativeType: 'button',\n})\n\nconst emit = defineEmits<ButtonEmits>()\n\nconst group = useButtonGroup()\n\nconst type = computed(() => props.type ?? group?.type.value ?? 'default')\nconst variant = computed(() => props.variant ?? group?.variant.value ?? 'solid')\nconst size = computed(() => props.size ?? group?.size.value ?? 'md')\n\nconst isDisabled = computed(() => props.disabled || props.loading || group?.disabled.value || false)\nconst tag = computed(() => (props.href ? 'a' : 'button'))\n\nconst classes = computed(() => [\n 'wx-button',\n `wx-button--${type.value}`,\n `wx-button--${variant.value}`,\n `wx-button--${size.value}`,\n {\n 'wx-button--block': props.block,\n 'wx-button--round': props.round,\n 'wx-button--loading': props.loading,\n 'is-disabled': isDisabled.value,\n },\n])\n\nconst nativeAttrs = computed(() =>\n props.href\n ? {\n href: isDisabled.value ? undefined : props.href,\n target: props.target,\n role: 'button',\n 'aria-disabled': isDisabled.value ? 'true' : undefined,\n tabindex: isDisabled.value ? -1 : undefined,\n }\n : {\n type: props.nativeType,\n disabled: isDisabled.value,\n },\n)\n\nfunction onClick(event: MouseEvent) {\n if (isDisabled.value) {\n event.preventDefault()\n event.stopPropagation()\n return\n }\n emit('click', event)\n}\n</script>\n\n<template>\n <component\n :is=\"tag\"\n v-bind=\"{ ...nativeAttrs, ...$attrs }\"\n :class=\"classes\"\n :aria-busy=\"loading || undefined\"\n @click=\"onClick\"\n >\n <span v-if=\"loading\" class=\"wx-button__spinner\" aria-hidden=\"true\" />\n <span v-else-if=\"icon || $slots.icon\" class=\"wx-button__icon\">\n <slot name=\"icon\">\n <wx-icon v-if=\"icon\" :name=\"icon\" />\n </slot>\n </span>\n <span v-if=\"$slots.default\" class=\"wx-button__label\">\n <slot />\n </span>\n </component>\n</template>\n\n<style scoped>\n.wx-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--wx-space-8);\n box-sizing: border-box;\n border: 1px solid transparent;\n border-radius: var(--wx-radius-control);\n font-family: inherit;\n font-weight: var(--wx-font-weight-semibold);\n line-height: var(--wx-font-line-height-tight);\n text-decoration: none;\n white-space: nowrap;\n cursor: pointer;\n user-select: none;\n transition:\n background-color var(--wx-duration-normal) var(--wx-easing-standard),\n border-color var(--wx-duration-normal) var(--wx-easing-standard),\n color var(--wx-duration-normal) var(--wx-easing-standard),\n box-shadow var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-button:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n/* sizes */\n.wx-button--sm {\n height: var(--wx-size-control-sm);\n padding: 0 var(--wx-space-12);\n font-size: var(--wx-font-size-control-sm);\n}\n\n.wx-button--md {\n height: var(--wx-size-control-md);\n padding: 0 var(--wx-space-18);\n font-size: var(--wx-font-size-control-md);\n}\n\n.wx-button--lg {\n height: var(--wx-size-control-lg);\n padding: 0 var(--wx-space-24);\n font-size: var(--wx-font-size-control-lg);\n}\n\n.wx-button--block {\n display: flex;\n width: 100%;\n}\n\n.wx-button--round {\n border-radius: var(--wx-radius-full);\n}\n\n/*\n * Each type exposes its own palette through local variables, so the variant rules\n * below stay type-agnostic.\n */\n.wx-button--default {\n --wx-button-bg: var(--wx-bg-surface);\n --wx-button-bg-hover: var(--wx-bg-fill);\n --wx-button-bg-active: var(--wx-bg-fill-hover);\n --wx-button-bg-disabled: var(--wx-bg-surface);\n --wx-button-fg: var(--wx-text-default);\n --wx-button-border: var(--wx-border-default);\n}\n\n.wx-button--primary {\n --wx-button-bg: var(--wx-color-primary);\n --wx-button-bg-hover: var(--wx-color-primary-hover);\n --wx-button-bg-active: var(--wx-color-primary-active);\n --wx-button-bg-disabled: var(--wx-color-primary-disabled);\n --wx-button-fg: var(--wx-color-primary-contrast);\n --wx-button-border: var(--wx-color-primary);\n --wx-button-accent: var(--wx-color-primary);\n --wx-button-soft: var(--wx-color-primary-soft);\n}\n\n.wx-button--success {\n --wx-button-bg: var(--wx-color-success);\n --wx-button-bg-hover: var(--wx-color-success-hover);\n --wx-button-bg-active: var(--wx-color-success-active);\n --wx-button-bg-disabled: var(--wx-color-success-disabled);\n --wx-button-fg: var(--wx-color-success-contrast);\n --wx-button-border: var(--wx-color-success);\n --wx-button-accent: var(--wx-color-success);\n --wx-button-soft: var(--wx-color-success-soft);\n}\n\n.wx-button--warning {\n --wx-button-bg: var(--wx-color-warning);\n --wx-button-bg-hover: var(--wx-color-warning-hover);\n --wx-button-bg-active: var(--wx-color-warning-active);\n --wx-button-bg-disabled: var(--wx-color-warning-disabled);\n --wx-button-fg: var(--wx-color-warning-contrast);\n --wx-button-border: var(--wx-color-warning);\n --wx-button-accent: var(--wx-color-warning);\n --wx-button-soft: var(--wx-color-warning-soft);\n}\n\n.wx-button--danger {\n --wx-button-bg: var(--wx-color-danger);\n --wx-button-bg-hover: var(--wx-color-danger-hover);\n --wx-button-bg-active: var(--wx-color-danger-active);\n --wx-button-bg-disabled: var(--wx-color-danger-disabled);\n --wx-button-fg: var(--wx-color-danger-contrast);\n --wx-button-border: var(--wx-color-danger);\n --wx-button-accent: var(--wx-color-danger);\n --wx-button-soft: var(--wx-color-danger-soft);\n}\n\n/* solid */\n.wx-button--solid {\n background: var(--wx-button-bg);\n border-color: var(--wx-button-border);\n color: var(--wx-button-fg);\n}\n\n.wx-button--solid:hover:not(.is-disabled) {\n background: var(--wx-button-bg-hover);\n border-color: var(--wx-button-bg-hover);\n}\n\n.wx-button--solid:active:not(.is-disabled) {\n background: var(--wx-button-bg-active);\n border-color: var(--wx-button-bg-active);\n}\n\n.wx-button--solid.is-disabled {\n background: var(--wx-button-bg-disabled);\n border-color: var(--wx-button-bg-disabled);\n}\n\n.wx-button--solid.wx-button--default.is-disabled {\n border-color: var(--wx-border-default);\n color: var(--wx-text-disabled);\n}\n\n/* outline */\n.wx-button--outline {\n background: transparent;\n border-color: var(--wx-button-accent, var(--wx-border-default));\n color: var(--wx-button-accent, var(--wx-text-default));\n}\n\n.wx-button--outline:hover:not(.is-disabled) {\n background: var(--wx-button-soft, var(--wx-bg-fill));\n}\n\n.wx-button--outline:active:not(.is-disabled) {\n border-color: var(--wx-button-bg-active);\n color: var(--wx-button-bg-active);\n}\n\n/*\n * Not `--wx-button-bg-disabled`: for the default type that is the surface colour, which painted\n * a disabled outline button's border and label in the colour of whatever it was sitting on — an\n * invisible button, in both themes. A disabled control still has to be seen to be disabled.\n */\n.wx-button--outline.is-disabled {\n border-color: var(--wx-border-muted);\n color: var(--wx-text-disabled);\n}\n\n/* text */\n.wx-button--text {\n background: transparent;\n border-color: transparent;\n color: var(--wx-button-accent, var(--wx-text-default));\n}\n\n.wx-button--text:hover:not(.is-disabled) {\n background: var(--wx-bg-fill);\n}\n\n.wx-button--text:active:not(.is-disabled) {\n background: var(--wx-bg-fill-hover);\n}\n\n.wx-button--text.is-disabled {\n color: var(--wx-text-disabled);\n}\n\n/* states */\n.wx-button.is-disabled {\n cursor: not-allowed;\n}\n\n.wx-button--loading {\n cursor: progress;\n}\n\n.wx-button__spinner {\n width: 1em;\n height: 1em;\n border: 2px solid currentcolor;\n border-right-color: transparent;\n border-radius: var(--wx-radius-full);\n /* Same pace as a spinning WxIcon — a turn a second, not three. */\n animation: wx-button-spin var(--wx-button-spin-duration, 1s) linear infinite;\n}\n\n.wx-button__icon {\n display: inline-flex;\n align-items: center;\n}\n\n@keyframes wx-button-spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-button {\n transition: none;\n }\n\n .wx-button__spinner {\n animation-duration: 2s;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, provide } from 'vue'\nimport { buttonGroupKey } from '../../composables/useButtonGroup'\nimport type { ButtonGroupProps } from './types'\n\ndefineOptions({ name: 'WxButtonGroup' })\n\nconst props = withDefaults(defineProps<ButtonGroupProps>(), {\n type: undefined,\n variant: undefined,\n size: undefined,\n disabled: false,\n vertical: false,\n attached: true,\n ariaLabel: undefined,\n})\n\nprovide(buttonGroupKey, {\n type: computed(() => props.type),\n variant: computed(() => props.variant),\n size: computed(() => props.size),\n disabled: computed(() => props.disabled),\n vertical: computed(() => props.vertical),\n})\n\nconst classes = computed(() => [\n 'wx-button-group',\n {\n 'wx-button-group--vertical': props.vertical,\n 'wx-button-group--attached': props.attached,\n },\n])\n</script>\n\n<template>\n <div :class=\"classes\" role=\"group\" :aria-label=\"ariaLabel\">\n <slot />\n </div>\n</template>\n\n<style scoped>\n.wx-button-group {\n display: inline-flex;\n align-items: center;\n gap: var(--wx-space-8);\n vertical-align: middle;\n}\n\n.wx-button-group--vertical {\n flex-direction: column;\n align-items: stretch;\n}\n\n/* Joined: the buttons share one outline, so the gap goes and the borders overlap. */\n.wx-button-group--attached {\n gap: 0;\n}\n\n.wx-button-group--attached :deep(.wx-button) {\n position: relative;\n border-radius: 0;\n}\n\n.wx-button-group--attached :deep(.wx-button:first-child) {\n border-start-start-radius: var(--wx-radius-control);\n border-end-start-radius: var(--wx-radius-control);\n}\n\n.wx-button-group--attached :deep(.wx-button:last-child) {\n border-start-end-radius: var(--wx-radius-control);\n border-end-end-radius: var(--wx-radius-control);\n}\n\n.wx-button-group--attached :deep(.wx-button:not(:first-child)) {\n margin-left: -1px;\n}\n\n/* The hovered or focused button owns the shared border, so it is not half-covered. */\n.wx-button-group--attached :deep(.wx-button:hover),\n.wx-button-group--attached :deep(.wx-button:focus-visible),\n.wx-button-group--attached :deep(.wx-button:active) {\n z-index: 1;\n}\n\n.wx-button-group--attached.wx-button-group--vertical :deep(.wx-button) {\n border-radius: 0;\n}\n\n.wx-button-group--attached.wx-button-group--vertical :deep(.wx-button:first-child) {\n border-start-start-radius: var(--wx-radius-control);\n border-start-end-radius: var(--wx-radius-control);\n}\n\n.wx-button-group--attached.wx-button-group--vertical :deep(.wx-button:last-child) {\n border-end-start-radius: var(--wx-radius-control);\n border-end-end-radius: var(--wx-radius-control);\n}\n\n.wx-button-group--attached.wx-button-group--vertical :deep(.wx-button:not(:first-child)) {\n margin-left: 0;\n margin-top: -1px;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, useSlots } from 'vue'\nimport type { CardProps } from './types'\n\ndefineOptions({ name: 'WxCard' })\n\nconst props = withDefaults(defineProps<CardProps>(), {\n title: undefined,\n shadow: 'always',\n padding: 'md',\n bordered: false,\n})\n\nconst slots = useSlots()\n\nconst hasHeader = computed(() => Boolean(props.title || slots.header || slots.extra))\nconst hasSidebar = computed(() => Boolean(slots.sidebar))\n\nconst classes = computed(() => [\n 'wx-card',\n `wx-card--shadow-${props.shadow}`,\n `wx-card--padding-${props.padding}`,\n {\n 'wx-card--bordered': props.bordered,\n 'wx-card--with-sidebar': hasSidebar.value,\n },\n])\n</script>\n\n<template>\n <section :class=\"classes\">\n <header v-if=\"hasHeader\" class=\"wx-card__header\">\n <div class=\"wx-card__title\">\n <slot name=\"header\">{{ title }}</slot>\n </div>\n <div v-if=\"$slots.extra\" class=\"wx-card__extra\">\n <slot name=\"extra\" />\n </div>\n </header>\n\n <div class=\"wx-card__body\">\n <div v-if=\"hasSidebar\" class=\"wx-card__layout\">\n <aside class=\"wx-card__sidebar\">\n <slot name=\"sidebar\" />\n </aside>\n <div class=\"wx-card__content\">\n <slot />\n </div>\n </div>\n <slot v-else />\n </div>\n\n <footer v-if=\"$slots.footer\" class=\"wx-card__footer\">\n <slot name=\"footer\" />\n </footer>\n </section>\n</template>\n\n<style scoped>\n.wx-card {\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n background: var(--wx-bg-surface);\n border: 1px solid transparent;\n border-radius: var(--wx-radius-md);\n color: var(--wx-text-default);\n transition: box-shadow var(--wx-duration-normal) var(--wx-easing-standard);\n /* The sidebar layout reacts to the card's own width, not the viewport's. */\n container-type: inline-size;\n}\n\n.wx-card--bordered {\n border-color: var(--wx-border-default);\n}\n\n.wx-card--shadow-always {\n box-shadow: var(--wx-shadow-card);\n}\n\n.wx-card--shadow-hover:hover {\n box-shadow: var(--wx-shadow-card);\n}\n\n.wx-card__header,\n.wx-card__body,\n.wx-card__footer {\n padding: var(--wx-card-padding, var(--wx-gap, var(--wx-space-16)));\n}\n\n.wx-card--padding-none {\n --wx-card-padding: 0px;\n}\n\n.wx-card--padding-sm {\n --wx-card-padding: var(--wx-space-12);\n}\n\n/*\n * The default padding is the panel's own step (§6 of the visual spec): the air inside a card\n * is the air between the things in it, and it narrows with the window. Outside a panel — the\n * docs, a dialog mounted off the app tree — the variable is not there and the desktop step is\n * the fallback.\n */\n.wx-card--padding-md {\n --wx-card-padding: var(--wx-gap, var(--wx-space-16));\n}\n\n.wx-card--padding-lg {\n --wx-card-padding: var(--wx-space-24);\n}\n\n.wx-card__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--wx-space-16);\n padding-bottom: 0;\n}\n\n.wx-card__title {\n min-width: 0;\n color: var(--wx-text-strong);\n font-size: var(--wx-font-size-lg);\n font-weight: var(--wx-font-weight-semibold);\n line-height: var(--wx-font-line-height-tight);\n}\n\n.wx-card__extra {\n flex: 0 0 auto;\n color: var(--wx-text-muted);\n}\n\n/*\n * A card is a column of things, and they need the same air between them as around them.\n * The form's own gap reaches only its direct children, so two fields dropped into a card\n * stack flush and the hint under one reads as the label of the next.\n */\n.wx-card__body,\n.wx-card__sidebar,\n.wx-card__content {\n display: flex;\n flex-direction: column;\n gap: var(--wx-card-padding, var(--wx-gap, var(--wx-space-16)));\n}\n\n.wx-card__body {\n flex: 1 1 auto;\n}\n\n.wx-card__footer {\n padding-top: 0;\n}\n\n/* Sidebar layout: stacked by default, two columns once the card is wide enough. */\n.wx-card__layout {\n display: flex;\n flex-direction: column;\n gap: var(--wx-card-padding, var(--wx-gap, var(--wx-space-16)));\n}\n\n.wx-card__sidebar,\n.wx-card__content {\n min-width: 0;\n}\n\n.wx-card__content {\n flex: 1 1 auto;\n}\n\n@container (min-width: 560px) {\n .wx-card__layout {\n flex-direction: row;\n }\n\n .wx-card__sidebar {\n flex: 0 0 auto;\n width: var(--wx-card-sidebar-width, 240px);\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, nextTick, ref, watch } from 'vue'\nimport { PopoverAnchor, PopoverContent, PopoverPortal, PopoverRoot, PopoverTrigger } from 'reka-ui'\nimport WxIcon from '../Icon/Icon.vue'\nimport { useFormField } from '../../composables/useFormField'\nimport { useControlAttrs } from '../../composables/useControlAttrs'\nimport type {\n CascaderEmits,\n CascaderModelValue,\n CascaderOption,\n CascaderProps,\n CascaderValue,\n} from './types'\n\ndefineOptions({ name: 'WxCascader', inheritAttrs: false })\n\n/* `class` and `style` belong to the control; the rest belongs to its input. */\nconst { rootAttrs, controlAttrs } = useControlAttrs()\n\nconst props = withDefaults(defineProps<CascaderProps>(), {\n options: () => [],\n expandTrigger: 'click',\n checkStrictly: false,\n emitPath: true,\n showAllLevels: true,\n separator: ' / ',\n lazy: false,\n load: undefined,\n placeholder: undefined,\n emptyText: 'Nothing here',\n clearable: false,\n teleport: true,\n disabled: undefined,\n size: undefined,\n status: undefined,\n id: undefined,\n name: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<CascaderEmits>()\n\nconst model = defineModel<CascaderModelValue>({ default: null })\n\nconst field = useFormField(props)\n\nconst open = ref(false)\n/** The chain of opened nodes — one column per entry, plus the root column. */\nconst activePath = ref<CascaderOption[]>([])\nconst panel = ref<HTMLElement | null>(null)\n\n/** Levels fetched by `load`, keyed by the path that asked for them. */\nconst loadedChildren = ref(new Map<string, CascaderOption[]>())\nconst loadingKeys = ref(new Set<string>())\n\n/**\n * A path is keyed by the values along it, serialised — no separator character to\n * clash with a value that happens to contain one. The root is the empty path.\n */\nfunction keyOf(path: CascaderOption[]): string {\n return JSON.stringify(path.map((option) => option.value))\n}\n\nconst rootOptions = computed<CascaderOption[]>(() =>\n props.options.length > 0 ? props.options : (loadedChildren.value.get(keyOf([])) ?? []),\n)\n\nfunction childrenOf(option: CascaderOption, parents: CascaderOption[]): CascaderOption[] {\n if (option.children?.length) return option.children\n return loadedChildren.value.get(keyOf([...parents, option])) ?? []\n}\n\nfunction isLeaf(option: CascaderOption, parents: CascaderOption[]): boolean {\n if (option.leaf === true) return true\n if (option.children?.length) return false\n if (!props.lazy) return true\n\n /* Lazily: a node is a leaf once its level came back empty, not before. */\n const loaded = loadedChildren.value.get(keyOf([...parents, option]))\n return loaded !== undefined && loaded.length === 0\n}\n\nfunction isLoading(option: CascaderOption, parents: CascaderOption[]): boolean {\n return loadingKeys.value.has(keyOf([...parents, option]))\n}\n\n/** The root column, then one column per opened node that has something under it. */\nconst columns = computed<CascaderOption[][]>(() => {\n const result: CascaderOption[][] = [rootOptions.value]\n\n activePath.value.forEach((option, index) => {\n const children = childrenOf(option, activePath.value.slice(0, index))\n if (children.length > 0) result.push(children)\n })\n\n return result\n})\n\n/** Walks a stored path of values back into the options they name. */\nfunction resolvePath(values: CascaderValue[]): CascaderOption[] {\n const path: CascaderOption[] = []\n let level = rootOptions.value\n\n for (const value of values) {\n const option = level.find((candidate) => candidate.value === value)\n if (!option) break\n path.push(option)\n level = childrenOf(option, path.slice(0, -1))\n }\n\n return path\n}\n\n/** Depth-first search, for a model that holds the last value alone. */\nfunction findPath(\n options: CascaderOption[],\n value: CascaderValue,\n parents: CascaderOption[] = [],\n): CascaderOption[] | undefined {\n for (const option of options) {\n const path = [...parents, option]\n if (option.value === value) return path\n\n const found = findPath(childrenOf(option, parents), value, path)\n if (found) return found\n }\n return undefined\n}\n\nconst selectedPath = computed<CascaderOption[]>(() => {\n const value = model.value\n if (value === null || value === undefined || value === '') return []\n if (Array.isArray(value)) return resolvePath(value)\n return findPath(rootOptions.value, value) ?? []\n})\n\nconst hasValue = computed(() => {\n const value = model.value\n if (value === null || value === undefined || value === '') return false\n /* An empty path is \"nothing picked\" — that is what `clear` leaves behind. */\n if (Array.isArray(value)) return value.length > 0\n return true\n})\n\nconst displayLabel = computed(() => {\n const path = selectedPath.value\n\n /* Nothing resolved — usually a lazy tree that has not loaded the branch yet. */\n if (path.length === 0) {\n const value = model.value\n if (!hasValue.value) return ''\n return Array.isArray(value) ? value.join(props.separator) : String(value)\n }\n\n if (!props.showAllLevels) return path[path.length - 1].label\n return path.map((option) => option.label).join(props.separator)\n})\n\nconst showClear = computed(() => props.clearable && !field.disabled.value && hasValue.value)\n\n/** What a plain form post carries: the path as `content,news`, or the single value. */\nconst formValue = computed(() => {\n const value = model.value\n if (!hasValue.value) return ''\n return Array.isArray(value) ? value.join(',') : String(value)\n})\n\nconst classes = computed(() => [\n 'wx-cascader',\n `wx-cascader--${field.size.value}`,\n {\n [`wx-cascader--${field.status.value}`]: field.status.value !== 'default',\n 'is-open': open.value,\n 'is-disabled': field.disabled.value,\n },\n])\n\nasync function loadLevel(path: CascaderOption[]): Promise<void> {\n if (!props.load) return\n\n const key = keyOf(path)\n if (loadedChildren.value.has(key) || loadingKeys.value.has(key)) return\n\n loadingKeys.value.add(key)\n try {\n const children = await props.load(path[path.length - 1] ?? null, path)\n loadedChildren.value.set(key, children)\n } finally {\n loadingKeys.value.delete(key)\n }\n}\n\nfunction expand(option: CascaderOption, level: number) {\n if (option.disabled) return\n\n const parents = activePath.value.slice(0, level)\n activePath.value = [...parents, option]\n emit('expand', activePath.value)\n\n if (props.lazy && !isLeaf(option, parents)) void loadLevel([...parents, option])\n}\n\nfunction select(path: CascaderOption[]) {\n const value: CascaderModelValue = props.emitPath\n ? path.map((option) => option.value)\n : (path[path.length - 1]?.value ?? null)\n\n model.value = value\n emit('change', value)\n}\n\nfunction onOptionClick(option: CascaderOption, level: number) {\n if (option.disabled) return\n\n const parents = activePath.value.slice(0, level)\n const path = [...parents, option]\n const leaf = isLeaf(option, parents)\n\n expand(option, level)\n\n if (leaf || props.checkStrictly) select(path)\n if (leaf) open.value = false\n}\n\nfunction onOptionHover(option: CascaderOption, level: number) {\n if (props.expandTrigger !== 'hover' || option.disabled) return\n if (isLeaf(option, activePath.value.slice(0, level))) return\n expand(option, level)\n}\n\nfunction clear() {\n model.value = props.emitPath ? [] : null\n activePath.value = []\n emit('change', model.value)\n emit('clear')\n}\n\nwatch(open, (value) => {\n if (value) {\n /* Reopening lands where the current value sits, not where the last poke left it. */\n activePath.value = selectedPath.value.slice(0, -1)\n if (props.lazy && rootOptions.value.length === 0) void loadLevel([])\n emit('open')\n return\n }\n emit('close')\n})\n\n// --- keyboard ---------------------------------------------------------------\n\nfunction optionsIn(level: number): HTMLButtonElement[] {\n if (!panel.value) return []\n return [\n ...panel.value.querySelectorAll<HTMLButtonElement>(\n `[data-column=\"${level}\"] .wx-cascader__option:not(:disabled)`,\n ),\n ]\n}\n\nfunction focusOption(level: number, index: number) {\n const items = optionsIn(level)\n if (items.length === 0) return\n const bounded = ((index % items.length) + items.length) % items.length\n items[bounded]?.focus()\n}\n\nfunction onPanelKeydown(event: KeyboardEvent) {\n const target = event.target as HTMLElement | null\n const column = target?.closest<HTMLElement>('[data-column]')\n\n /* The panel itself has focus right after opening: the first arrow enters the list. */\n if (!column) {\n if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {\n event.preventDefault()\n focusOption(0, 0)\n }\n return\n }\n\n const level = Number(column.dataset.column)\n const items = optionsIn(level)\n const current = items.indexOf(target as HTMLButtonElement)\n const option = columns.value[level]?.[Number((target as HTMLElement).dataset.index)]\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault()\n focusOption(level, current + 1)\n break\n case 'ArrowUp':\n event.preventDefault()\n focusOption(level, current - 1)\n break\n case 'ArrowRight': {\n if (!option || isLeaf(option, activePath.value.slice(0, level))) return\n event.preventDefault()\n expand(option, level)\n void nextTick(() => focusOption(level + 1, 0))\n break\n }\n case 'ArrowLeft': {\n if (level === 0) return\n event.preventDefault()\n activePath.value = activePath.value.slice(0, level - 1)\n void nextTick(() => {\n const parent = columns.value[level - 1]?.findIndex(\n (candidate) => candidate.value === activePath.value[level - 1]?.value,\n )\n focusOption(level - 1, parent === undefined || parent < 0 ? 0 : parent)\n })\n break\n }\n default:\n break\n }\n}\n</script>\n\n<template>\n <popover-root v-model:open=\"open\">\n <div :class=\"classes\" v-bind=\"rootAttrs\">\n <popover-anchor as=\"div\" class=\"wx-cascader__anchor\">\n <popover-trigger\n :id=\"field.id.value\"\n v-bind=\"controlAttrs\"\n class=\"wx-cascader__trigger\"\n type=\"button\"\n :disabled=\"field.disabled.value\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"field.describedBy.value\"\n :aria-invalid=\"field.status.value === 'error' || undefined\"\n >\n <span v-if=\"hasValue\" class=\"wx-cascader__value\">{{ displayLabel }}</span>\n <span v-else class=\"wx-cascader__placeholder\">{{ placeholder }}</span>\n <wx-icon class=\"wx-cascader__arrow\" name=\"chevron-down\" />\n </popover-trigger>\n\n <button\n v-if=\"showClear\"\n class=\"wx-cascader__clear\"\n type=\"button\"\n tabindex=\"-1\"\n aria-label=\"Clear\"\n @click.stop=\"clear\"\n >\n <wx-icon name=\"close\" />\n </button>\n </popover-anchor>\n\n <input v-if=\"name\" type=\"hidden\" :name=\"name\" :value=\"formValue\" />\n </div>\n\n <popover-portal :disabled=\"!teleport\">\n <!--\n The panel itself takes focus when it opens — that is what makes the arrow keys\n work — so the key handler sits on it rather than on the columns inside.\n -->\n <popover-content\n class=\"wx-cascader__panel\"\n align=\"start\"\n :side-offset=\"4\"\n @keydown=\"onPanelKeydown\"\n >\n <div ref=\"panel\" class=\"wx-cascader__columns\">\n <div\n v-for=\"(column, level) in columns\"\n :key=\"level\"\n class=\"wx-cascader__column\"\n :data-column=\"level\"\n role=\"listbox\"\n :aria-label=\"`Level ${level + 1}`\"\n >\n <button\n v-for=\"(option, index) in column\"\n :key=\"String(option.value)\"\n class=\"wx-cascader__option\"\n type=\"button\"\n role=\"option\"\n :data-index=\"index\"\n :disabled=\"option.disabled\"\n :aria-selected=\"selectedPath[level]?.value === option.value\"\n :class=\"{\n 'is-active': activePath[level]?.value === option.value,\n 'is-selected': selectedPath[level]?.value === option.value,\n }\"\n @click=\"onOptionClick(option, level)\"\n @mouseenter=\"onOptionHover(option, level)\"\n >\n <span class=\"wx-cascader__label\">\n <slot name=\"option\" :option=\"option\" :level=\"level\">{{ option.label }}</slot>\n </span>\n\n <wx-icon\n v-if=\"isLoading(option, activePath.slice(0, level))\"\n class=\"wx-cascader__mark\"\n name=\"loader\"\n spin\n />\n <wx-icon\n v-else-if=\"!isLeaf(option, activePath.slice(0, level))\"\n class=\"wx-cascader__mark\"\n name=\"chevron-right\"\n />\n <wx-icon\n v-else-if=\"selectedPath[level]?.value === option.value\"\n class=\"wx-cascader__mark wx-cascader__mark--check\"\n name=\"check\"\n />\n </button>\n\n <p v-if=\"column.length === 0\" class=\"wx-cascader__empty\">{{ emptyText }}</p>\n </div>\n </div>\n </popover-content>\n </popover-portal>\n </popover-root>\n</template>\n\n<style scoped>\n.wx-cascader {\n display: block;\n width: 100%;\n}\n\n.wx-cascader__anchor {\n display: flex;\n align-items: center;\n box-sizing: border-box;\n height: var(--wx-size-control-md);\n padding-right: var(--wx-space-8);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-control);\n color: var(--wx-text-default);\n font-size: var(--wx-font-size-control-md);\n transition: border-color var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-cascader--sm .wx-cascader__anchor {\n height: var(--wx-size-control-sm);\n font-size: var(--wx-font-size-control-sm);\n}\n\n.wx-cascader--lg .wx-cascader__anchor {\n height: var(--wx-size-control-lg);\n font-size: var(--wx-font-size-control-lg);\n}\n\n.wx-cascader__anchor:hover {\n border-color: var(--wx-border-strong);\n}\n\n.wx-cascader.is-open .wx-cascader__anchor,\n.wx-cascader__anchor:focus-within {\n border-color: var(--wx-border-focus);\n}\n\n.wx-cascader--error .wx-cascader__anchor,\n.wx-cascader--error.is-open .wx-cascader__anchor {\n border-color: var(--wx-color-danger);\n}\n\n.wx-cascader--success .wx-cascader__anchor {\n border-color: var(--wx-color-success);\n}\n\n.wx-cascader--warning .wx-cascader__anchor {\n border-color: var(--wx-color-warning);\n}\n\n.wx-cascader.is-disabled .wx-cascader__anchor {\n background: var(--wx-bg-disabled);\n color: var(--wx-text-disabled);\n}\n\n.wx-cascader__trigger {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n flex: 1 1 auto;\n min-width: 0;\n height: 100%;\n padding: 0 0 0 var(--wx-space-12);\n background: transparent;\n border: none;\n color: inherit;\n font-family: inherit;\n font-size: inherit;\n text-align: start;\n cursor: pointer;\n}\n\n.wx-cascader__trigger:focus-visible {\n outline: none;\n}\n\n.wx-cascader.is-disabled .wx-cascader__trigger {\n cursor: not-allowed;\n}\n\n.wx-cascader__value,\n.wx-cascader__placeholder {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wx-cascader__placeholder {\n color: var(--wx-text-placeholder);\n}\n\n.wx-cascader__arrow {\n flex: 0 0 auto;\n color: var(--wx-text-muted);\n font-size: 16px;\n transition: transform var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-cascader.is-open .wx-cascader__arrow {\n transform: rotate(180deg);\n}\n\n.wx-cascader__clear {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 20px;\n height: 20px;\n padding: 0;\n background: transparent;\n border: none;\n border-radius: var(--wx-radius-full);\n color: var(--wx-text-muted);\n cursor: pointer;\n}\n\n.wx-cascader__clear:hover {\n color: var(--wx-text-default);\n}\n</style>\n\n<style>\n/* The panel is teleported, so its styles cannot be scoped to the component. */\n.wx-cascader__panel {\n /* One layer for every floating panel, so the one opened last is the one on top. */\n z-index: var(--wx-z-index-popover);\n box-sizing: border-box;\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-sm);\n box-shadow: var(--wx-shadow-popover);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n font-size: var(--wx-font-size-control-md);\n overflow: hidden;\n}\n\n.wx-cascader__columns {\n display: flex;\n align-items: stretch;\n max-width: min(90vw, 720px);\n /* Columns scroll sideways rather than push the panel off a narrow screen. */\n overflow-x: auto;\n}\n\n.wx-cascader__column {\n display: flex;\n flex-direction: column;\n flex: 0 0 auto;\n gap: 1px;\n min-width: 180px;\n max-height: 280px;\n padding: var(--wx-space-4);\n overflow-y: auto;\n}\n\n.wx-cascader__column + .wx-cascader__column {\n border-left: 1px solid var(--wx-border-muted);\n}\n\n.wx-cascader__option {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--wx-space-8);\n width: 100%;\n padding: var(--wx-space-6) var(--wx-space-10);\n background: transparent;\n border: none;\n border-radius: var(--wx-radius-xs);\n color: inherit;\n font-family: inherit;\n font-size: var(--wx-font-size-sm);\n text-align: start;\n cursor: pointer;\n}\n\n.wx-cascader__option:hover:not(:disabled),\n.wx-cascader__option:focus-visible {\n background: var(--wx-bg-fill);\n outline: none;\n}\n\n.wx-cascader__option.is-active {\n background: var(--wx-bg-fill);\n}\n\n.wx-cascader__option.is-selected {\n color: var(--wx-color-primary);\n font-weight: var(--wx-font-weight-semibold);\n}\n\n.wx-cascader__option:disabled {\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n.wx-cascader__label {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wx-cascader__mark {\n flex: 0 0 auto;\n color: var(--wx-text-muted);\n font-size: 14px;\n}\n\n.wx-cascader__mark--check {\n color: var(--wx-color-primary);\n}\n\n.wx-cascader__empty {\n margin: 0;\n padding: var(--wx-space-10);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n text-align: center;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, inject, onMounted, ref, watch } from 'vue'\nimport { checkboxGroupKey, useFormField } from '../../composables/useFormField'\nimport type { CheckboxEmits, CheckboxProps } from './types'\nimport { useControlAttrs } from '../../composables/useControlAttrs'\n\ndefineOptions({ name: 'WxCheckbox', inheritAttrs: false })\n\n/* `class` and `style` belong to the control; the rest belongs to its input. */\nconst { rootAttrs, controlAttrs } = useControlAttrs()\n\nconst props = withDefaults(defineProps<CheckboxProps>(), {\n value: undefined,\n label: undefined,\n indeterminate: false,\n disabled: undefined,\n size: undefined,\n id: undefined,\n name: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<CheckboxEmits>()\n\nconst model = defineModel<boolean>({ default: false })\n\nconst group = inject(checkboxGroupKey, null)\nconst field = useFormField(props)\nconst inputRef = ref<HTMLInputElement | null>(null)\n\nconst checked = computed(() =>\n group ? group.modelValue.value.includes(props.value ?? null) : model.value === true,\n)\n\nconst disabled = computed(\n () =>\n props.disabled ||\n group?.disabled.value ||\n group?.locked?.(props.value ?? null) === true ||\n field.disabled.value,\n)\nconst size = computed(() => props.size ?? group?.size.value ?? field.size.value)\n\nconst classes = computed(() => [\n 'wx-checkbox',\n `wx-checkbox--${size.value}`,\n {\n 'is-checked': checked.value,\n 'is-indeterminate': props.indeterminate && !checked.value,\n 'is-disabled': disabled.value,\n },\n])\n\n/** `indeterminate` only exists as a DOM property, never as an attribute. */\nfunction syncIndeterminate() {\n if (inputRef.value) inputRef.value.indeterminate = props.indeterminate && !checked.value\n}\n\nonMounted(syncIndeterminate)\nwatch([() => props.indeterminate, checked], syncIndeterminate)\n\nfunction onChange(event: Event) {\n const input = event.target as HTMLInputElement\n const next = input.checked\n if (group) group.toggle(props.value ?? null, next)\n else model.value = next\n // The group may have refused the change; the input says what the group holds, not the click.\n if (input.checked !== checked.value) input.checked = checked.value\n emit('change', next)\n}\n</script>\n\n<template>\n <label :class=\"classes\" v-bind=\"rootAttrs\">\n <input\n :id=\"field.id.value\"\n ref=\"inputRef\"\n v-bind=\"controlAttrs\"\n class=\"wx-checkbox__native\"\n type=\"checkbox\"\n :name=\"name ?? group?.name.value\"\n :checked=\"checked\"\n :disabled=\"disabled\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"field.describedBy.value\"\n @change=\"onChange\"\n />\n\n <span class=\"wx-checkbox__box\" aria-hidden=\"true\">\n <svg class=\"wx-checkbox__mark\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path\n v-if=\"indeterminate && !checked\"\n d=\"M4 8h8\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n <path\n v-else\n d=\"M3.5 8.5l3 3 6-6\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n\n <span v-if=\"label || $slots.default\" class=\"wx-checkbox__label\">\n <slot>{{ label }}</slot>\n </span>\n </label>\n</template>\n\n<style scoped>\n.wx-checkbox {\n display: inline-flex;\n align-items: center;\n gap: var(--wx-space-8);\n cursor: pointer;\n user-select: none;\n color: var(--wx-text-default);\n}\n\n.wx-checkbox.is-disabled {\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n.wx-checkbox__native {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n border: 0;\n}\n\n.wx-checkbox__box {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n box-sizing: border-box;\n width: var(--wx-checkbox-size, 20px);\n height: var(--wx-checkbox-size, 20px);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-strong);\n border-radius: var(--wx-radius-xs);\n color: transparent;\n transition:\n background-color var(--wx-duration-fast) var(--wx-easing-standard),\n border-color var(--wx-duration-fast) var(--wx-easing-standard),\n color var(--wx-duration-fast) var(--wx-easing-standard),\n box-shadow var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-checkbox--sm {\n --wx-checkbox-size: 16px;\n font-size: var(--wx-font-size-control-sm);\n}\n\n.wx-checkbox--md {\n --wx-checkbox-size: 20px;\n /* A tick beside a label is a choice in a list, and reads at the list size. */\n font-size: var(--wx-font-size-control-md);\n}\n\n.wx-checkbox--lg {\n --wx-checkbox-size: 24px;\n font-size: var(--wx-font-size-control-lg);\n}\n\n.wx-checkbox:hover:not(.is-disabled) .wx-checkbox__box {\n border-color: var(--wx-color-primary);\n}\n\n.wx-checkbox.is-checked .wx-checkbox__box,\n.wx-checkbox.is-indeterminate .wx-checkbox__box {\n border-color: var(--wx-color-primary);\n color: var(--wx-color-primary);\n}\n\n.wx-checkbox.is-disabled .wx-checkbox__box {\n background: var(--wx-bg-disabled);\n border-color: var(--wx-border-default);\n}\n\n.wx-checkbox.is-disabled.is-checked .wx-checkbox__box,\n.wx-checkbox.is-disabled.is-indeterminate .wx-checkbox__box {\n color: var(--wx-color-primary-disabled);\n border-color: var(--wx-color-primary-disabled);\n}\n\n.wx-checkbox__native:focus-visible + .wx-checkbox__box {\n border-color: var(--wx-color-primary);\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-checkbox__mark {\n width: 100%;\n height: 100%;\n}\n\n.wx-checkbox__label {\n line-height: var(--wx-font-line-height-normal);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-checkbox__box {\n transition: none;\n }\n}\n</style>\n","import type { Extension, Range } from '@codemirror/state'\nimport {\n Decoration,\n ViewPlugin,\n type DecorationSet,\n type EditorView,\n type ViewUpdate,\n} from '@codemirror/view'\nimport type {\n CodeEditorCompleter,\n CodeEditorCompletion,\n CodeEditorCompletionContext,\n MustacheVariable,\n MustacheWords,\n} from './types'\n\n/**\n * Mustache over text or HTML: `{{name}}`, sections `{{#list}}…{{/list}}`, `{{^name}}`, comments.\n *\n * Neither CodeMirror nor a maintained package carries Mustache for CodeMirror 6 (the legacy modes\n * have Jinja and Velocity, not Mustache), and a template of a notification is a dozen lines — so\n * the tags are found by one scan of the document and painted as marks over whatever language is\n * underneath. The same scan answers the completion source and the checks a form runs on a\n * template, so the three never disagree about where a tag begins.\n */\n\n/** What a tag is, by its first character. */\nexport type MustacheTagKind =\n | 'variable'\n | 'section'\n | 'inverted'\n | 'close'\n | 'comment'\n /** `{{{name}}}` and `{{&name}}`: printed raw by Mustache itself. */\n | 'raw'\n /** `{{>partial}}`, `{{=<% %>=}}`, `{{%pragma}}`, `{{$block}}`, `{{<parent}}`. */\n | 'other'\n /** `{{` with no `}}` after it. */\n | 'unclosed'\n\nexport interface MustacheTag {\n kind: MustacheTagKind\n /** The name inside, trimmed; empty for a comment and for a tag still being typed. */\n name: string\n /** Offset of the first `{`. */\n from: number\n /** Offset just past the last `}` — the end of the document for an unclosed tag. */\n to: number\n}\n\nconst SIGILS: Record<string, MustacheTagKind> = {\n '#': 'section',\n '^': 'inverted',\n '/': 'close',\n '!': 'comment',\n '&': 'raw',\n '>': 'other',\n '<': 'other',\n '=': 'other',\n '%': 'other',\n $: 'other',\n}\n\n/** Every tag of a template, in order. */\nexport function scanMustache(text: string): MustacheTag[] {\n const tags: MustacheTag[] = []\n let at = 0\n\n while (at < text.length) {\n const from = text.indexOf('{{', at)\n\n if (from === -1) break\n\n const triple = text.startsWith('{{{', from)\n const close = triple ? '}}}' : '}}'\n const end = text.indexOf(close, from + (triple ? 3 : 2))\n\n if (end === -1) {\n tags.push({ kind: 'unclosed', name: '', from, to: text.length })\n break\n }\n\n const inner = text.slice(from + (triple ? 3 : 2), end)\n const sigil = inner.trimStart().charAt(0)\n const kind: MustacheTagKind = triple ? 'raw' : (SIGILS[sigil] ?? 'variable')\n const name =\n kind === 'comment'\n ? ''\n : (kind === 'variable' || triple ? inner : inner.trimStart().slice(1)).trim()\n\n tags.push({ kind, name, from, to: end + close.length })\n at = end + close.length\n }\n\n return tags\n}\n\n/** The sections open at an offset, the innermost last. */\nexport function openSections(tags: MustacheTag[], before: number): string[] {\n const open: string[] = []\n\n for (const tag of tags) {\n if (tag.to > before) break\n\n if (tag.kind === 'section' || tag.kind === 'inverted') open.push(tag.name)\n\n if (tag.kind === 'close') {\n const at = open.lastIndexOf(tag.name)\n\n if (at !== -1) open.splice(at)\n }\n }\n\n return open\n}\n\nexport interface MustacheProblems {\n /** Sections opened and never closed. */\n unclosed: string[]\n /** `{{/name}}` with nothing of that name open. */\n stray: string[]\n /** Names no variable and no field of an open list has — only when variables were given. */\n unknown: string[]\n /** Tags Mustache would read and a template here may not use: partials, delimiters, pragmas. */\n refused: string[]\n /** `{{` that never ends. */\n broken: boolean\n}\n\n/**\n * What is wrong with a template as it stands, by the same rules the completion knows: the open\n * list's fields inside its section, the variables everywhere. With no variables the names are not\n * judged — a template for any event may say anything.\n */\nexport function mustacheProblems(text: string, variables?: MustacheVariable[]): MustacheProblems {\n const tags = scanMustache(text)\n const problems: MustacheProblems = {\n unclosed: [],\n stray: [],\n unknown: [],\n refused: [],\n broken: false,\n }\n const open: string[] = []\n const lists = new Map((variables ?? []).map((variable) => [variable.name, variable]))\n\n const known = (name: string): boolean => {\n for (const section of [...open].reverse()) {\n if (lists.get(section)?.fields?.some((field) => field.name === name)) return true\n }\n\n return (variables ?? []).some(\n (variable) =>\n variable.name === name ||\n (variable.name.endsWith('.*') && name.startsWith(variable.name.slice(0, -1))),\n )\n }\n\n const unknown = new Set<string>()\n\n for (const tag of tags) {\n if (tag.kind === 'unclosed') problems.broken = true\n if (tag.kind === 'other') problems.refused.push(text.slice(tag.from, tag.to))\n if (tag.kind === 'comment' || tag.kind === 'unclosed' || tag.kind === 'other') continue\n\n if (tag.kind === 'close') {\n const at = open.lastIndexOf(tag.name)\n\n if (at === -1) problems.stray.push(tag.name)\n else open.splice(at)\n\n continue\n }\n\n if (variables !== undefined && tag.name !== '' && !known(tag.name)) unknown.add(tag.name)\n if (tag.kind === 'section' || tag.kind === 'inverted') open.push(tag.name)\n }\n\n problems.unclosed = open\n problems.unknown = [...unknown]\n\n return problems\n}\n\n/* ------------------------------------------------------------------------- highlighting ----- */\n\nconst marks: Record<MustacheTagKind, Decoration> = {\n variable: Decoration.mark({ class: 'wx-cm-mustache' }),\n raw: Decoration.mark({ class: 'wx-cm-mustache' }),\n section: Decoration.mark({ class: 'wx-cm-mustache wx-cm-mustache--section' }),\n inverted: Decoration.mark({ class: 'wx-cm-mustache wx-cm-mustache--section' }),\n close: Decoration.mark({ class: 'wx-cm-mustache wx-cm-mustache--section' }),\n comment: Decoration.mark({ class: 'wx-cm-mustache wx-cm-mustache--comment' }),\n other: Decoration.mark({ class: 'wx-cm-mustache wx-cm-mustache--invalid' }),\n unclosed: Decoration.mark({ class: 'wx-cm-mustache wx-cm-mustache--invalid' }),\n}\n\n/*\n * The whole document every time: a section opened on line 2 colours a close on line 40, and a\n * notification is short enough that a scan costs less than keeping track of what changed.\n */\nfunction decorate(view: EditorView): DecorationSet {\n const ranges: Range<Decoration>[] = []\n\n for (const tag of scanMustache(view.state.doc.toString())) {\n if (tag.to > tag.from) ranges.push(marks[tag.kind].range(tag.from, tag.to))\n }\n\n return Decoration.set(ranges, true)\n}\n\n/** The tags painted as marks over the language underneath. */\nexport function mustacheHighlighting(): Extension {\n return ViewPlugin.fromClass(\n class {\n decorations: DecorationSet\n\n constructor(view: EditorView) {\n this.decorations = decorate(view)\n }\n\n update(update: ViewUpdate) {\n if (update.docChanged) this.decorations = decorate(update.view)\n }\n },\n { decorations: (plugin) => plugin.decorations },\n )\n}\n\n/* --------------------------------------------------------------------------- completion ----- */\n\nconst WORDS: MustacheWords = {\n variable: 'variable',\n list: 'list',\n field: 'field of :list',\n section: 'shown when :name has a value',\n inverted: 'shown when :name is empty',\n close: 'closes :name',\n comment: 'a comment, never printed',\n example: 'Example: :example',\n}\n\nfunction say(line: string, replace: Record<string, string>): string {\n return line.replace(/:(\\w+)/g, (whole, key: string) => replace[key] ?? whole)\n}\n\nfunction exampleOf(variable: MustacheVariable): string | undefined {\n const example = variable.example\n\n if (example === undefined || example === null || example === '') return undefined\n if (typeof example === 'string' || typeof example === 'number') return String(example)\n\n return undefined\n}\n\nfunction isList(variable: MustacheVariable): boolean {\n return (variable.fields?.length ?? 0) > 0\n}\n\n/** A section around the caret: on lines of its own for a list, inline for \"has a value\". */\nfunction sectionOf(name: string, sigil: '#' | '^', block: boolean): string {\n return block ? `${sigil}${name}}}\\n\\${}\\n{{/${name}}}` : `${sigil}${name}}}\\${}{{/${name}}}`\n}\n\n/**\n * Mustache's own suggestions after `{{`: the variables and the fields of the list being looped\n * over, a list as a whole section, `{{#…}}` / `{{^…}}` for \"has a value\" / \"is empty\", and after\n * `{{/` the section open nearest. With no variables only the syntax is offered — a template for\n * any event knows no names.\n *\n * Every suggestion ends the tag: the `}}` that closing brackets typed is taken over rather than\n * doubled, and a section is written whole with the caret inside.\n *\n * ```ts\n * <wx-code-editor language=\"mustache\" :completions=\"mustacheCompletions(variables)\" />\n * ```\n */\nexport function mustacheCompletions(\n variables: MustacheVariable[] = [],\n words: Partial<MustacheWords> = {},\n): CodeEditorCompleter {\n const said: MustacheWords = { ...WORDS, ...words }\n const byName = new Map(variables.map((variable) => [variable.name, variable]))\n\n return (context: CodeEditorCompletionContext) => {\n const { text, pos } = context\n const start = text.lastIndexOf('{{', pos - 2)\n\n if (start === -1) return null\n\n const typed = text.slice(start + 2, pos)\n const head = /^([#^/!]?)(\\s*)([\\w.]*)$/.exec(typed)\n\n // A tag closed before the caret, or one with something in it that no name has.\n if (head === null) return null\n\n const sigil = head[1] ?? ''\n\n if (sigil === '!') return null\n\n const from = start + 2 + sigil.length + (head[2]?.length ?? 0)\n const after = text.slice(pos)\n const rest = /^[\\w.]*/.exec(after)?.[0] ?? ''\n const to = pos + rest.length + (after.slice(rest.length).startsWith('}}') ? 2 : 0)\n const open = openSections(scanMustache(text.slice(0, start)), start)\n const options: CodeEditorCompletion[] = []\n\n if (sigil === '/') {\n ;[...open].reverse().forEach((name, depth) => {\n options.push({\n label: name,\n apply: `${name}}}`,\n detail: say(said.close, { name: `{{#${name}}}` }),\n type: 'keyword',\n boost: 99 - depth,\n })\n })\n\n return options.length === 0 ? null : { from, to, options }\n }\n\n if (sigil === '#' || sigil === '^') {\n for (const variable of variables) {\n if (variable.name.endsWith('.*')) continue\n\n const list = isList(variable)\n\n options.push({\n label: variable.name,\n apply: sectionOf(variable.name, sigil, list).slice(1),\n detail: list\n ? said.list\n : say(sigil === '#' ? said.section : said.inverted, { name: variable.name }),\n info: variable.label,\n type: list ? 'class' : 'variable',\n boost: list ? 1 : 0,\n })\n }\n\n return options.length === 0 ? null : { from, to, options }\n }\n\n // Inside a list: the fields of its element first, the way Mustache looks a name up.\n ;[...open].reverse().forEach((name, depth) => {\n for (const field of byName.get(name)?.fields ?? []) {\n options.push({\n label: field.name,\n apply: `${field.name}}}`,\n detail: say(said.field, { list: name }),\n info: field.label,\n type: 'property',\n boost: 50 - depth,\n })\n }\n })\n\n for (const variable of variables) {\n if (variable.name.endsWith('.*')) {\n options.push({\n label: `${variable.name.slice(0, -1)}…`,\n apply: variable.name.slice(0, -1),\n detail: said.variable,\n info: variable.label,\n type: 'variable',\n })\n\n continue\n }\n\n if (isList(variable)) {\n options.push({\n label: variable.name,\n apply: sectionOf(variable.name, '#', true),\n detail: said.list,\n info: [variable.label, (variable.fields ?? []).map((one) => one.name).join(', ')]\n .filter(Boolean)\n .join(' — '),\n type: 'class',\n boost: 5,\n })\n\n continue\n }\n\n const example = exampleOf(variable)\n\n options.push(\n {\n label: variable.name,\n apply: `${variable.name}}}`,\n detail: example,\n info: [variable.label, example === undefined ? undefined : say(said.example, { example })]\n .filter(Boolean)\n .join('\\n'),\n type: 'variable',\n boost: 10,\n },\n {\n label: `#${variable.name}`,\n apply: sectionOf(variable.name, '#', false),\n detail: say(said.section, { name: variable.name }),\n type: 'keyword',\n boost: -10,\n },\n {\n label: `^${variable.name}`,\n apply: sectionOf(variable.name, '^', false),\n detail: say(said.inverted, { name: variable.name }),\n type: 'keyword',\n boost: -11,\n },\n )\n }\n\n const nearest = open.at(-1)\n\n if (nearest !== undefined) {\n options.push({\n label: `/${nearest}`,\n apply: `/${nearest}}}`,\n detail: say(said.close, { name: `{{#${nearest}}}` }),\n type: 'keyword',\n boost: 20,\n })\n }\n\n if (variables.length === 0) {\n options.push(\n {\n label: '#…',\n apply: '#${name}}}\\n${}\\n{{/${name}}}',\n detail: say(said.section, { name: '…' }),\n type: 'keyword',\n },\n {\n label: '^…',\n apply: '^${name}}}\\n${}\\n{{/${name}}}',\n detail: say(said.inverted, { name: '…' }),\n type: 'keyword',\n },\n )\n }\n\n options.push({\n label: '!…',\n apply: '! ${} }}',\n detail: said.comment,\n type: 'text',\n boost: -20,\n })\n\n return { from, to, options }\n }\n}\n","import { defineAsyncComponent } from 'vue'\n\n/*\n * Loaded when first drawn, not with the panel: CodeMirror with its seven languages is a third of\n * what the panel downloaded before anything appeared, and most screens have no code on them.\n * The component is the same one — props, events, `v-model` and the instance a template ref\n * points at — it just arrives a moment after the screen that holds it.\n */\nexport const WxCodeEditor = Object.assign(\n defineAsyncComponent({ loader: () => import('./CodeEditor.vue'), suspensible: false }),\n // Named like what it loads: a test — ours or a site's — that stubs `WxCodeEditor` by name still does.\n { name: 'WxCodeEditor' },\n)\nexport type * from './types'\nexport {\n mustacheCompletions,\n mustacheHighlighting,\n mustacheProblems,\n scanMustache,\n} from './mustache'\nexport type { MustacheProblems, MustacheTag, MustacheTagKind } from './mustache'\n","<script setup lang=\"ts\">\nimport { computed, provide } from 'vue'\nimport { checkboxGroupKey, useFormField, type ChoiceValue } from '../../composables/useFormField'\nimport WxCheckbox from '../Checkbox/Checkbox.vue'\nimport type { CheckboxGroupEmits, CheckboxGroupProps } from './types'\n\ndefineOptions({ name: 'WxCheckboxGroup' })\n\nconst props = withDefaults(defineProps<CheckboxGroupProps>(), {\n options: undefined,\n disabled: undefined,\n size: undefined,\n name: undefined,\n inline: false,\n min: undefined,\n max: undefined,\n})\n\nconst emit = defineEmits<CheckboxGroupEmits>()\n\nconst model = defineModel<ChoiceValue[]>({ default: () => [] })\n\nconst field = useFormField(props)\n\n/** A group cannot be the target of a `for`, so the item label becomes a span. */\nfield.item?.registerLabelTarget(undefined)\n\nconst disabled = computed(() => props.disabled ?? field.disabled.value)\nconst size = computed(() => props.size ?? field.size.value)\n\nfunction toggle(value: ChoiceValue, checked: boolean) {\n const current = model.value ?? []\n if (checked) {\n if (current.includes(value)) return\n if (props.max !== undefined && current.length >= props.max) return\n model.value = [...current, value]\n } else {\n if (props.min !== undefined && current.length <= props.min) return\n model.value = current.filter((item) => item !== value)\n }\n emit('change', model.value)\n}\n\n/*\n * A box the limit will not let change is drawn disabled. Before, a click past `max` was ignored\n * by the group while the native input had already flipped: a box that looked unchecked and was\n * checked to the browser, and nothing said why.\n */\nfunction locked(value: ChoiceValue): boolean {\n const current = model.value ?? []\n const checked = current.includes(value)\n\n if (!checked) return props.max !== undefined && current.length >= props.max\n\n return props.min !== undefined && current.length <= props.min\n}\n\nprovide(checkboxGroupKey, {\n name: computed(() => props.name),\n modelValue: computed(() => model.value ?? []),\n disabled,\n size,\n toggle,\n locked,\n})\n</script>\n\n<template>\n <div\n :class=\"['wx-checkbox-group', { 'wx-checkbox-group--inline': inline }]\"\n role=\"group\"\n :aria-labelledby=\"field.item ? `${field.item.id.value}-label` : undefined\"\n :aria-describedby=\"field.describedBy.value\"\n >\n <slot>\n <wx-checkbox\n v-for=\"option in options\"\n :key=\"String(option.value)\"\n :value=\"option.value\"\n :label=\"option.label\"\n :disabled=\"option.disabled\"\n />\n </slot>\n </div>\n</template>\n\n<style scoped>\n.wx-checkbox-group {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n}\n\n.wx-checkbox-group--inline {\n flex-direction: row;\n flex-wrap: wrap;\n gap: var(--wx-space-16);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { ColBreakpoint, ColProps } from './types'\n\ndefineOptions({ name: 'WxCol' })\n\nconst props = withDefaults(defineProps<ColProps>(), {\n span: 24,\n offset: undefined,\n sm: undefined,\n md: undefined,\n lg: undefined,\n xl: undefined,\n order: undefined,\n as: 'div',\n})\n\nconst breakpoints = ['sm', 'md', 'lg', 'xl'] as const\n\nfunction normalize(value: ColBreakpoint) {\n return typeof value === 'number' ? { span: value } : value\n}\n\n/**\n * Every width is published as a variable and the media queries in the stylesheet\n * pick which one wins, each falling back to the breakpoint below it. That keeps the\n * component down to one rule per breakpoint instead of the 24 spans × 4 widths a\n * class-per-span grid needs.\n */\nconst style = computed(() => {\n const vars: Record<string, string> = { '--wx-col-span': String(props.span) }\n if (props.offset !== undefined) vars['--wx-col-offset'] = String(props.offset)\n if (props.order !== undefined) vars['--wx-col-order'] = String(props.order)\n\n for (const name of breakpoints) {\n const value = props[name]\n if (value === undefined) continue\n const { span, offset } = normalize(value)\n if (span !== undefined) vars[`--wx-col-span-${name}`] = String(span)\n if (offset !== undefined) vars[`--wx-col-offset-${name}`] = String(offset)\n }\n\n return vars\n})\n</script>\n\n<template>\n <component :is=\"as\" class=\"wx-col\" :style=\"style\">\n <slot />\n </component>\n</template>\n\n<style scoped>\n.wx-col {\n box-sizing: border-box;\n /* Half the gutter on each side; the row pulls the outer halves back. */\n flex: 0 0 auto;\n min-width: 0;\n padding-inline: calc(var(--wx-row-gutter, 0px) / 2);\n width: calc(var(--wx-col-span, 24) / 24 * 100%);\n margin-inline-start: calc(var(--wx-col-offset, 0) / 24 * 100%);\n order: var(--wx-col-order, 0);\n}\n\n/*\n * The breakpoints measure the row, not the window: `@container` against the\n * `wx-row` container `WxRow` establishes. A grid inside a drawer, a card or a main\n * column that lost half its width to a sidebar then reflows because *it* is narrow,\n * which is the question a column actually wants answered. The names in the props\n * keep their usual widths, so `:md=\"12\"` still means \"from 768px of room\".\n */\n@container wx-row (min-width: 640px) {\n .wx-col {\n width: calc(var(--wx-col-span-sm, var(--wx-col-span, 24)) / 24 * 100%);\n margin-inline-start: calc(var(--wx-col-offset-sm, var(--wx-col-offset, 0)) / 24 * 100%);\n }\n}\n\n@container wx-row (min-width: 768px) {\n .wx-col {\n width: calc(var(--wx-col-span-md, var(--wx-col-span-sm, var(--wx-col-span, 24))) / 24 * 100%);\n margin-inline-start: calc(\n var(--wx-col-offset-md, var(--wx-col-offset-sm, var(--wx-col-offset, 0))) / 24 * 100%\n );\n }\n}\n\n@container wx-row (min-width: 1024px) {\n .wx-col {\n width: calc(\n var(--wx-col-span-lg, var(--wx-col-span-md, var(--wx-col-span-sm, var(--wx-col-span, 24)))) /\n 24 * 100%\n );\n margin-inline-start: calc(\n var(\n --wx-col-offset-lg,\n var(--wx-col-offset-md, var(--wx-col-offset-sm, var(--wx-col-offset, 0)))\n ) /\n 24 * 100%\n );\n }\n}\n\n@container wx-row (min-width: 1280px) {\n .wx-col {\n width: calc(\n var(\n --wx-col-span-xl,\n var(\n --wx-col-span-lg,\n var(--wx-col-span-md, var(--wx-col-span-sm, var(--wx-col-span, 24)))\n )\n ) /\n 24 * 100%\n );\n margin-inline-start: calc(\n var(\n --wx-col-offset-xl,\n var(\n --wx-col-offset-lg,\n var(--wx-col-offset-md, var(--wx-col-offset-sm, var(--wx-col-offset, 0)))\n )\n ) /\n 24 * 100%\n );\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport {\n ColorAreaArea,\n ColorAreaRoot,\n ColorAreaThumb,\n ColorSliderRoot,\n ColorSliderThumb,\n ColorSliderTrack,\n PopoverAnchor,\n PopoverContent,\n PopoverPortal,\n PopoverRoot,\n colorToHex,\n convertToHsb,\n getAreaBackgroundStyle,\n getSliderBackgroundStyle,\n parseColor,\n} from 'reka-ui'\nimport type { Color } from 'reka-ui'\nimport { useFormField } from '../../composables/useFormField'\nimport type { ColorPickerEmits, ColorPickerProps } from './types'\nimport { useControlAttrs } from '../../composables/useControlAttrs'\n\ndefineOptions({ name: 'WxColorPicker', inheritAttrs: false })\n\n/* `class` and `style` belong to the control; the rest belongs to its input. */\nconst { rootAttrs, controlAttrs } = useControlAttrs()\n\nconst HEX = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i\n\nconst props = withDefaults(defineProps<ColorPickerProps>(), {\n presets: () => [],\n clearable: false,\n placeholder: '#000000',\n teleport: true,\n disabled: undefined,\n readonly: false,\n size: undefined,\n status: undefined,\n id: undefined,\n name: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<ColorPickerEmits>()\n\nconst model = defineModel<string | null>({ default: null })\n\nconst field = useFormField(props)\nconst open = ref(false)\n\n/** What the text box shows. Kept separate so a half-typed hex is not thrown away. */\nconst text = ref(model.value ?? '')\n\nwatch(model, (value) => {\n text.value = value ?? ''\n})\n\n/**\n * A hex parses into an RGB colour, and the picker works in HSB. Both the gradients and\n * the primitives take the space from the object unless told otherwise, so an unconverted\n * colour draws an RGB area — where the brightness gradient runs the other way and the\n * square looks upside down until the first drag replaces the object.\n */\nfunction toWorking(hex: string): Color {\n return convertToHsb(parseColor(hex))\n}\n\n/**\n * The picker works on a colour object, not on the hex string.\n *\n * A grey has no hue to speak of, so parsing #919191 back into channels invents one —\n * and re-deriving it on every pointer move is what made the hue strip jump from blue\n * to teal to red as the pointer travelled into the desaturated corner. Holding the\n * object keeps the hue the user chose even where the colour cannot express it.\n */\nconst working = ref<Color>(\n toWorking(model.value && HEX.test(model.value) ? model.value : '#427edd'),\n)\n\nwatch(model, (value) => {\n const hex = value && HEX.test(value) ? value : null\n if (!hex || hex === colorToHex(working.value).toLowerCase()) return\n working.value = toWorking(hex)\n})\n\n// The space is stated rather than read off the colour, so the gradients cannot drift\n// away from the channels the area and the slider are pinned to.\nconst areaStyle = computed(() =>\n getAreaBackgroundStyle(working.value, 'saturation', 'brightness', 'hsb'),\n)\nconst hueStyle = computed(() => getSliderBackgroundStyle(working.value, 'hue', 'hsb'))\n\nconst swatch = computed(() => (model.value && HEX.test(model.value) ? model.value : null))\n\nconst classes = computed(() => [\n 'wx-color-picker',\n `wx-color-picker--${field.size.value}`,\n {\n [`wx-color-picker--${field.status.value}`]: field.status.value !== 'default',\n 'is-open': open.value,\n 'is-disabled': field.disabled.value,\n },\n])\n\nfunction commit(value: string | null) {\n if (model.value === value) return\n model.value = value\n emit('change', value)\n}\n\n/** Typing is free-form; only a complete hex reaches the model. */\nfunction onInput(event: Event) {\n const value = (event.target as HTMLInputElement).value\n text.value = value\n if (HEX.test(value)) commit(value.toLowerCase())\n else if (value === '') commit(null)\n}\n\n/** On blur the box either shows a valid colour or goes back to the last one. */\nfunction onBlur() {\n if (text.value === '') {\n commit(null)\n return\n }\n const candidate = text.value.startsWith('#') ? text.value : `#${text.value}`\n if (HEX.test(candidate)) {\n commit(candidate.toLowerCase())\n text.value = candidate.toLowerCase()\n } else {\n text.value = model.value ?? ''\n }\n}\n\n/**\n * The two primitives do not agree on which event carries the new colour: the hue\n * slider reports through `change`, the saturation area through `update:modelValue`.\n * Both are bound on both, and only string payloads are taken — the slider can also\n * hand back a colour object. Committing twice is harmless: an unchanged value is\n * dropped.\n */\nfunction onColor(color: Color) {\n working.value = convertToHsb(color)\n commit(colorToHex(color).toLowerCase())\n}\n\n/** Presets and typing come in as hex and have to be parsed back into the picker. */\nfunction onHex(value: string) {\n const hex = value.toLowerCase()\n working.value = toWorking(hex)\n commit(hex)\n}\n\nfunction clear() {\n commit(null)\n text.value = ''\n}\n\nfunction openPicker() {\n if (!field.disabled.value && !props.readonly) open.value = true\n}\n</script>\n\n<template>\n <popover-root v-model:open=\"open\">\n <div :class=\"classes\" v-bind=\"rootAttrs\">\n <popover-anchor as-child>\n <div class=\"wx-color-picker__field\" @click=\"openPicker\">\n <button\n class=\"wx-color-picker__swatch\"\n type=\"button\"\n :disabled=\"field.disabled.value\"\n :aria-label=\"ariaLabel ?? 'Pick a colour'\"\n :style=\"swatch ? { background: swatch } : undefined\"\n :class=\"{ 'is-empty': !swatch }\"\n />\n\n <input\n :id=\"field.id.value\"\n v-bind=\"controlAttrs\"\n class=\"wx-color-picker__input\"\n type=\"text\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n :value=\"text\"\n :name=\"name\"\n :placeholder=\"placeholder\"\n :disabled=\"field.disabled.value\"\n :readonly=\"readonly\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"field.describedBy.value\"\n :aria-invalid=\"field.status.value === 'error' || undefined\"\n @input=\"onInput\"\n @blur=\"onBlur\"\n />\n\n <button\n v-if=\"clearable && swatch && !field.disabled.value\"\n class=\"wx-color-picker__clear\"\n type=\"button\"\n tabindex=\"-1\"\n aria-label=\"Clear\"\n @click.stop=\"clear\"\n >\n ✕\n </button>\n </div>\n </popover-anchor>\n\n <popover-portal :disabled=\"!teleport\">\n <popover-content class=\"wx-color-picker__panel\" :side-offset=\"4\" align=\"start\">\n <!-- Channels are stated: the defaults are RGB, which would move the hue as\n the pointer travels and disagree with the gradient drawn underneath. -->\n <color-area-root\n class=\"wx-color-picker__area\"\n color-space=\"hsb\"\n x-channel=\"saturation\"\n y-channel=\"brightness\"\n :model-value=\"working\"\n @update:color=\"onColor\"\n >\n <color-area-area class=\"wx-color-picker__area-surface\" :style=\"areaStyle\">\n <color-area-thumb class=\"wx-color-picker__thumb\" />\n </color-area-area>\n </color-area-root>\n\n <color-slider-root\n class=\"wx-color-picker__hue\"\n color-space=\"hsb\"\n channel=\"hue\"\n :model-value=\"working\"\n @update:color=\"onColor\"\n >\n <color-slider-track class=\"wx-color-picker__hue-track\" :style=\"hueStyle\">\n <color-slider-thumb class=\"wx-color-picker__thumb\" />\n </color-slider-track>\n </color-slider-root>\n\n <div v-if=\"presets.length\" class=\"wx-color-picker__presets\">\n <button\n v-for=\"preset in presets\"\n :key=\"preset\"\n class=\"wx-color-picker__preset\"\n type=\"button\"\n :style=\"{ background: preset }\"\n :aria-label=\"preset\"\n :aria-pressed=\"model === preset\"\n @click=\"onHex(preset)\"\n />\n </div>\n </popover-content>\n </popover-portal>\n </div>\n </popover-root>\n</template>\n\n<style scoped>\n.wx-color-picker {\n display: block;\n width: 100%;\n}\n\n.wx-color-picker__field {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n box-sizing: border-box;\n height: var(--wx-size-control-md);\n padding: 0 var(--wx-space-8) 0 var(--wx-space-6);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-control);\n color: var(--wx-text-default);\n font-size: var(--wx-font-size-control-md);\n cursor: text;\n transition: border-color var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-color-picker--sm .wx-color-picker__field {\n height: var(--wx-size-control-sm);\n font-size: var(--wx-font-size-control-sm);\n}\n\n.wx-color-picker--lg .wx-color-picker__field {\n height: var(--wx-size-control-lg);\n font-size: var(--wx-font-size-control-lg);\n}\n\n.wx-color-picker__field:hover {\n border-color: var(--wx-border-strong);\n}\n\n.wx-color-picker.is-open .wx-color-picker__field,\n.wx-color-picker__field:focus-within {\n border-color: var(--wx-border-focus);\n}\n\n.wx-color-picker--error .wx-color-picker__field {\n border-color: var(--wx-color-danger);\n}\n\n.wx-color-picker--success .wx-color-picker__field {\n border-color: var(--wx-color-success);\n}\n\n.wx-color-picker--warning .wx-color-picker__field {\n border-color: var(--wx-color-warning);\n}\n\n.wx-color-picker.is-disabled .wx-color-picker__field {\n background: var(--wx-bg-disabled);\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n.wx-color-picker__swatch {\n flex: 0 0 auto;\n width: 22px;\n height: 22px;\n padding: 0;\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-xs);\n cursor: pointer;\n}\n\n/* A chequerboard says \"no colour\" more clearly than an empty box. */\n.wx-color-picker__swatch.is-empty {\n background-image:\n linear-gradient(45deg, var(--wx-bg-fill) 25%, transparent 25%),\n linear-gradient(-45deg, var(--wx-bg-fill) 25%, transparent 25%),\n linear-gradient(45deg, transparent 75%, var(--wx-bg-fill) 75%),\n linear-gradient(-45deg, transparent 75%, var(--wx-bg-fill) 75%);\n background-size: 8px 8px;\n background-position:\n 0 0,\n 0 4px,\n 4px -4px,\n -4px 0;\n}\n\n.wx-color-picker__input {\n flex: 1 1 auto;\n min-width: 0;\n height: 100%;\n padding: 0;\n background: transparent;\n border: none;\n outline: none;\n color: inherit;\n font-family: var(--wx-font-family-mono);\n font-size: inherit;\n text-transform: lowercase;\n}\n\n.wx-color-picker__input::placeholder {\n color: var(--wx-text-placeholder);\n text-transform: none;\n}\n\n.wx-color-picker__clear {\n flex: 0 0 auto;\n width: 18px;\n height: 18px;\n padding: 0;\n background: transparent;\n border: none;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n line-height: 1;\n cursor: pointer;\n}\n\n.wx-color-picker__clear:hover {\n color: var(--wx-text-default);\n}\n</style>\n\n<style>\n/* Teleported panel. */\n.wx-color-picker__panel {\n z-index: var(--wx-z-index-popover);\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-10);\n width: 232px;\n padding: var(--wx-space-10);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-sm);\n box-shadow: var(--wx-shadow-popover);\n}\n\n.wx-color-picker__area,\n.wx-color-picker__area-surface {\n position: relative;\n width: 100%;\n height: 140px;\n border-radius: var(--wx-radius-xs);\n}\n\n.wx-color-picker__hue {\n position: relative;\n height: 14px;\n}\n\n.wx-color-picker__hue-track {\n /* Reka renders the track as an inline element, where width and height do nothing. */\n display: block;\n position: relative;\n width: 100%;\n height: 100%;\n border-radius: var(--wx-radius-full);\n}\n\n.wx-color-picker__thumb {\n width: 14px;\n height: 14px;\n background: transparent;\n border: 2px solid #fff;\n border-radius: var(--wx-radius-full);\n box-shadow: 0 0 0 1px rgb(0 0 0 / 0.35);\n}\n\n.wx-color-picker__thumb:focus-visible {\n outline: none;\n box-shadow:\n 0 0 0 1px rgb(0 0 0 / 0.35),\n var(--wx-ring-focus);\n}\n\n.wx-color-picker__presets {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-4);\n}\n\n.wx-color-picker__preset {\n width: 20px;\n height: 20px;\n padding: 0;\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-xs);\n cursor: pointer;\n}\n\n.wx-color-picker__preset[aria-pressed='true'] {\n box-shadow: 0 0 0 2px var(--wx-color-primary);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { ContainerProps } from './types'\n\ndefineOptions({ name: 'WxContainer' })\n\nconst props = withDefaults(defineProps<ContainerProps>(), {\n direction: 'vertical',\n fullHeight: false,\n viewport: false,\n as: 'div',\n})\n\nconst classes = computed(() => [\n 'wx-container',\n `wx-container--${props.direction}`,\n {\n 'wx-container--full-height': props.fullHeight,\n 'wx-container--viewport': props.viewport,\n },\n])\n</script>\n\n<template>\n <component :is=\"as\" :class=\"classes\">\n <slot />\n </component>\n</template>\n\n<style scoped>\n.wx-container {\n display: flex;\n box-sizing: border-box;\n flex: 1 1 auto;\n /*\n * A flex item refuses to shrink below its content by default, which is what makes\n * a scrolling main column overflow the page instead of scrolling inside it.\n */\n min-width: 0;\n min-height: 0;\n background: var(--wx-bg-body);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n}\n\n.wx-container--vertical {\n flex-direction: column;\n}\n\n.wx-container--horizontal {\n flex-direction: row;\n}\n\n.wx-container--full-height {\n /* `dvh` rather than `vh`: on a phone the browser chrome eats the difference. */\n min-height: 100dvh;\n}\n\n/*\n * An application shell rather than a document: the container *is* the viewport, and\n * a column inside it scrolls instead of the page. Without the cap, a `WxMain` marked\n * `scroll` has nothing to scroll against — the container grows with the content, and\n * the pane never overflows, so it never scrolls and the page ends up clipped.\n */\n.wx-container--viewport {\n height: 100dvh;\n max-height: 100dvh;\n overflow: hidden;\n}\n\n/* Nested: an inner container fills the shell it is in rather than the window again. */\n.wx-container--viewport .wx-container--viewport {\n height: auto;\n max-height: none;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { StatisticProps } from './types'\n\ndefineOptions({ name: 'WxStatistic' })\n\nconst props = withDefaults(defineProps<StatisticProps>(), {\n value: undefined,\n title: undefined,\n precision: undefined,\n locale: undefined,\n grouping: true,\n prefix: undefined,\n suffix: undefined,\n formatter: undefined,\n size: 'md',\n tone: 'strong',\n align: undefined,\n})\n\nconst display = computed(() => {\n if (props.formatter) return props.formatter(props.value)\n if (typeof props.value !== 'number') return props.value ?? ''\n\n /*\n * `Intl` rather than a hand-rolled separator: 268 500 in one locale is 268,500 in\n * another, and an admin panel that ships in several languages should not decide.\n */\n return new Intl.NumberFormat(props.locale, {\n useGrouping: props.grouping,\n minimumFractionDigits: props.precision,\n maximumFractionDigits: props.precision,\n }).format(props.value)\n})\n\nconst classes = computed(() => [\n 'wx-statistic',\n `wx-statistic--${props.size}`,\n `wx-statistic--tone-${props.tone}`,\n { [`wx-statistic--align-${props.align}`]: Boolean(props.align) },\n])\n</script>\n\n<template>\n <div :class=\"classes\">\n <div v-if=\"title || $slots.title\" class=\"wx-statistic__title\">\n <slot name=\"title\">{{ title }}</slot>\n </div>\n\n <div class=\"wx-statistic__value\">\n <span v-if=\"prefix || $slots.prefix\" class=\"wx-statistic__affix\">\n <slot name=\"prefix\">{{ prefix }}</slot>\n </span>\n\n <span class=\"wx-statistic__number\">\n <slot name=\"value\">{{ display }}</slot>\n </span>\n\n <span v-if=\"suffix || $slots.suffix\" class=\"wx-statistic__affix\">\n <slot name=\"suffix\">{{ suffix }}</slot>\n </span>\n </div>\n\n <div v-if=\"$slots.default\" class=\"wx-statistic__footer\">\n <slot />\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-statistic {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n min-width: 0;\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n}\n\n.wx-statistic--align-center {\n text-align: center;\n align-items: center;\n}\n\n.wx-statistic--align-end {\n text-align: end;\n align-items: flex-end;\n}\n\n.wx-statistic--align-start {\n text-align: start;\n align-items: flex-start;\n}\n\n.wx-statistic--align-justify {\n text-align: justify;\n}\n\n.wx-statistic__title {\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n line-height: var(--wx-font-line-height-normal);\n}\n\n.wx-statistic--sm .wx-statistic__title {\n font-size: var(--wx-font-size-xs);\n}\n\n.wx-statistic__value {\n display: flex;\n align-items: baseline;\n gap: var(--wx-space-4);\n color: var(--wx-statistic-color, var(--wx-text-strong));\n /* Digits of equal width, so a ticking number does not jitter. */\n font-variant-numeric: tabular-nums;\n font-weight: var(--wx-font-weight-semibold);\n line-height: var(--wx-font-line-height-tight);\n}\n\n.wx-statistic--sm .wx-statistic__value {\n font-size: var(--wx-font-size-lg);\n}\n\n.wx-statistic--md .wx-statistic__value {\n font-size: var(--wx-font-size-2xl);\n}\n\n.wx-statistic--lg .wx-statistic__value {\n font-size: var(--wx-font-size-3xl);\n}\n\n.wx-statistic__number {\n min-width: 0;\n}\n\n.wx-statistic__affix {\n color: var(--wx-text-muted);\n font-size: 0.65em;\n font-weight: var(--wx-font-weight-medium);\n}\n\n.wx-statistic__footer {\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n}\n\n/* tones */\n.wx-statistic--tone-default {\n --wx-statistic-color: var(--wx-text-default);\n}\n\n.wx-statistic--tone-strong {\n --wx-statistic-color: var(--wx-text-strong);\n}\n\n.wx-statistic--tone-muted {\n --wx-statistic-color: var(--wx-text-muted);\n}\n\n.wx-statistic--tone-placeholder {\n --wx-statistic-color: var(--wx-text-placeholder);\n}\n\n.wx-statistic--tone-primary {\n --wx-statistic-color: var(--wx-color-primary);\n}\n\n.wx-statistic--tone-success {\n --wx-statistic-color: var(--wx-color-success-active);\n}\n\n.wx-statistic--tone-warning {\n --wx-statistic-color: var(--wx-color-warning-active);\n}\n\n.wx-statistic--tone-danger {\n --wx-statistic-color: var(--wx-color-danger);\n}\n\n.wx-statistic--tone-info {\n --wx-statistic-color: var(--wx-color-info-active);\n}\n\n.wx-statistic--tone-inverse {\n --wx-statistic-color: var(--wx-text-inverse);\n}\n</style>\n","import type { CountdownTarget } from './types'\n\n/** Largest unit first: each token takes its share of what the previous ones left. */\nconst units: [token: string, ms: number][] = [\n ['DD', 86_400_000],\n ['HH', 3_600_000],\n ['mm', 60_000],\n ['ss', 1_000],\n ['SSS', 1],\n]\n\n/**\n * Renders a span of milliseconds against a pattern of `DD`, `HH`, `mm`, `ss`, `SSS`.\n *\n * Only the tokens the pattern actually contains consume time, so `mm:ss` on two hours\n * prints `120:00` rather than silently dropping the hours. Everything else in the\n * pattern is copied through — mind that a literal word containing a token (`ss` in\n * \"passed\") would be replaced.\n */\nexport function formatCountdown(ms: number, format = 'HH:mm:ss'): string {\n let remaining = Math.max(0, Math.floor(ms))\n let out = format\n\n for (const [token, unit] of units) {\n if (!out.includes(token)) continue\n const value = Math.floor(remaining / unit)\n remaining -= value * unit\n out = out.replace(token, String(value).padStart(token.length, '0'))\n }\n\n return out\n}\n\n/** Normalises whatever the caller passed as a target into a timestamp. */\nexport function toTimestamp(value: CountdownTarget): number {\n if (typeof value === 'number') return value\n if (value instanceof Date) return value.getTime()\n const parsed = Date.parse(value)\n return Number.isNaN(parsed) ? 0 : parsed\n}\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport WxStatistic from '../Statistic/Statistic.vue'\nimport { formatCountdown, toTimestamp } from './format'\nimport type { CountdownEmits, CountdownProps } from './types'\n\ndefineOptions({ name: 'WxCountdown' })\n\nconst props = withDefaults(defineProps<CountdownProps>(), {\n format: 'HH:mm:ss',\n interval: 1000,\n title: undefined,\n prefix: undefined,\n suffix: undefined,\n size: 'md',\n tone: 'strong',\n align: undefined,\n})\n\nconst emit = defineEmits<CountdownEmits>()\n\nconst target = computed(() => toTimestamp(props.value))\nconst remaining = ref(Math.max(0, target.value - Date.now()))\n\nlet timer: ReturnType<typeof setInterval> | undefined\n\nfunction stop() {\n if (timer === undefined) return\n clearInterval(timer)\n timer = undefined\n}\n\nfunction tick() {\n const left = Math.max(0, target.value - Date.now())\n remaining.value = left\n emit('change', left)\n\n /* `finish` fires once: the timer stops before the next tick can repeat it. */\n if (left === 0) {\n stop()\n emit('finish')\n }\n}\n\nfunction start() {\n stop()\n if (remaining.value === 0) return\n timer = setInterval(tick, Math.max(16, props.interval))\n}\n\n/*\n * A new target — or a new tick rate — restarts the clock rather than letting it\n * drift. The value is recomputed either way; the timer only exists once the\n * component is mounted, which is what keeps it off the server: an interval started\n * during SSR is never cleared, and it holds the render process open forever.\n */\nlet running = false\n\nwatch(\n [target, () => props.interval],\n () => {\n remaining.value = Math.max(0, target.value - Date.now())\n if (running) start()\n },\n { immediate: true },\n)\n\nonMounted(() => {\n running = true\n start()\n})\n\nonBeforeUnmount(() => {\n running = false\n stop()\n})\n\nconst text = computed(() => formatCountdown(remaining.value, props.format))\n\ndefineExpose({ remaining })\n</script>\n\n<template>\n <wx-statistic\n class=\"wx-countdown\"\n :value=\"text\"\n :title=\"title\"\n :prefix=\"prefix\"\n :suffix=\"suffix\"\n :size=\"size\"\n :tone=\"tone\"\n :align=\"align\"\n >\n <template v-if=\"$slots.title\" #title><slot name=\"title\" /></template>\n <template v-if=\"$slots.prefix\" #prefix><slot name=\"prefix\" /></template>\n <template v-if=\"$slots.suffix\" #suffix><slot name=\"suffix\" /></template>\n <template v-if=\"$slots.value\" #value\n ><slot name=\"value\" :remaining=\"remaining\" :text=\"text\"\n /></template>\n <template v-if=\"$slots.default\" #default><slot /></template>\n </wx-statistic>\n</template>\n","import type { RootProps } from '@vuepic/vue-datepicker'\n\n/** What `@vuepic/vue-datepicker` wants for its language: a date-fns locale object. */\nexport type DateFnsLocale = NonNullable<RootProps['locale']>\n\ntype Width = 'narrow' | 'short' | 'abbreviated' | 'wide'\ntype Context = 'formatting' | 'standalone'\n\nconst cache = new Map<string, DateFnsLocale>()\n\n/**\n * Builds a date-fns locale out of `Intl`.\n *\n * The picker bundles exactly one language — `en-US` — and takes any other as a date-fns\n * locale object, so a panel in Russian gets an English calendar unless one is handed in.\n * Reaching for `date-fns/locale` would mean a runtime dependency on date-fns and a chunk\n * per language; the browser already carries every one of them, so the names come from\n * `Intl.DateTimeFormat` and are shaped here into what date-fns reads.\n *\n * Only what the picker asks for is filled in honestly: month, weekday and day-period\n * names, the era, and enough of `match` to parse a typed-in date back. Quarter names and\n * ordinal suffixes have no `Intl` source and fall back to digits — the picker reaches for\n * them only in a quarter picker and in a day cell's `aria-label`, where a bare number\n * reads correctly in most languages anyway.\n */\nexport function dateFnsLocale(tag: string): DateFnsLocale {\n const cached = cache.get(tag)\n if (cached) return cached\n\n const built = build(supported(tag) ? tag : 'en-US')\n cache.set(tag, built)\n\n return built\n}\n\n/** `Intl` throws a `RangeError` on a malformed tag rather than falling back. */\nfunction supported(tag: string): boolean {\n try {\n new Intl.DateTimeFormat(tag)\n\n return true\n } catch {\n return false\n }\n}\n\nfunction build(tag: string): DateFnsLocale {\n const months = memo((key: string) => {\n const [width, context] = key.split(':') as [Width, Context]\n\n return monthNames(tag, width, context)\n })\n const days = memo((width: string) => dayNames(tag, width as Width))\n const periods = memo(() => dayPeriodNames(tag))\n const eras = memo((width: string) => eraNames(tag, width as Width))\n const quarters = memo((width: string) => quarterNames(width as Width))\n\n const localize: DateFnsLocale['localize'] = {\n ordinalNumber: (value) => ordinalNumber(tag, Number(value)),\n era: (value, options) => eras(options?.width ?? 'wide')[Number(value)] ?? '',\n quarter: (value, options) => quarters(options?.width ?? 'wide')[Number(value) - 1] ?? '',\n month: (value, options) =>\n months(`${options?.width ?? 'wide'}:${options?.context ?? 'formatting'}`)[Number(value)] ??\n '',\n day: (value, options) => days(options?.width ?? 'wide')[Number(value)] ?? '',\n // `Intl` offers one form of \"am\"; the widths date-fns asks for do not exist to give.\n dayPeriod: (value) => periods('')[String(value)] ?? '',\n }\n\n const match: DateFnsLocale['match'] = {\n ordinalNumber: (str) => {\n const found = /^(\\d+)(?:st|nd|rd|th|[^\\s\\d]{0,3})?/i.exec(str)\n if (!found) return null\n\n return { value: Number(found[1]), rest: str.slice(found[0].length) }\n },\n era: nameMatcher(() => widths.flatMap((width) => indexed<Matched<'era'>>(eras(width)))),\n quarter: nameMatcher(() =>\n widths.flatMap((width) =>\n quarters(width).map((name, index) => ({ name, value: (index + 1) as Matched<'quarter'> })),\n ),\n ),\n month: nameMatcher(() =>\n widths.flatMap((width) =>\n contexts.flatMap((context) => indexed<Matched<'month'>>(months(`${width}:${context}`))),\n ),\n ),\n day: nameMatcher(() => widths.flatMap((width) => indexed<Matched<'day'>>(days(width)))),\n dayPeriod: nameMatcher(() =>\n Object.entries(periods('')).map(([value, name]) => ({\n name,\n value: value as Matched<'dayPeriod'>,\n })),\n ),\n }\n\n return {\n code: tag,\n localize,\n match,\n formatLong: formatLong(tag),\n /*\n * The picker never reaches for relative or distance wording — it draws a calendar,\n * not \"3 days ago\". The shape is part of the type, so it is filled in rather than\n * left out.\n */\n formatDistance: () => '',\n formatRelative: () => '',\n options: { weekStartsOn: weekStartsOn(tag), firstWeekContainsDate: 1 },\n } as DateFnsLocale\n}\n\nconst widths: Width[] = ['narrow', 'short', 'abbreviated', 'wide']\nconst contexts: Context[] = ['formatting', 'standalone']\n\nfunction memo<T>(make: (key: string) => T): (key: string) => T {\n const store = new Map<string, T>()\n\n return (key) => {\n if (!store.has(key)) store.set(key, make(key))\n\n return store.get(key) as T\n }\n}\n\n/** What date-fns expects a given matcher to hand back — `Month`, `Day` and friends. */\ntype Matched<K extends keyof DateFnsLocale['match']> = NonNullable<\n ReturnType<DateFnsLocale['match'][K]>\n>['value']\n\nfunction indexed<T>(names: string[]): { name: string; value: T }[] {\n return names.map((name, value) => ({ name, value: value as T }))\n}\n\n/**\n * Longest name first, so \"сентябрь\" is not cut short by the abbreviated \"сент\" that\n * starts the same way.\n */\nfunction nameMatcher<T>(entries: () => { name: string; value: T }[]) {\n return (str: string) => {\n const sorted = [...entries()].sort((a, b) => b.name.length - a.name.length)\n const lower = str.toLowerCase()\n\n for (const { name, value } of sorted) {\n if (name && lower.startsWith(name.toLowerCase())) {\n return { value, rest: str.slice(name.length) }\n }\n }\n\n return null\n }\n}\n\n/** A year with no daylight-saving surprises, read in UTC so the day never slips. */\nfunction at(month: number, day = 15, hour = 12): Date {\n return new Date(Date.UTC(2021, month, day, hour))\n}\n\nfunction partOf(format: Intl.DateTimeFormat, date: Date, type: Intl.DateTimeFormatPartTypes) {\n return format.formatToParts(date).find((part) => part.type === type)?.value ?? ''\n}\n\n/**\n * Standalone and formatting month names differ in half of Europe: Russian heads the\n * calendar with \"сентябрь\" but writes \"15 сентября\" in a sentence. `Intl` draws the same\n * line — a month on its own comes out standalone, a month beside a day comes out in the\n * sentence form — so the two are read from two formatters.\n */\nfunction monthNames(tag: string, width: Width, context: Context): string[] {\n const month = width === 'wide' ? 'long' : width === 'narrow' ? 'narrow' : 'short'\n const format = new Intl.DateTimeFormat(tag, {\n month,\n ...(context === 'formatting' ? { day: 'numeric' as const } : {}),\n timeZone: 'UTC',\n })\n\n return Array.from({ length: 12 }, (_, index) => partOf(format, at(index), 'month'))\n}\n\nfunction dayNames(tag: string, width: Width): string[] {\n const weekday = width === 'wide' ? 'long' : width === 'narrow' ? 'narrow' : 'short'\n const format = new Intl.DateTimeFormat(tag, { weekday, timeZone: 'UTC' })\n // 1 August 2021 was a Sunday, which is index 0 in date-fns.\n const names = Array.from({ length: 7 }, (_, index) => format.format(at(7, 1 + index)))\n\n /*\n * date-fns keeps a two-letter weekday (\"Su\", \"вс\") that `Intl` does not offer, and the\n * picker's own header format asks for exactly that one. Cutting the abbreviated name\n * down lands on it in every language checked — \"Sun\" to \"Su\", \"dim.\" to \"di\", \"вс\" as\n * it already is.\n */\n return width === 'short'\n ? names.map((name) => [...name.replace(/\\.$/, '')].slice(0, 2).join(''))\n : names\n}\n\nfunction dayPeriodNames(tag: string): Record<string, string> {\n const format = new Intl.DateTimeFormat(tag, { hour: 'numeric', hour12: true, timeZone: 'UTC' })\n const am = partOf(format, at(0, 1, 9), 'dayPeriod') || 'AM'\n const pm = partOf(format, at(0, 1, 21), 'dayPeriod') || 'PM'\n\n return { am, pm, midnight: am, noon: pm, morning: am, afternoon: pm, evening: pm, night: pm }\n}\n\nfunction eraNames(tag: string, width: Width): string[] {\n const era = width === 'wide' ? 'long' : width === 'narrow' ? 'narrow' : 'short'\n const format = new Intl.DateTimeFormat(tag, { era, year: 'numeric', timeZone: 'UTC' })\n const bc = at(0, 1)\n bc.setUTCFullYear(-500)\n\n return [partOf(format, bc, 'era'), partOf(format, at(0, 1), 'era')]\n}\n\n/**\n * `Intl` has no quarter names, and no calendar in this kit shows one — the picker only\n * asks in a quarter picker, which none of the presets is.\n */\nfunction quarterNames(width: Width): string[] {\n return width === 'narrow' ? ['1', '2', '3', '4'] : ['Q1', 'Q2', 'Q3', 'Q4']\n}\n\n/**\n * Only English spells its ordinals with a suffix; elsewhere the digits alone are what a\n * reader expects, which is also what date-fns' own non-English locales mostly return.\n */\nfunction ordinalNumber(tag: string, value: number): string {\n if (!tag.toLowerCase().startsWith('en')) return String(value)\n\n const rest = value % 100\n if (rest >= 11 && rest <= 13) return `${value}th`\n\n return `${value}${['th', 'st', 'nd', 'rd'][value % 10] ?? 'th'}`\n}\n\n/**\n * `P` and `p` tokens, which only a caller's own `format` can reach. `Intl` will not hand\n * out a pattern, so the order of the parts is read off a formatted date and the rest is\n * the conventional shape for that order.\n */\nfunction formatLong(tag: string): DateFnsLocale['formatLong'] {\n const parts = new Intl.DateTimeFormat(tag, { timeZone: 'UTC' })\n .formatToParts(at(0, 1))\n .filter((part) => part.type === 'day' || part.type === 'month' || part.type === 'year')\n .map((part) => part.type[0])\n .join('')\n\n const date =\n parts === 'mdy'\n ? { full: 'EEEE, MMMM do, y', long: 'MMMM do, y', medium: 'MMM d, y', short: 'MM/dd/yyyy' }\n : parts === 'ymd'\n ? { full: 'y MMMM d, EEEE', long: 'y MMMM d', medium: 'y MMM d', short: 'yyyy-MM-dd' }\n : { full: 'EEEE, d MMMM y', long: 'd MMMM y', medium: 'd MMM y', short: 'dd.MM.yyyy' }\n\n const hour12 = new Intl.DateTimeFormat(tag, { hour: 'numeric', timeZone: 'UTC' })\n .formatToParts(at(0, 1, 21))\n .some((part) => part.type === 'dayPeriod')\n\n const time = hour12\n ? { full: 'h:mm:ss a zzzz', long: 'h:mm:ss a z', medium: 'h:mm:ss a', short: 'h:mm a' }\n : { full: 'HH:mm:ss zzzz', long: 'HH:mm:ss z', medium: 'HH:mm:ss', short: 'HH:mm' }\n\n const dateTime = {\n full: '{{date}} {{time}}',\n long: '{{date}} {{time}}',\n medium: '{{date}}, {{time}}',\n short: '{{date}}, {{time}}',\n }\n\n const pick = (formats: Record<string, string>) => (options: { width?: string }) =>\n formats[options?.width ?? 'full'] ?? formats.full\n\n return { date: pick(date), time: pick(time), dateTime: pick(dateTime) }\n}\n\n/** `getWeekInfo` counts Monday as 1 and Sunday as 7; date-fns counts Sunday as 0. */\nfunction weekStartsOn(tag: string): 0 | 1 | 2 | 3 | 4 | 5 | 6 {\n type WithWeekInfo = Intl.Locale & { getWeekInfo?: () => { firstDay: number } }\n\n try {\n const first = (new Intl.Locale(tag) as WithWeekInfo).getWeekInfo?.().firstDay\n\n if (first) return (first % 7) as 0 | 1 | 2 | 3 | 4 | 5 | 6\n } catch {\n // Not every engine carries week data; Monday is this kit's default anyway.\n }\n\n return 1\n}\n","import { computed, inject, provide, type ComputedRef, type InjectionKey, type Ref } from 'vue'\nimport { dateFnsLocale, type DateFnsLocale } from '../internal/dateLocale'\n\n/** A BCP-47 tag, or something that reads one — the application's own language. */\nexport type DateLocaleSource = string | Ref<string> | ComputedRef<string>\n\n/**\n * The language every date picker below draws its calendar in.\n *\n * This is the language of the *interface*, not of the content: an administrator who\n * switched the panel to Russian on a machine set to English expects the month header to\n * follow the switch, and neither the browser nor the site's content languages know about\n * it. A `locale` prop on the picker still wins over what is provided here.\n */\nexport const dateLocaleKey: InjectionKey<DateLocaleSource> = Symbol('wx-date-locale')\n\n/**\n * Tells every date picker below which language to draw its calendar in.\n *\n * ```ts\n * app.provide(dateLocaleKey, computed(() => admin.i18n.state.locale))\n * ```\n */\nexport function provideDateLocale(locale: DateLocaleSource): void {\n provide(dateLocaleKey, locale)\n}\n\n/** The calendar's language: the `locale` prop, then the application's, then the browser's. */\nexport function useDateLocale(\n locale: () => string | DateFnsLocale | undefined,\n): ComputedRef<DateFnsLocale> {\n const provided = inject(dateLocaleKey, undefined)\n\n return computed(() => {\n const asked = locale()\n // A hand-built date-fns locale is the picker's own escape hatch; it goes straight on.\n if (asked && typeof asked !== 'string') return asked\n\n const tag = asked ?? (typeof provided === 'string' ? provided : provided?.value)\n\n return dateFnsLocale(tag || browserLocale())\n })\n}\n\nfunction browserLocale(): string {\n return (typeof navigator === 'undefined' ? '' : navigator.language) || 'en-US'\n}\n","import { computed, inject, provide, type ComputedRef, type InjectionKey, type Ref } from 'vue'\n\n/** An IANA zone such as `'Asia/Hong_Kong'`, or something that reads one — or nothing yet. */\nexport type DateTimezoneSource =\n string | Ref<string | null | undefined> | ComputedRef<string | null | undefined>\n\n/**\n * The zone every date picker below shows and takes a *moment* in.\n *\n * A moment travels with its offset (`2026-10-12T09:30:00+08:00`), and without a zone the\n * picker draws it on the reader's own clock: an event at half past nine in Hong Kong reads\n * 04:30 to an editor in Moscow, and whatever they pick goes back with Moscow's offset. A site\n * has one clock — the one its events, opening hours and publication times are written in — so\n * a panel provides that zone here and every picker of a moment follows it. A `timezone` prop on\n * the picker still wins over what is provided.\n */\nexport const dateTimezoneKey: InjectionKey<DateTimezoneSource> = Symbol('wx-date-timezone')\n\n/**\n * Tells every date picker below which zone a moment is shown and entered in.\n *\n * ```ts\n * app.provide(dateTimezoneKey, computed(() => manifest.value?.timezone))\n * ```\n */\nexport function provideDateTimezone(timezone: DateTimezoneSource): void {\n provide(dateTimezoneKey, timezone)\n}\n\n/** The zone: the `timezone` prop, then the application's, then none — the reader's own. */\nexport function useDateTimezone(\n timezone: () => string | undefined,\n): ComputedRef<string | undefined> {\n const provided = inject(dateTimezoneKey, undefined)\n\n return computed(() => {\n const asked = timezone() ?? (typeof provided === 'string' ? provided : provided?.value)\n\n return asked ? asked : undefined\n })\n}\n\n/** The zone this browser keeps its clock in, or an empty string where it will not say. */\nexport function readersTimezone(): string {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone ?? ''\n } catch {\n return ''\n }\n}\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { VueDatePicker } from '@vuepic/vue-datepicker'\nimport { useFormField } from '../../composables/useFormField'\nimport '../../styles/datepicker.css'\nimport type { DatePickerEmits, DatePickerModelValue, DatePickerProps } from './types'\nimport { useControlAttrs } from '../../composables/useControlAttrs'\nimport { useDateLocale } from '../../composables/useDateLocale'\nimport { readersTimezone, useDateTimezone } from '../../composables/useDateTimezone'\n\ndefineOptions({ name: 'WxDatePicker', inheritAttrs: false })\n\n/* `class` and `style` belong to the control; the rest belongs to its input. */\nconst { rootAttrs, controlAttrs } = useControlAttrs()\n\nconst props = withDefaults(defineProps<DatePickerProps>(), {\n type: 'date',\n valueFormat: undefined,\n format: undefined,\n placeholder: undefined,\n clearable: true,\n minDate: undefined,\n maxDate: undefined,\n seconds: false,\n minutesIncrement: 1,\n is24: true,\n locale: undefined,\n timezone: undefined,\n weekStart: 1,\n autoApply: true,\n textInput: false,\n teleport: true,\n disabled: undefined,\n readonly: false,\n size: undefined,\n status: undefined,\n id: undefined,\n name: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<DatePickerEmits>()\n\n/*\n * Every slot is passed straight through to the underlying picker, so this component's\n * slots are whatever the caller hands it. Saying so explicitly is what keeps the\n * declaration honest: left to infer, the slot type is read off a template that\n * enumerates `$slots`, and TypeScript answers that circle by emitting `any` — which\n * takes the props of this component down with it.\n */\ndefineSlots<Record<string, (props: Record<string, unknown>) => unknown>>()\n\nconst model = defineModel<DatePickerModelValue>({ default: null })\n\nconst field = useFormField(props)\n\n/*\n * The picker bundles English and nothing else, so without this the month header and the\n * weekday row stay English under a panel drawn in any other language.\n */\nconst locale = useDateLocale(() => props.locale)\n\nconst hasTime = computed(() => props.type !== 'date')\n\n/**\n * What the model holds. Defaults match the column types a Laravel migration\n * produces, so the value can go to the API untouched; `'date'` opts out and keeps\n * `Date` objects.\n */\nconst modelType = computed(() => {\n if (props.valueFormat === 'date') return undefined\n if (props.valueFormat) return props.valueFormat\n if (props.type === 'time') return props.seconds ? 'HH:mm:ss' : 'HH:mm'\n if (props.type === 'datetime') return props.seconds ? 'yyyy-MM-dd HH:mm:ss' : 'yyyy-MM-dd HH:mm'\n return 'yyyy-MM-dd'\n})\n\nconst asked = useDateTimezone(() => props.timezone)\n\n/**\n * The zone handed to the picker — only for a value that is a moment. A format without an\n * offset is a wall clock (a Laravel `datetime` column read as written), and moving it into a\n * zone would shift the hour it names; a plain date would even change its day.\n */\nconst timezone = computed(() =>\n typeof modelType.value === 'string' && /[Xx]/.test(modelType.value.replace(/'[^']*'/g, ''))\n ? asked.value\n : undefined,\n)\n\n/** What the field shows. Day-first, because this kit is aimed at European admins. */\nconst displayFormat = computed(() => {\n if (props.format) return props.format\n const time = props.seconds ? 'HH:mm:ss' : 'HH:mm'\n if (props.type === 'time') return time\n if (props.type === 'datetime') {\n // A clock in somebody else's zone says whose it is: \"09:30\" alone reads as the reader's own.\n const zone = timezone.value && timezone.value !== readersTimezone() ? \" 'GMT'xxx\" : ''\n\n return `dd.MM.yyyy ${time}${zone}`\n }\n return 'dd.MM.yyyy'\n})\n\n/**\n * The overlay is sized to a calendar (`modeHeight`, 255 by default) so switching\n * between panes does not resize the menu. A time-only picker has no calendar to\n * match, and the default leaves ~150px of empty space around the columns.\n */\nconst config = computed(() => (props.type === 'time' ? { modeHeight: 125 } : undefined))\n\nconst timeConfig = computed(() => ({\n enableTimePicker: hasTime.value,\n enableSeconds: props.seconds,\n is24: props.is24,\n minutesIncrement: props.minutesIncrement,\n}))\n\nconst inputAttrs = computed(() => ({\n id: field.id.value,\n name: props.name,\n clearable: props.clearable,\n // The library reads `state: false` as invalid; leaving it undefined means neutral.\n state: field.status.value === 'error' ? false : undefined,\n 'aria-label': props.ariaLabel,\n 'aria-describedby': field.describedBy.value,\n}))\n\nconst classes = computed(() => [\n 'wx-datepicker',\n `wx-datepicker--${field.size.value}`,\n {\n [`wx-datepicker--${field.status.value}`]: field.status.value !== 'default',\n 'is-disabled': field.disabled.value,\n },\n])\n\nfunction onUpdate(value: DatePickerModelValue) {\n model.value = value\n emit('change', value)\n}\n\nfunction onCleared() {\n model.value = null\n emit('change', null)\n emit('clear')\n}\n</script>\n\n<template>\n <div :class=\"classes\" v-bind=\"rootAttrs\">\n <vue-date-picker\n :model-value=\"model\"\n :model-type=\"modelType\"\n :formats=\"{ input: displayFormat }\"\n :time-picker=\"type === 'time'\"\n :time-config=\"timeConfig\"\n :config=\"config\"\n :input-attrs=\"inputAttrs\"\n :ui=\"{ input: 'wx-datepicker__input', menu: 'wx-datepicker__menu' }\"\n :placeholder=\"placeholder\"\n :min-date=\"minDate\"\n :max-date=\"maxDate\"\n :locale=\"locale\"\n :timezone=\"timezone\"\n :week-start=\"weekStart\"\n :auto-apply=\"autoApply\"\n :text-input=\"textInput\"\n :teleport=\"teleport\"\n :disabled=\"field.disabled.value\"\n :readonly=\"readonly\"\n v-bind=\"controlAttrs\"\n @update:model-value=\"onUpdate\"\n @cleared=\"onCleared\"\n @open=\"emit('open')\"\n @closed=\"emit('close')\"\n >\n <template v-for=\"(_, name) in $slots\" #[name]=\"slotProps\">\n <slot :name=\"name\" v-bind=\"slotProps ?? {}\" />\n </template>\n </vue-date-picker>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { VueDatePicker } from '@vuepic/vue-datepicker'\nimport { useFormField } from '../../composables/useFormField'\nimport '../../styles/datepicker.css'\nimport type { DateRangePickerEmits, DateRangePickerModelValue, DateRangePickerProps } from './types'\nimport { useControlAttrs } from '../../composables/useControlAttrs'\nimport { useDateLocale } from '../../composables/useDateLocale'\n\ndefineOptions({ name: 'WxDateRangePicker', inheritAttrs: false })\n\n/* `class` and `style` belong to the control; the rest belongs to its input. */\nconst { rootAttrs, controlAttrs } = useControlAttrs()\n\nconst props = withDefaults(defineProps<DateRangePickerProps>(), {\n valueFormat: undefined,\n format: undefined,\n placeholder: undefined,\n clearable: true,\n minDate: undefined,\n maxDate: undefined,\n months: 2,\n locale: undefined,\n weekStart: 1,\n autoApply: true,\n textInput: false,\n teleport: true,\n disabled: undefined,\n readonly: false,\n size: undefined,\n status: undefined,\n id: undefined,\n name: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<DateRangePickerEmits>()\n\n/*\n * Every slot is passed straight through to the picker underneath, so this component's\n * slots are whatever the caller hands it. Saying so explicitly is what keeps the\n * declaration honest: left to infer, the slot type is read off a template that\n * enumerates the slots themselves, and TypeScript answers that circle by emitting\n * `any`.\n */\ndefineSlots<Record<string, (props: Record<string, unknown>) => unknown>>()\n\nconst model = defineModel<DateRangePickerModelValue>({ default: null })\n\nconst field = useFormField(props)\n\n/*\n * The picker bundles English and nothing else, so without this the month header and the\n * weekday row stay English under a panel drawn in any other language.\n */\nconst locale = useDateLocale(() => props.locale)\n\nconst modelType = computed(() =>\n props.valueFormat === 'date' ? undefined : (props.valueFormat ?? 'yyyy-MM-dd'),\n)\nconst displayFormat = computed(() => props.format ?? 'dd.MM.yyyy')\n\n/*\n * A range of days, not of moments. The picker offers a clock underneath by default, and\n * the time picked there is thrown away by the date-only format the moment it is applied —\n * so the control is only there to be misread. Pair two `WxDateTimePicker`s where the ends\n * really are moments.\n */\nconst timeConfig = { enableTimePicker: false }\n\nconst inputAttrs = computed(() => ({\n id: field.id.value,\n name: props.name,\n clearable: props.clearable,\n state: field.status.value === 'error' ? false : undefined,\n 'aria-label': props.ariaLabel,\n 'aria-describedby': field.describedBy.value,\n}))\n\nconst classes = computed(() => [\n 'wx-datepicker',\n 'wx-datepicker--range',\n `wx-datepicker--${field.size.value}`,\n {\n [`wx-datepicker--${field.status.value}`]: field.status.value !== 'default',\n 'is-disabled': field.disabled.value,\n },\n])\n\n/** The library hands back `null` while only the first date has been picked. */\nfunction onUpdate(value: DateRangePickerModelValue) {\n model.value = value\n emit('change', value)\n}\n\nfunction onCleared() {\n model.value = null\n emit('change', null)\n emit('clear')\n}\n</script>\n\n<template>\n <div :class=\"classes\" v-bind=\"rootAttrs\">\n <vue-date-picker\n range\n :model-value=\"model\"\n :model-type=\"modelType\"\n :formats=\"{ input: displayFormat }\"\n :time-config=\"timeConfig\"\n :multi-calendars=\"months\"\n :input-attrs=\"inputAttrs\"\n :ui=\"{ input: 'wx-datepicker__input', menu: 'wx-datepicker__menu' }\"\n :placeholder=\"placeholder\"\n :min-date=\"minDate\"\n :max-date=\"maxDate\"\n :locale=\"locale\"\n :week-start=\"weekStart\"\n :auto-apply=\"autoApply\"\n :text-input=\"textInput\"\n :teleport=\"teleport\"\n :disabled=\"field.disabled.value\"\n :readonly=\"readonly\"\n v-bind=\"controlAttrs\"\n @update:model-value=\"onUpdate\"\n @cleared=\"onCleared\"\n @open=\"emit('open')\"\n @closed=\"emit('close')\"\n >\n <template v-for=\"(_, name) in $slots\" #[name]=\"slotProps\">\n <slot :name=\"name\" v-bind=\"slotProps ?? {}\" />\n </template>\n </vue-date-picker>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport WxDatePicker from '../DatePicker/DatePicker.vue'\nimport type { DatePickerModelValue, DatePickerProps } from '../DatePicker/types'\n\ndefineOptions({ name: 'WxDateTimePicker' })\n\n/**\n * Every prop defaults to `undefined` on purpose. Vue casts an absent boolean prop\n * to `false`, and this preset forwards its whole prop object — without these the\n * preset would hand `WxDatePicker` an explicit `false` for `is24`, `clearable`,\n * `autoApply` and `teleport`, overriding that component's own defaults. Passing\n * `undefined` lets each default apply as if the prop had never been written.\n */\nwithDefaults(defineProps<Omit<DatePickerProps, 'type'>>(), {\n valueFormat: undefined,\n format: undefined,\n placeholder: undefined,\n clearable: undefined,\n minDate: undefined,\n maxDate: undefined,\n seconds: undefined,\n minutesIncrement: undefined,\n is24: undefined,\n locale: undefined,\n weekStart: undefined,\n autoApply: undefined,\n textInput: undefined,\n teleport: undefined,\n disabled: undefined,\n readonly: undefined,\n size: undefined,\n status: undefined,\n id: undefined,\n name: undefined,\n ariaLabel: undefined,\n})\n\n/*\n * Every slot is passed straight through to the picker underneath, so this component's\n * slots are whatever the caller hands it. Saying so explicitly is what keeps the\n * declaration honest: left to infer, the slot type is read off a template that\n * enumerates the slots themselves, and TypeScript answers that circle by emitting\n * `any`.\n */\ndefineSlots<Record<string, (props: Record<string, unknown>) => unknown>>()\n\nconst model = defineModel<DatePickerModelValue>({ default: null })\n</script>\n\n<template>\n <wx-date-picker v-model=\"model\" type=\"datetime\" v-bind=\"$props\">\n <template v-for=\"(_, name) in $slots\" #[name]=\"slotProps\">\n <slot :name=\"name\" v-bind=\"slotProps ?? {}\" />\n </template>\n </wx-date-picker>\n</template>\n","import { inject, type InjectionKey } from 'vue'\nimport type { DescriptionsContext } from './types'\n\nexport const descriptionsKey: InjectionKey<DescriptionsContext> = Symbol('wx-descriptions')\n\n/** A pair on its own, outside any list, still has to render something sensible. */\nexport function useDescriptions(): DescriptionsContext {\n return inject(descriptionsKey, {\n bordered: false,\n layout: 'horizontal',\n labelWidth: undefined,\n columns: 1,\n })\n}\n","<script setup lang=\"ts\">\nimport { computed, provide } from 'vue'\nimport { descriptionsKey } from './context'\nimport type { DescriptionsProps } from './types'\n\ndefineOptions({ name: 'WxDescriptions' })\n\nconst props = withDefaults(defineProps<DescriptionsProps>(), {\n title: undefined,\n columns: 2,\n bordered: false,\n size: 'md',\n layout: 'horizontal',\n labelWidth: undefined,\n})\n\ndefineSlots<{\n title?: () => unknown\n /** Beside the heading: an edit button, a status. */\n extra?: () => unknown\n default?: () => unknown\n}>()\n\nprovide(descriptionsKey, {\n get bordered() {\n return props.bordered\n },\n get layout() {\n return props.layout\n },\n get labelWidth() {\n return props.labelWidth\n },\n get columns() {\n return Math.max(1, props.columns)\n },\n})\n\nconst classes = computed(() => [\n 'wx-descriptions',\n `wx-descriptions--${props.size}`,\n `wx-descriptions--${props.layout}`,\n { 'wx-descriptions--bordered': props.bordered },\n])\n\nconst style = computed(() => ({\n '--wx-descriptions-columns': String(Math.max(1, props.columns)),\n '--wx-descriptions-label': props.labelWidth ?? 'max-content',\n}))\n</script>\n\n<template>\n <div :class=\"classes\" :style=\"style\">\n <header v-if=\"title || $slots.title || $slots.extra\" class=\"wx-descriptions__header\">\n <div class=\"wx-descriptions__title\">\n <slot name=\"title\">{{ title }}</slot>\n </div>\n <div v-if=\"$slots.extra\" class=\"wx-descriptions__extra\">\n <slot name=\"extra\" />\n </div>\n </header>\n\n <!--\n A grid rather than a table. The facts are a list of pairs, not tabular data —\n nothing lines up down a column except by accident — and a grid can fold to one\n column in a narrow panel, which a table cannot be talked into.\n -->\n <dl class=\"wx-descriptions__list\">\n <slot />\n </dl>\n </div>\n</template>\n\n<style scoped>\n.wx-descriptions {\n box-sizing: border-box;\n /* The fold is decided by the panel this sits in, not by the window. */\n container-type: inline-size;\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n}\n\n.wx-descriptions__header {\n display: flex;\n align-items: center;\n gap: var(--wx-space-12);\n margin-bottom: var(--wx-space-10);\n}\n\n.wx-descriptions__title {\n min-width: 0;\n color: var(--wx-text-strong);\n font-size: var(--wx-font-size-md);\n font-weight: var(--wx-font-weight-semibold);\n}\n\n.wx-descriptions__extra {\n margin-inline-start: auto;\n}\n\n.wx-descriptions__list {\n display: grid;\n margin: 0;\n padding: 0;\n font-size: var(--wx-font-size-sm);\n}\n\n/*\n * Horizontal: every column is a label and a value, so the grid has twice as many\n * tracks as it has columns. The labels size to their content and share one width,\n * which is what keeps the values aligned down the page.\n */\n.wx-descriptions--horizontal .wx-descriptions__list {\n grid-template-columns: repeat(\n var(--wx-descriptions-columns, 2),\n var(--wx-descriptions-label, max-content) 1fr\n );\n gap: var(--wx-descriptions-row-gap) var(--wx-descriptions-column-gap);\n}\n\n.wx-descriptions--vertical .wx-descriptions__list {\n grid-template-columns: repeat(var(--wx-descriptions-columns, 2), 1fr);\n gap: var(--wx-descriptions-row-gap) var(--wx-descriptions-column-gap);\n}\n\n.wx-descriptions--sm {\n --wx-descriptions-row-gap: var(--wx-space-6);\n --wx-descriptions-column-gap: var(--wx-space-12);\n --wx-descriptions-cell: var(--wx-space-6) var(--wx-space-10);\n}\n\n.wx-descriptions--md {\n --wx-descriptions-row-gap: var(--wx-space-8);\n --wx-descriptions-column-gap: var(--wx-space-16);\n --wx-descriptions-cell: var(--wx-space-8) var(--wx-space-12);\n}\n\n.wx-descriptions--lg {\n --wx-descriptions-row-gap: var(--wx-space-12);\n --wx-descriptions-column-gap: var(--wx-space-24);\n --wx-descriptions-cell: var(--wx-space-10) var(--wx-space-16);\n}\n\n/*\n * Bordered: the grid's gaps become the rules. One pixel of the list's own background\n * shows between the cells, and the cells paint themselves over everything else.\n */\n.wx-descriptions--bordered .wx-descriptions__list {\n gap: 1px;\n background: var(--wx-border-default);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-sm);\n overflow: hidden;\n}\n\n/*\n * One column once there is no room for two. The pairs keep their own labels beside\n * their values; it is the columns that fold, not the layout.\n */\n@container (max-width: 420px) {\n .wx-descriptions--horizontal .wx-descriptions__list {\n grid-template-columns: var(--wx-descriptions-label, max-content) 1fr;\n }\n\n .wx-descriptions--vertical .wx-descriptions__list {\n grid-template-columns: 1fr;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useDescriptions } from '../Descriptions/context'\nimport type { DescriptionsItemProps } from '../Descriptions/types'\n\ndefineOptions({ name: 'WxDescriptionsItem', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<DescriptionsItemProps>(), {\n label: undefined,\n span: 1,\n})\n\ndefineSlots<{\n label?: () => unknown\n default?: () => unknown\n}>()\n\nconst list = useDescriptions()\n\nconst stacked = computed(() => list.layout === 'vertical')\n\n/*\n * Beside its value, a pair is two grid cells, so spanning two columns means spanning\n * four tracks — and the label keeps the one track it started with. Above its value,\n * the pair is a single cell and spans plainly.\n *\n * Clamped to the columns the list actually has: a pair asking for more tracks than\n * there are does not widen the grid, it spills out of it and takes the placement of\n * every pair after it with it.\n */\nconst span = computed(() => {\n const columns = Math.min(Math.max(1, props.span), list.columns)\n return stacked.value ? columns : columns * 2 - 1\n})\n\n/*\n * Handed to CSS rather than set as `grid-column` here, because the number is only right\n * while the list has all its columns. Folded to one — which is a container query, and so\n * is not knowable from script — every pair spans a single track, and an inline style is\n * exactly what a stylesheet cannot take back.\n */\nconst style = computed(() => ({ '--wx-descriptions-span': String(span.value) }))\n</script>\n\n<template>\n <!--\n Stacked, the pair is one box and the grid places it as one. Side by side, the\n label and the value are grid items of the list itself — that is what lets the\n labels of different pairs share a column and line up. A wrapper here would end\n that, which is why there is not one.\n -->\n <div v-if=\"stacked\" class=\"wx-descriptions__pair\" :style=\"style\">\n <dt class=\"wx-descriptions__label\">\n <slot name=\"label\">{{ label }}</slot>\n </dt>\n <dd class=\"wx-descriptions__value\"><slot /></dd>\n </div>\n\n <template v-else>\n <dt class=\"wx-descriptions__label\">\n <slot name=\"label\">{{ label }}</slot>\n </dt>\n <dd class=\"wx-descriptions__value\" :style=\"style\"><slot /></dd>\n </template>\n</template>\n\n<style>\n/*\n * Unscoped: the pair is a fragment whose parts are laid out by the list above it,\n * and the bordered look is switched on from up there. A scoped rule could reach\n * neither.\n */\n.wx-descriptions__label {\n min-width: 0;\n color: var(--wx-text-muted);\n font-weight: var(--wx-font-weight-medium);\n line-height: var(--wx-font-line-height-normal);\n}\n\n.wx-descriptions__value {\n min-width: 0;\n margin: 0;\n grid-column: span var(--wx-descriptions-span, 1);\n color: var(--wx-text-default);\n line-height: var(--wx-font-line-height-normal);\n}\n\n.wx-descriptions__pair {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n grid-column: span var(--wx-descriptions-span, 1);\n}\n\n/*\n * Folded to one column there is one track for a value and one for a pair, so every span\n * is one whatever it was asked for. Left alone, a pair spanning two columns still asked\n * for three tracks out of two and was placed on a row of its own past the edge of the\n * grid — which is what threw the labels and the values of every pair after it apart.\n */\n@container (max-width: 420px) {\n .wx-descriptions__value,\n .wx-descriptions__pair {\n grid-column: span 1;\n }\n}\n\n/*\n * The rules are the gaps. A one-pixel gap over a background in the border colour\n * draws a lattice that is exact at any number of columns and under any span —\n * where a border per cell doubles up along every shared edge, and the rules that\n * would trim it cannot be written without knowing the column count.\n */\n.wx-descriptions--bordered .wx-descriptions__label,\n.wx-descriptions--bordered .wx-descriptions__value,\n.wx-descriptions--bordered .wx-descriptions__pair {\n padding: var(--wx-descriptions-cell, 8px 12px);\n background: var(--wx-bg-surface);\n}\n\n.wx-descriptions--bordered.wx-descriptions--horizontal .wx-descriptions__label {\n background: var(--wx-bg-subtle);\n}\n</style>\n","/**\n * The pieces `WxDialog` and `WxDrawer` have in common: both take a size in pixels or\n * per cent, both can be dragged to a new one, and both can be told to remember it.\n */\n\n/** A number is pixels, however it arrives — `width=\"520\"` in a template is a string. */\nexport function cssLength(value: number | string | undefined): string | undefined {\n if (value === undefined || value === null || value === '') return undefined\n if (typeof value === 'number') return Number.isFinite(value) ? `${value}px` : undefined\n\n const trimmed = value.trim()\n return /^-?\\d+(\\.\\d+)?$/.test(trimmed) ? `${trimmed}px` : trimmed\n}\n\n/**\n * The pixels behind a size prop, when there are any — `'60%'` has none, and a gesture\n * that starts on such a panel has to measure it instead.\n */\nexport function pixelLength(value: number | string | undefined): number | undefined {\n if (typeof value === 'number') return Number.isFinite(value) ? value : undefined\n if (typeof value !== 'string') return undefined\n\n const trimmed = value.trim()\n if (!/^-?\\d+(\\.\\d+)?(px)?$/.test(trimmed)) return undefined\n return Number.parseFloat(trimmed)\n}\n\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), Math.max(min, max))\n}\n\nexport interface PanelMemory<T> {\n read: () => Partial<T> | null\n write: (value: T) => void\n clear: () => void\n}\n\n/**\n * `localStorage`, with every way it can fail treated the same way: remembering a panel's\n * size is a convenience, and a private window or a full quota only costs the default.\n */\nexport function usePanelMemory<T>(prefix: string, key: () => string | undefined): PanelMemory<T> {\n const storageKey = () => {\n const name = key()\n return name ? prefix + name : null\n }\n\n return {\n read() {\n const id = storageKey()\n if (!id || typeof window === 'undefined') return null\n try {\n const raw = window.localStorage.getItem(id)\n return raw ? (JSON.parse(raw) as Partial<T>) : null\n } catch {\n // Unavailable, or holding something we did not write.\n return null\n }\n },\n write(value: T) {\n const id = storageKey()\n if (!id || typeof window === 'undefined') return\n try {\n window.localStorage.setItem(id, JSON.stringify(value))\n } catch {\n // A private window or a full quota.\n }\n },\n clear() {\n const id = storageKey()\n if (!id || typeof window === 'undefined') return\n try {\n window.localStorage.removeItem(id)\n } catch {\n // Nothing to undo if it cannot be removed.\n }\n },\n }\n}\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref, useSlots, watch } from 'vue'\nimport {\n DialogClose,\n DialogContent,\n DialogOverlay,\n DialogPortal,\n DialogRoot,\n DialogTitle,\n DialogTrigger,\n} from 'reka-ui'\nimport WxIcon from '../Icon/Icon.vue'\nimport { clamp, cssLength, pixelLength, usePanelMemory } from '../../composables/useOverlayPanel'\nimport type { DialogEmits, DialogLayout, DialogProps } from './types'\n\ndefineOptions({ name: 'WxDialog', inheritAttrs: false })\n\n/*\n * A window over the page: a heading with its actions, a body that scrolls, a row of\n * buttons under it. `WxDrawer` is the same panel anchored to an edge of the screen —\n * reach for that one when what is behind it has to stay visible.\n *\n * What has no appearance of its own — the focus trap, the scroll lock, Escape, the\n * portal, `aria-modal` — comes from Reka's dialog primitive. Everything that can be\n * seen is ours.\n */\nconst props = withDefaults(defineProps<DialogProps>(), {\n title: undefined,\n width: 520,\n height: undefined,\n scroll: 'body',\n stickyFooter: true,\n minWidth: 320,\n minHeight: 200,\n sidebarWidth: 200,\n closable: true,\n closeLabel: 'Close',\n closeOnOverlay: true,\n closeOnEscape: true,\n overlay: true,\n modal: true,\n draggable: false,\n resizable: false,\n persist: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<DialogEmits>()\n\ndefineSlots<{\n /** The control that opens the panel. Exactly one element. */\n trigger?: (props: { open: boolean }) => unknown\n /** The body. */\n default?: (props: { close: () => void }) => unknown\n /** Replaces `title`. */\n title?: () => unknown\n /** Next to the heading — badges, or actions that belong to the whole panel. */\n extra?: (props: { close: () => void }) => unknown\n /** A column beside the body. Its presence is what splits the body in two. */\n sidebar?: (props: { close: () => void }) => unknown\n /** A row under the body — where the Save and Cancel go. */\n footer?: (props: { close: () => void }) => unknown\n}>()\n\nconst open = defineModel<boolean>('open', { default: false })\n\nconst slots = useSlots()\n\nfunction close() {\n open.value = false\n}\n\nconst hasTitle = computed(() => Boolean(props.title || slots.title))\nconst hasHead = computed(() => Boolean(hasTitle.value || slots.extra || props.closable))\nconst hasSidebar = computed(() => Boolean(slots.sidebar))\n\n/* Reka needs a `DialogTitle` to name the panel; without a visible one it is hidden. */\nconst accessibleName = computed(() => props.title ?? props.ariaLabel ?? 'Dialog')\n\n/*\n * A panel taller than the screen is not a panel that can be moved or stretched: the\n * gesture would fight the scroll it sits in, and there is no free space around it to move\n * into. Both are ignored rather than refused, so one prop can turn a dialog into the long\n * kind without having to unpick the rest.\n */\nconst scrollsInPlace = computed(() => props.scroll === 'body')\nconst movable = computed(() => props.draggable && scrollsInPlace.value)\nconst sizable = computed(() => props.resizable && scrollsInPlace.value)\n\n/** Pixels the panel was last left at. Empty until it is dragged, resized or restored. */\nconst layout = ref<DialogLayout>({})\n\nconst memory = usePanelMemory<DialogLayout>('wx-dialog:', () => props.persist)\n\n/*\n * Sizes travel as custom properties rather than as `width` and `height`: the small-screen\n * rules then override them by being a later rule, instead of having to out-shout an\n * inline style with `!important`.\n */\nconst panelVars = computed(() => {\n const vars: Record<string, string> = {}\n\n const width = layout.value.width != null ? `${layout.value.width}px` : cssLength(props.width)\n if (width) vars['--wx-dialog-width'] = width\n\n const height = layout.value.height != null ? `${layout.value.height}px` : cssLength(props.height)\n if (height) vars['--wx-dialog-height'] = height\n\n if (layout.value.x) vars['--wx-dialog-x'] = `${layout.value.x}px`\n if (layout.value.y) vars['--wx-dialog-y'] = `${layout.value.y}px`\n\n const sidebar = cssLength(props.sidebarWidth)\n if (sidebar) vars['--wx-dialog-sidebar-width'] = sidebar\n\n return vars\n})\n\nconst panel = ref<HTMLElement | null>(null)\nconst dragging = ref(false)\nconst resizing = ref(false)\n\n/** The panel as it stood when the pointer went down, so every move is measured once. */\ninterface Gesture {\n kind: 'move' | 'resize'\n pointerX: number\n pointerY: number\n left: number\n top: number\n width: number\n height: number\n x: number\n y: number\n}\n\nlet gesture: Gesture | null = null\n\n/** Room left around the panel when a resize runs into the edge of the screen. */\nconst GUTTER = 32\n\nfunction begin(kind: 'move' | 'resize', event: PointerEvent) {\n /*\n * Touch is left out on purpose: a finger dragging the heading is a finger not\n * scrolling, and on a screen that small the panel fills it anyway.\n */\n if (event.button !== 0 || event.pointerType === 'touch') return\n\n const element = panel.value\n if (!element) return\n\n const rect = element.getBoundingClientRect()\n\n gesture = {\n kind,\n pointerX: event.clientX,\n pointerY: event.clientY,\n left: rect.left,\n top: rect.top,\n /* A panel sized in per cent has no pixels of its own until it is measured. */\n width: rect.width || layout.value.width || pixelLength(props.width) || props.minWidth,\n height: rect.height || layout.value.height || pixelLength(props.height) || props.minHeight,\n x: layout.value.x ?? 0,\n y: layout.value.y ?? 0,\n }\n\n if (kind === 'move') dragging.value = true\n else resizing.value = true\n\n window.addEventListener('pointermove', move)\n window.addEventListener('pointerup', end)\n window.addEventListener('pointercancel', end)\n event.preventDefault()\n}\n\nfunction startDrag(event: PointerEvent) {\n if (!movable.value) return\n /* The heading holds the × and whatever `extra` put there; those keep their clicks. */\n const target = event.target as HTMLElement | null\n if (target?.closest('button, a, input, select, textarea, [contenteditable]')) return\n begin('move', event)\n}\n\nfunction startResize(event: PointerEvent) {\n if (!sizable.value) return\n begin('resize', event)\n}\n\nfunction move(event: PointerEvent) {\n if (!gesture) return\n\n const dx = event.clientX - gesture.pointerX\n const dy = event.clientY - gesture.pointerY\n\n if (gesture.kind === 'move') {\n /* Held by its own edges, so the panel cannot be dragged off the screen. */\n const left = clamp(gesture.left + dx, 0, window.innerWidth - gesture.width)\n const top = clamp(gesture.top + dy, 0, window.innerHeight - gesture.height)\n\n layout.value = {\n ...layout.value,\n x: gesture.x + (left - gesture.left),\n y: gesture.y + (top - gesture.top),\n }\n return\n }\n\n const width = clamp(gesture.width + dx, props.minWidth, window.innerWidth - GUTTER)\n const height = clamp(gesture.height + dy, props.minHeight, window.innerHeight - GUTTER)\n\n /*\n * The panel is centred, so it grows by half in each direction. Shifting it by that\n * half pins the top-left corner and leaves only the one under the pointer moving.\n */\n layout.value = {\n width,\n height,\n x: gesture.x + (width - gesture.width) / 2,\n y: gesture.y + (height - gesture.height) / 2,\n }\n}\n\nfunction stopListening() {\n window.removeEventListener('pointermove', move)\n window.removeEventListener('pointerup', end)\n window.removeEventListener('pointercancel', end)\n}\n\nfunction end() {\n if (!gesture) return\n\n gesture = null\n dragging.value = false\n resizing.value = false\n stopListening()\n\n memory.write(layout.value)\n emit('layout', { ...layout.value })\n}\n\n/** Back to the declared size, in the middle of the screen, and forgotten. */\nfunction reset() {\n layout.value = {}\n memory.clear()\n}\n\nfunction restore() {\n const saved = memory.read()\n if (!saved) return\n\n const next: DialogLayout = {}\n for (const key of ['width', 'height', 'x', 'y'] as const) {\n const value = saved[key]\n if (typeof value === 'number' && Number.isFinite(value)) next[key] = value\n }\n layout.value = next\n}\n\n/*\n * After mount rather than during setup: this renders on a server too, and a panel sized\n * from one machine's `localStorage` would not match the markup the browser hydrates.\n */\nonMounted(restore)\nonBeforeUnmount(stopListening)\n\nwatch(open, (value) => {\n if (value) {\n emit('open')\n return\n }\n\n emit('close')\n /* Without a key to remember it by, every opening starts from the declared size. */\n if (!props.persist) layout.value = {}\n})\n\nfunction onEscape(event: Event) {\n if (!props.closeOnEscape) event.preventDefault()\n}\n\nfunction onInteractOutside(event: Event) {\n if (!props.closeOnOverlay) event.preventDefault()\n}\n\n/*\n * Reka hands focus to the first tabbable thing in the panel when it opens, and that is\n * the × in the heading — after the native `autofocus` has already fired, so a field marked\n * for it loses. A field marked `autofocus` is what the person came to type into.\n */\nfunction onOpenAutoFocus(event: Event) {\n const target = panel.value?.querySelector<HTMLElement>('[autofocus]')\n\n if (!target) return\n\n event.preventDefault()\n target.focus()\n}\n\n/*\n * The wrapper covers the screen, so a click beside the panel is a click inside the\n * dialog as far as Reka is concerned — and in modal mode it gives the wrapper its own\n * `pointer-events: auto`, which the overlay underneath can then never be handed. The\n * space around the panel is therefore closed here, by the element that receives it.\n */\nfunction onViewportPointerDown() {\n if (props.closeOnOverlay) close()\n}\n\ndefineExpose({ close, reset })\n</script>\n\n<template>\n <dialog-root v-model:open=\"open\" :modal=\"modal\">\n <!--\n `as-child`: the trigger is whatever the caller already has — a button, a menu item,\n a row in a table — and wrapping it in a button of ours would nest one inside another.\n -->\n <dialog-trigger v-if=\"$slots.trigger\" as-child>\n <slot name=\"trigger\" :open=\"open\" />\n </dialog-trigger>\n\n <dialog-portal>\n <dialog-overlay v-if=\"overlay\" class=\"wx-dialog__overlay\" />\n\n <!--\n The content element covers the screen: it centres the panel and gives it room to\n be dragged in. `aria-describedby` is cleared because there is no description —\n Reka warns about a missing one otherwise.\n -->\n <dialog-content\n class=\"wx-dialog__viewport\"\n :class=\"{ 'wx-dialog__viewport--scrolls': !scrollsInPlace }\"\n :aria-describedby=\"undefined\"\n @escape-key-down=\"onEscape\"\n @interact-outside=\"onInteractOutside\"\n @open-auto-focus=\"onOpenAutoFocus\"\n @mousedown.self=\"onViewportPointerDown\"\n >\n <div\n ref=\"panel\"\n v-bind=\"$attrs\"\n class=\"wx-dialog\"\n :class=\"{\n 'wx-dialog--draggable': movable,\n 'wx-dialog--dragging': dragging,\n 'wx-dialog--resizing': resizing,\n 'wx-dialog--split': hasSidebar,\n 'wx-dialog--long': !scrollsInPlace,\n 'wx-dialog--sticky-foot': !scrollsInPlace && stickyFooter,\n }\"\n :style=\"panelVars\"\n >\n <header v-if=\"hasHead\" class=\"wx-dialog__head\" @pointerdown=\"startDrag\">\n <dialog-title class=\"wx-dialog__title\" :class=\"{ 'wx-sr-only': !hasTitle }\">\n <slot name=\"title\">{{ hasTitle ? title : accessibleName }}</slot>\n </dialog-title>\n\n <div v-if=\"$slots.extra\" class=\"wx-dialog__extra\">\n <slot name=\"extra\" :close=\"close\" />\n </div>\n\n <dialog-close v-if=\"closable\" class=\"wx-dialog__close\" :aria-label=\"closeLabel\">\n <wx-icon name=\"close\" />\n </dialog-close>\n </header>\n\n <dialog-title v-else class=\"wx-sr-only\">{{ accessibleName }}</dialog-title>\n\n <div class=\"wx-dialog__body\">\n <aside v-if=\"hasSidebar\" class=\"wx-dialog__sidebar\">\n <slot name=\"sidebar\" :close=\"close\" />\n </aside>\n\n <div class=\"wx-dialog__content\">\n <slot :close=\"close\" />\n </div>\n </div>\n\n <footer v-if=\"$slots.footer\" class=\"wx-dialog__foot\">\n <slot name=\"footer\" :close=\"close\" />\n </footer>\n\n <!-- Pointer-only, and hidden with it: a corner this size cannot be hit by a finger. -->\n <div\n v-if=\"sizable\"\n class=\"wx-dialog__grip\"\n aria-hidden=\"true\"\n @pointerdown=\"startResize\"\n />\n </div>\n </dialog-content>\n </dialog-portal>\n </dialog-root>\n</template>\n\n<style>\n/* The panel is teleported, so its styles cannot be scoped to the component. */\n.wx-dialog__overlay {\n position: fixed;\n inset: 0;\n z-index: var(--wx-z-index-overlay);\n background: var(--wx-bg-overlay);\n}\n\n.wx-dialog__viewport {\n position: fixed;\n inset: 0;\n z-index: var(--wx-z-index-dialog);\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n padding: var(--wx-space-16);\n /*\n * The wrapper only places the panel. Left to itself it would swallow every click\n * beside it, so it lets them through to the overlay — except in modal mode, where Reka\n * writes `pointer-events: auto` back onto it and the wrapper closes the dialog itself.\n */\n pointer-events: none;\n}\n\n/* Reka focuses the content when it opens; the ring belongs on what is inside it. */\n.wx-dialog__viewport:focus,\n.wx-dialog__viewport:focus-visible {\n outline: none;\n}\n\n.wx-dialog {\n /* One set of paddings for the three parts, so the small screens can halve them once. */\n --wx-dialog-pad-x: var(--wx-space-18);\n --wx-dialog-pad-y: var(--wx-space-14);\n --wx-dialog-body-pad: var(--wx-space-18);\n position: relative;\n pointer-events: auto;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n width: min(var(--wx-dialog-width, 520px), 100%);\n height: var(--wx-dialog-height, auto);\n max-height: 100%;\n translate: var(--wx-dialog-x, 0) var(--wx-dialog-y, 0);\n background: var(--wx-bg-surface);\n border-radius: var(--wx-radius-md);\n box-shadow: var(--wx-shadow-dialog);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n font-size: var(--wx-font-size-md);\n line-height: var(--wx-font-line-height-normal);\n}\n\n.wx-dialog__head {\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n gap: var(--wx-space-12);\n padding: var(--wx-dialog-pad-y) var(--wx-dialog-pad-x);\n border-bottom: 1px solid var(--wx-border-muted);\n}\n\n.wx-dialog--draggable .wx-dialog__head {\n cursor: grab;\n user-select: none;\n}\n\n.wx-dialog--dragging .wx-dialog__head {\n cursor: grabbing;\n}\n\n/* A gesture that strays over the body would otherwise paint it blue as it goes. */\n.wx-dialog--dragging,\n.wx-dialog--resizing {\n user-select: none;\n}\n\n.wx-dialog__title {\n flex: 1 1 auto;\n min-width: 0;\n margin: 0;\n color: var(--wx-text-strong);\n font-size: var(--wx-font-size-lg);\n font-weight: var(--wx-font-weight-semibold);\n line-height: var(--wx-font-line-height-tight);\n}\n\n.wx-dialog__extra {\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n color: var(--wx-text-muted);\n}\n\n.wx-dialog__close {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n /* Pulled into the padding so the × sits in the corner, not inside the text block. */\n margin-right: -6px;\n padding: 0;\n background: none;\n border: none;\n border-radius: var(--wx-radius-full);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-md);\n cursor: pointer;\n}\n\n.wx-dialog__close:hover {\n background: var(--wx-bg-fill);\n color: var(--wx-text-default);\n}\n\n.wx-dialog__close:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n/*\n * The body is the only part that scrolls, so the heading and the buttons stay put however\n * long the content is. Split in two, each column scrolls on its own instead.\n */\n.wx-dialog__body {\n flex: 1 1 auto;\n min-height: 0;\n display: flex;\n overflow: hidden;\n}\n\n.wx-dialog__content {\n flex: 1 1 auto;\n min-width: 0;\n overflow: auto;\n padding: var(--wx-dialog-body-pad);\n}\n\n/*\n * Air between whatever the body was given, so that a dialog that is three fields stacked one\n * after another does not read as one block of controls. A form item carries no margin of its\n * own — the gap belongs to the form around it — and a dialog is not a form.\n *\n * A margin between siblings rather than a flex gap: turning the body into a flex container\n * would also change how a body that is one thing sizes itself, and some of those are meant to\n * fill it. Nothing happens here to a body that is a single element.\n */\n.wx-dialog__content > * + * {\n margin-block-start: var(--wx-space-14);\n}\n\n.wx-dialog__sidebar {\n flex: 0 0 auto;\n width: var(--wx-dialog-sidebar-width, 200px);\n overflow: auto;\n padding: var(--wx-dialog-pad-y) var(--wx-dialog-pad-x);\n background: var(--wx-bg-subtle);\n border-right: 1px solid var(--wx-border-muted);\n border-bottom-left-radius: var(--wx-radius-md);\n}\n\n.wx-dialog__foot {\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: var(--wx-space-8);\n padding: var(--wx-dialog-pad-y) var(--wx-dialog-pad-x);\n border-top: 1px solid var(--wx-border-muted);\n}\n\n/*\n * The long kind: the panel is as tall as its content and the wrapper around it scrolls.\n * `margin: auto` rather than `align-items: center` — a centred flex item taller than its\n * container is clipped at the top and cannot be scrolled back to, while an auto margin\n * simply gives up when there is no room left to share.\n */\n.wx-dialog__viewport--scrolls {\n align-items: flex-start;\n overflow-y: auto;\n /* The wrapper is the scroller now, so it has to take its own events. */\n pointer-events: auto;\n}\n\n.wx-dialog--long {\n height: auto;\n max-height: none;\n margin-block: auto;\n translate: none;\n}\n\n.wx-dialog--long .wx-dialog__body,\n.wx-dialog--long .wx-dialog__content,\n.wx-dialog--long .wx-dialog__sidebar {\n overflow: visible;\n}\n\n/*\n * Stuck to the bottom of the screen while the rest of the panel scrolls past it. The\n * background is what makes it a bar rather than a transparent strip over the content, and\n * the rounded corners are the panel's own, borrowed for the moment it rests on them.\n */\n.wx-dialog--long.wx-dialog--sticky-foot .wx-dialog__foot {\n position: sticky;\n bottom: 0;\n z-index: 1;\n background: var(--wx-bg-surface);\n border-bottom-left-radius: var(--wx-radius-md);\n border-bottom-right-radius: var(--wx-radius-md);\n}\n\n.wx-dialog__grip {\n position: absolute;\n right: 0;\n bottom: 0;\n width: 20px;\n height: 20px;\n cursor: nwse-resize;\n touch-action: none;\n}\n\n.wx-dialog__grip::after {\n content: '';\n position: absolute;\n right: 5px;\n bottom: 5px;\n width: 7px;\n height: 7px;\n border-right: 2px solid var(--wx-border-strong);\n border-bottom: 2px solid var(--wx-border-strong);\n opacity: 0.5;\n}\n\n.wx-dialog__grip:hover::after {\n opacity: 1;\n}\n\n@keyframes wx-dialog-in {\n from {\n opacity: 0;\n transform: translateY(8px) scale(0.97);\n }\n}\n\n@keyframes wx-dialog-out {\n to {\n opacity: 0;\n transform: scale(0.98);\n }\n}\n\n@keyframes wx-dialog-fade-in {\n from {\n opacity: 0;\n }\n}\n\n@keyframes wx-dialog-fade-out {\n to {\n opacity: 0;\n }\n}\n\n/*\n * The wrapper is what animates, not the panel inside it: Reka waits for the animation on\n * the element it owns before unmounting, and a centred panel scaled from the middle of\n * the screen is a panel scaled from its own middle.\n */\n.wx-dialog__viewport[data-state='open'] {\n animation: wx-dialog-in var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-dialog__viewport[data-state='closed'] {\n animation: wx-dialog-out var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-dialog__overlay[data-state='open'] {\n animation: wx-dialog-fade-in var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-dialog__overlay[data-state='closed'] {\n animation: wx-dialog-fade-out var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n/*\n * Small screens: the panel takes what there is, and the remembered size and position go\n * with it — a dialog dragged into a corner on a desktop must not open half off a phone.\n */\n@media (max-width: 640px) {\n .wx-dialog__viewport {\n padding: var(--wx-space-8);\n }\n\n .wx-dialog {\n /* Tighter than on a desktop: every pixel of padding is a line of content lost. */\n --wx-dialog-pad-x: var(--wx-space-12);\n --wx-dialog-pad-y: var(--wx-space-10);\n --wx-dialog-body-pad: var(--wx-space-12);\n width: 100%;\n height: auto;\n translate: none;\n }\n\n .wx-dialog__head {\n gap: var(--wx-space-8);\n }\n\n .wx-dialog--split .wx-dialog__body {\n flex-direction: column;\n overflow: auto;\n }\n\n .wx-dialog--split .wx-dialog__sidebar,\n .wx-dialog--split .wx-dialog__content {\n overflow: visible;\n }\n\n .wx-dialog__sidebar {\n width: auto;\n border-right: none;\n border-bottom: 1px solid var(--wx-border-muted);\n border-radius: 0;\n }\n}\n\n/* Nothing here can be aimed at with a finger. */\n@media (pointer: coarse) {\n .wx-dialog__grip {\n display: none;\n }\n\n .wx-dialog--draggable .wx-dialog__head {\n cursor: default;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-dialog__viewport,\n .wx-dialog__overlay {\n animation: none;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, useSlots } from 'vue'\nimport type { DividerProps } from './types'\n\ndefineOptions({ name: 'WxDivider' })\n\nconst props = withDefaults(defineProps<DividerProps>(), {\n direction: 'horizontal',\n variant: 'solid',\n align: 'center',\n spacing: 'md',\n label: undefined,\n})\n\nconst slots = useSlots()\n\n/*\n * A plain rule is a separator and says so; one carrying a label is a small heading\n * in disguise, and `role=\"separator\"` on an element with text confuses a screen\n * reader more than it helps. The note lives here rather than above the template's\n * root element, where a comment would turn the template into a fragment.\n */\nconst hasLabel = computed(() => Boolean(props.label || slots.default))\n\nconst classes = computed(() => [\n 'wx-divider',\n `wx-divider--${props.direction}`,\n `wx-divider--${props.variant}`,\n `wx-divider--spacing-${props.spacing}`,\n {\n 'wx-divider--labelled': hasLabel.value,\n [`wx-divider--align-${props.align}`]: hasLabel.value,\n },\n])\n</script>\n\n<template>\n <div\n :class=\"classes\"\n :role=\"hasLabel ? undefined : 'separator'\"\n :aria-orientation=\"hasLabel || direction === 'horizontal' ? undefined : 'vertical'\"\n >\n <span v-if=\"hasLabel\" class=\"wx-divider__label\">\n <slot>{{ label }}</slot>\n </span>\n </div>\n</template>\n\n<style scoped>\n.wx-divider {\n --wx-divider-color: var(--wx-border-default);\n --wx-divider-style: solid;\n\n box-sizing: border-box;\n border: 0;\n color: var(--wx-text-muted);\n font-family: var(--wx-font-family-sans);\n font-size: var(--wx-font-size-xs);\n}\n\n.wx-divider--dashed {\n --wx-divider-style: dashed;\n}\n\n.wx-divider--dotted {\n --wx-divider-style: dotted;\n}\n\n/* horizontal */\n.wx-divider--horizontal {\n display: flex;\n align-items: center;\n gap: var(--wx-space-12);\n width: 100%;\n margin-block: var(--wx-divider-gap, var(--wx-space-16));\n}\n\n/*\n * The rule is drawn by the pseudo-elements rather than a border on the box, so a\n * label can sit between two of them without a background of its own — which is what\n * keeps it readable on a card, a table row or a tinted panel alike.\n */\n.wx-divider--horizontal::before,\n.wx-divider--horizontal::after {\n content: '';\n flex: 1 1 auto;\n border-top: 1px var(--wx-divider-style) var(--wx-divider-color);\n}\n\n.wx-divider--horizontal:not(.wx-divider--labelled) {\n /* No label, no gap — the two halves have to meet or the rule shows a notch. */\n gap: 0;\n}\n\n.wx-divider--horizontal:not(.wx-divider--labelled)::after {\n display: none;\n}\n\n.wx-divider--align-start::before {\n flex: 0 0 var(--wx-space-24);\n}\n\n.wx-divider--align-end::after {\n flex: 0 0 var(--wx-space-24);\n}\n\n/* vertical */\n.wx-divider--vertical {\n display: inline-block;\n width: 0;\n height: 1em;\n margin-inline: var(--wx-divider-gap, var(--wx-space-8));\n border-left: 1px var(--wx-divider-style) var(--wx-divider-color);\n vertical-align: middle;\n}\n\n/* A vertical rule never carries a label — there is no room for one. */\n.wx-divider--vertical .wx-divider__label {\n display: none;\n}\n\n.wx-divider--spacing-none {\n --wx-divider-gap: 0px;\n}\n\n.wx-divider--spacing-sm {\n --wx-divider-gap: var(--wx-space-8);\n}\n\n.wx-divider--spacing-md {\n --wx-divider-gap: var(--wx-space-16);\n}\n\n.wx-divider--spacing-lg {\n --wx-divider-gap: var(--wx-space-24);\n}\n\n.wx-divider--vertical.wx-divider--spacing-md {\n --wx-divider-gap: var(--wx-space-8);\n}\n\n.wx-divider--vertical.wx-divider--spacing-lg {\n --wx-divider-gap: var(--wx-space-12);\n}\n\n.wx-divider__label {\n flex: 0 0 auto;\n white-space: nowrap;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref, useSlots, watch } from 'vue'\nimport {\n DialogClose,\n DialogContent,\n DialogOverlay,\n DialogPortal,\n DialogRoot,\n DialogTitle,\n DialogTrigger,\n} from 'reka-ui'\nimport WxIcon from '../Icon/Icon.vue'\nimport { clamp, cssLength, pixelLength, usePanelMemory } from '../../composables/useOverlayPanel'\nimport type { DrawerEmits, DrawerLayout, DrawerProps } from './types'\n\ndefineOptions({ name: 'WxDrawer', inheritAttrs: false })\n\n/*\n * The same panel as `WxDialog` — heading, body, footer — anchored to an edge of the\n * screen instead of floating in the middle of it. It is the one to reach for when the\n * page behind it is the point: a record opened beside the table it came from.\n *\n * The dialog primitive underneath is Reka's, so the focus trap, the scroll lock, Escape\n * and `aria-modal` are the same as everywhere else. What can be seen is ours.\n */\nconst props = withDefaults(defineProps<DrawerProps>(), {\n title: undefined,\n side: 'right',\n size: 380,\n minSize: 280,\n sidebarWidth: 200,\n closable: true,\n closeLabel: 'Close',\n closeOnOverlay: true,\n closeOnEscape: true,\n overlay: true,\n modal: true,\n fullScreen: true,\n resizable: false,\n persist: undefined,\n ariaLabel: undefined,\n resizeLabel: 'Resize the panel',\n})\n\nconst emit = defineEmits<DrawerEmits>()\n\ndefineSlots<{\n /** The control that opens the panel. Exactly one element. */\n trigger?: (props: { open: boolean }) => unknown\n /** The body. The one part of the panel that scrolls. */\n default?: (props: { close: () => void }) => unknown\n /** Replaces `title`. */\n title?: () => unknown\n /** Next to the heading — badges, or actions that belong to the whole panel. */\n extra?: (props: { close: () => void }) => unknown\n /** A column beside the body. Its presence is what splits the body in two. */\n sidebar?: (props: { close: () => void }) => unknown\n /** A row under the body — where the Save and Cancel go. */\n footer?: (props: { close: () => void }) => unknown\n}>()\n\nconst open = defineModel<boolean>('open', { default: false })\n\nconst slots = useSlots()\n\nfunction close() {\n open.value = false\n}\n\nconst hasTitle = computed(() => Boolean(props.title || slots.title))\nconst hasHead = computed(() => Boolean(hasTitle.value || slots.extra || props.closable))\nconst hasSidebar = computed(() => Boolean(slots.sidebar))\n\n/* Reka needs a `DialogTitle` to name the panel; without a visible one it is hidden. */\nconst accessibleName = computed(() => props.title ?? props.ariaLabel ?? 'Panel')\n\n/** Which way the panel grows: across the screen, or down it. */\nconst horizontal = computed(() => props.side === 'left' || props.side === 'right')\n\n/** Pixels the panel was last left at. Empty until it is resized or restored. */\nconst layout = ref<DrawerLayout>({})\n\nconst memory = usePanelMemory<DrawerLayout>('wx-drawer:', () => props.persist)\n\n/*\n * The size travels as a custom property rather than as `width` or `height`: the\n * small-screen rule then takes the panel full-screen by being a later rule, instead of\n * having to out-shout an inline style with `!important`.\n */\nconst panelVars = computed(() => {\n const vars: Record<string, string> = {}\n\n const size = layout.value.size != null ? `${layout.value.size}px` : cssLength(props.size)\n if (size) vars['--wx-drawer-size'] = size\n\n const sidebar = cssLength(props.sidebarWidth)\n if (sidebar) vars['--wx-drawer-sidebar-width'] = sidebar\n\n return vars\n})\n\nconst resizing = ref(false)\n\n/** Room left between the panel and the far edge of the screen. */\nconst GUTTER = 32\n\n/** The panel as it stood when the gesture began, so every move is measured once. */\nlet gesture: { pointerX: number; pointerY: number; size: number } | null = null\n\n/**\n * The panel around the handle. Taken from the event rather than from a template ref: the\n * panel is a Reka component, and what a ref on one holds is the component, not the box\n * that has to be measured.\n */\nfunction panelOf(event: Event): HTMLElement | null {\n return (event.currentTarget as HTMLElement | null)?.closest('.wx-drawer') ?? null\n}\n\n/** What the panel measures now, falling back to what it was told to be. */\nfunction currentSize(element: HTMLElement | null): number {\n const rect = element?.getBoundingClientRect()\n const measured = horizontal.value ? rect?.width : rect?.height\n /* A panel sized in per cent has no pixels of its own until it is measured. */\n return measured || layout.value.size || pixelLength(props.size) || props.minSize\n}\n\nfunction maxSize(): number {\n const room = horizontal.value ? window.innerWidth : window.innerHeight\n return room - GUTTER\n}\n\n/** Pointer movement, turned into a size: every side grows towards the middle. */\nfunction sizeFrom(startSize: number, dx: number, dy: number): number {\n const delta =\n props.side === 'right' ? -dx : props.side === 'left' ? dx : props.side === 'top' ? dy : -dy\n return clamp(startSize + delta, props.minSize, maxSize())\n}\n\nfunction startResize(event: PointerEvent) {\n /*\n * Touch is left out on purpose: a handle this narrow cannot be aimed at with a finger,\n * and on a screen that small the panel covers everything anyway.\n */\n if (!props.resizable || event.button !== 0 || event.pointerType === 'touch') return\n\n gesture = { pointerX: event.clientX, pointerY: event.clientY, size: currentSize(panelOf(event)) }\n resizing.value = true\n\n window.addEventListener('pointermove', move)\n window.addEventListener('pointerup', end)\n window.addEventListener('pointercancel', end)\n event.preventDefault()\n}\n\nfunction move(event: PointerEvent) {\n if (!gesture) return\n\n layout.value = {\n size: sizeFrom(\n gesture.size,\n event.clientX - gesture.pointerX,\n event.clientY - gesture.pointerY,\n ),\n }\n}\n\nfunction stopListening() {\n window.removeEventListener('pointermove', move)\n window.removeEventListener('pointerup', end)\n window.removeEventListener('pointercancel', end)\n}\n\nfunction end() {\n if (!gesture) return\n\n gesture = null\n resizing.value = false\n stopListening()\n store()\n}\n\n/** The same resize from the keyboard, which is the only way to reach it without a mouse. */\nconst STEP = 24\n\nfunction onHandleKeydown(event: KeyboardEvent) {\n if (!props.resizable) return\n\n const towards = horizontal.value\n ? { ArrowLeft: -STEP, ArrowRight: STEP }\n : { ArrowUp: -STEP, ArrowDown: STEP }\n const delta = (towards as Record<string, number | undefined>)[event.key]\n if (delta === undefined) return\n\n event.preventDefault()\n const from = currentSize(panelOf(event))\n layout.value = {\n size: sizeFrom(from, horizontal.value ? delta : 0, horizontal.value ? 0 : delta),\n }\n store()\n}\n\nfunction store() {\n memory.write(layout.value)\n emit('layout', { ...layout.value })\n}\n\n/** Back to the declared size, and forgotten. */\nfunction reset() {\n layout.value = {}\n memory.clear()\n}\n\nfunction restore() {\n const saved = memory.read()\n if (!saved) return\n if (typeof saved.size === 'number' && Number.isFinite(saved.size)) {\n layout.value = { size: saved.size }\n }\n}\n\n/*\n * After mount rather than during setup: this renders on a server too, and a panel sized\n * from one machine's `localStorage` would not match the markup the browser hydrates.\n */\nonMounted(restore)\nonBeforeUnmount(stopListening)\n\nwatch(open, (value) => {\n if (value) {\n emit('open')\n return\n }\n\n emit('close')\n /* Without a key to remember it by, every opening starts from the declared size. */\n if (!props.persist) layout.value = {}\n})\n\nfunction onEscape(event: Event) {\n if (!props.closeOnEscape) event.preventDefault()\n}\n\nfunction onInteractOutside(event: Event) {\n if (!props.closeOnOverlay) event.preventDefault()\n}\n\ndefineExpose({ close, reset })\n</script>\n\n<template>\n <dialog-root v-model:open=\"open\" :modal=\"modal\">\n <!--\n `as-child`: the trigger is whatever the caller already has — a button, a menu item,\n a row in a table — and wrapping it in a button of ours would nest one inside another.\n -->\n <dialog-trigger v-if=\"$slots.trigger\" as-child>\n <slot name=\"trigger\" :open=\"open\" />\n </dialog-trigger>\n\n <dialog-portal>\n <dialog-overlay v-if=\"overlay\" class=\"wx-drawer__overlay\" />\n\n <!--\n Here the content element is the panel itself — nothing has to be centred, and it\n is the element Reka slides in. `aria-describedby` is cleared because there is no\n description; Reka warns about a missing one otherwise.\n -->\n <dialog-content\n v-bind=\"$attrs\"\n class=\"wx-drawer\"\n :class=\"[\n `wx-drawer--${side}`,\n {\n 'wx-drawer--resizing': resizing,\n 'wx-drawer--split': hasSidebar,\n 'wx-drawer--contained': !fullScreen,\n },\n ]\"\n :style=\"panelVars\"\n :aria-describedby=\"undefined\"\n @escape-key-down=\"onEscape\"\n @interact-outside=\"onInteractOutside\"\n >\n <header v-if=\"hasHead\" class=\"wx-drawer__head\">\n <dialog-title class=\"wx-drawer__title\" :class=\"{ 'wx-sr-only': !hasTitle }\">\n <slot name=\"title\">{{ hasTitle ? title : accessibleName }}</slot>\n </dialog-title>\n\n <div v-if=\"$slots.extra\" class=\"wx-drawer__extra\">\n <slot name=\"extra\" :close=\"close\" />\n </div>\n\n <dialog-close v-if=\"closable\" class=\"wx-drawer__close\" :aria-label=\"closeLabel\">\n <wx-icon name=\"close\" />\n </dialog-close>\n </header>\n\n <dialog-title v-else class=\"wx-sr-only\">{{ accessibleName }}</dialog-title>\n\n <div class=\"wx-drawer__body\">\n <aside v-if=\"hasSidebar\" class=\"wx-drawer__sidebar\">\n <slot name=\"sidebar\" :close=\"close\" />\n </aside>\n\n <div class=\"wx-drawer__content\">\n <slot :close=\"close\" />\n </div>\n </div>\n\n <footer v-if=\"$slots.footer\" class=\"wx-drawer__foot\">\n <slot name=\"footer\" :close=\"close\" />\n </footer>\n\n <!--\n A separator rather than a decoration: it takes focus and answers the arrow keys,\n which is the only way to resize the panel without a pointer.\n -->\n <div\n v-if=\"resizable\"\n class=\"wx-drawer__handle\"\n role=\"separator\"\n tabindex=\"0\"\n :aria-label=\"resizeLabel\"\n :aria-orientation=\"horizontal ? 'vertical' : 'horizontal'\"\n @pointerdown=\"startResize\"\n @keydown=\"onHandleKeydown\"\n />\n </dialog-content>\n </dialog-portal>\n </dialog-root>\n</template>\n\n<style>\n/* The panel is teleported, so its styles cannot be scoped to the component. */\n.wx-drawer__overlay {\n position: fixed;\n inset: 0;\n z-index: var(--wx-z-index-overlay);\n background: var(--wx-bg-overlay);\n}\n\n.wx-drawer {\n /*\n * One set of paddings for the three parts, so the small screens can halve them once — and\n * sideways it is the panel's step rather than a number of the drawer's own.\n *\n * The same list in a card stood 16 from the edge and in a drawer 18, which is two owners for\n * one distance (§6 of the visual spec). The step reaches here because the shell writes it on\n * the document as well as on itself, which is what a drawer teleported to the end of `<body>`\n * can inherit. Outside a panel there is no such variable and the drawer keeps the 18 it had.\n */\n --wx-drawer-pad-x: var(--wx-gap, var(--wx-space-18));\n --wx-drawer-pad-y: var(--wx-space-14);\n --wx-drawer-body-pad: var(--wx-gap, var(--wx-space-18));\n position: fixed;\n z-index: var(--wx-z-index-dialog);\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n background: var(--wx-bg-surface);\n box-shadow: var(--wx-shadow-dialog);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n font-size: var(--wx-font-size-md);\n line-height: var(--wx-font-line-height-normal);\n}\n\n.wx-drawer:focus,\n.wx-drawer:focus-visible {\n outline: none;\n}\n\n/*\n * `dvh` rather than `vh`: on a phone the address bar comes and goes, and a panel measured\n * against the taller of the two would keep its footer under it.\n */\n.wx-drawer--left,\n.wx-drawer--right {\n top: 0;\n height: 100dvh;\n width: min(var(--wx-drawer-size, 380px), 100%);\n}\n\n.wx-drawer--right {\n right: 0;\n border-left: 1px solid var(--wx-border-default);\n}\n\n.wx-drawer--left {\n left: 0;\n border-right: 1px solid var(--wx-border-default);\n}\n\n.wx-drawer--top,\n.wx-drawer--bottom {\n left: 0;\n width: 100%;\n height: min(var(--wx-drawer-size, 380px), 100dvh);\n}\n\n.wx-drawer--top {\n top: 0;\n border-bottom: 1px solid var(--wx-border-default);\n}\n\n.wx-drawer--bottom {\n bottom: 0;\n border-top: 1px solid var(--wx-border-default);\n}\n\n.wx-drawer__head {\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n gap: var(--wx-space-12);\n padding: var(--wx-drawer-pad-y) var(--wx-drawer-pad-x);\n border-bottom: 1px solid var(--wx-border-muted);\n}\n\n.wx-drawer__title {\n flex: 1 1 auto;\n min-width: 0;\n margin: 0;\n color: var(--wx-text-strong);\n font-size: var(--wx-font-size-lg);\n font-weight: var(--wx-font-weight-semibold);\n line-height: var(--wx-font-line-height-tight);\n}\n\n.wx-drawer__extra {\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n color: var(--wx-text-muted);\n}\n\n.wx-drawer__close {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n /* Pulled into the padding so the × sits in the corner, not inside the text block. */\n margin-right: -6px;\n padding: 0;\n background: none;\n border: none;\n border-radius: var(--wx-radius-full);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-md);\n cursor: pointer;\n}\n\n.wx-drawer__close:hover {\n background: var(--wx-bg-fill);\n color: var(--wx-text-default);\n}\n\n.wx-drawer__close:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n/*\n * The body is the only part that scrolls: the heading and the buttons stay where they are\n * however long the content is. Split in two, each column scrolls on its own instead.\n */\n.wx-drawer__body {\n flex: 1 1 auto;\n min-height: 0;\n display: flex;\n overflow: hidden;\n}\n\n.wx-drawer__content {\n flex: 1 1 auto;\n min-width: 0;\n overflow: auto;\n padding: var(--wx-drawer-body-pad);\n}\n\n.wx-drawer__sidebar {\n flex: 0 0 auto;\n width: var(--wx-drawer-sidebar-width, 200px);\n overflow: auto;\n padding: var(--wx-drawer-pad-y) var(--wx-drawer-pad-x);\n background: var(--wx-bg-subtle);\n border-right: 1px solid var(--wx-border-muted);\n}\n\n.wx-drawer__foot {\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: var(--wx-space-8);\n padding: var(--wx-drawer-pad-y) var(--wx-drawer-pad-x);\n border-top: 1px solid var(--wx-border-muted);\n}\n\n/* The handle sits on the edge the panel faces the page with. */\n.wx-drawer__handle {\n position: absolute;\n touch-action: none;\n background: transparent;\n transition: background var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-drawer__handle:hover,\n.wx-drawer--resizing .wx-drawer__handle {\n background: var(--wx-color-primary-soft);\n}\n\n.wx-drawer__handle:focus-visible {\n outline: none;\n background: var(--wx-color-primary);\n}\n\n.wx-drawer--right .wx-drawer__handle,\n.wx-drawer--left .wx-drawer__handle {\n top: 0;\n bottom: 0;\n width: 6px;\n cursor: col-resize;\n}\n\n.wx-drawer--right .wx-drawer__handle {\n left: 0;\n}\n\n.wx-drawer--left .wx-drawer__handle {\n right: 0;\n}\n\n.wx-drawer--top .wx-drawer__handle,\n.wx-drawer--bottom .wx-drawer__handle {\n left: 0;\n right: 0;\n height: 6px;\n cursor: row-resize;\n}\n\n.wx-drawer--top .wx-drawer__handle {\n bottom: 0;\n}\n\n.wx-drawer--bottom .wx-drawer__handle {\n top: 0;\n}\n\n/*\n * One pair of keyframes for all four sides: the side sets where the panel sits when it is\n * off-screen, and `translate` is a property of its own, so nothing here collides with a\n * `transform` set elsewhere.\n */\n.wx-drawer--right {\n --wx-drawer-from: 100% 0;\n}\n\n.wx-drawer--left {\n --wx-drawer-from: -100% 0;\n}\n\n.wx-drawer--top {\n --wx-drawer-from: 0 -100%;\n}\n\n.wx-drawer--bottom {\n --wx-drawer-from: 0 100%;\n}\n\n@keyframes wx-drawer-in {\n from {\n translate: var(--wx-drawer-from);\n }\n}\n\n@keyframes wx-drawer-out {\n to {\n translate: var(--wx-drawer-from);\n }\n}\n\n@keyframes wx-drawer-fade-in {\n from {\n opacity: 0;\n }\n}\n\n@keyframes wx-drawer-fade-out {\n to {\n opacity: 0;\n }\n}\n\n.wx-drawer[data-state='open'] {\n animation: wx-drawer-in var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-drawer[data-state='closed'] {\n animation: wx-drawer-out var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-drawer__overlay[data-state='open'] {\n animation: wx-drawer-fade-in var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-drawer__overlay[data-state='closed'] {\n animation: wx-drawer-fade-out var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n/*\n * Small screens: a panel that leaves a strip of the page visible is a panel too narrow to\n * work in, so it takes the whole screen — the remembered size with it.\n */\n@media (max-width: 640px) {\n .wx-drawer {\n /* Tighter than on a desktop: every pixel of padding is a line of content lost. Inside a\n panel the step has already shrunk to 8 by this width, and it stays the one owner. */\n --wx-drawer-pad-x: var(--wx-gap, var(--wx-space-12));\n --wx-drawer-pad-y: var(--wx-space-10);\n --wx-drawer-body-pad: var(--wx-gap, var(--wx-space-12));\n }\n\n /* All but a panel that asked to keep its declared size — see `fullScreen`. */\n .wx-drawer:not(.wx-drawer--contained) {\n inset: 0;\n width: 100%;\n height: 100dvh;\n border: none;\n }\n\n /*\n * A contained panel is still bound by the screen it is on: whatever it was told to be,\n * it leaves a strip of the page showing, so that what it covers is obviously still there.\n */\n .wx-drawer--contained.wx-drawer--left,\n .wx-drawer--contained.wx-drawer--right {\n width: min(var(--wx-drawer-size, 380px), 82%);\n }\n\n .wx-drawer__head {\n gap: var(--wx-space-8);\n }\n\n .wx-drawer--split .wx-drawer__body {\n flex-direction: column;\n overflow: auto;\n }\n\n .wx-drawer--split .wx-drawer__sidebar,\n .wx-drawer--split .wx-drawer__content {\n overflow: visible;\n }\n\n .wx-drawer__sidebar {\n width: auto;\n border-right: none;\n border-bottom: 1px solid var(--wx-border-muted);\n }\n\n .wx-drawer__handle {\n display: none;\n }\n}\n\n/* A handle six pixels wide cannot be aimed at with a finger. */\n@media (pointer: coarse) {\n .wx-drawer__handle {\n display: none;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-drawer,\n .wx-drawer__overlay {\n animation: none;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport { useDropdown } from '../../composables/useDropdown'\nimport type { DropdownItemEmits, DropdownItemProps } from './types'\n\ndefineOptions({ name: 'WxDropdownItem', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<DropdownItemProps>(), {\n icon: undefined,\n href: undefined,\n target: undefined,\n as: undefined,\n tone: 'default',\n active: false,\n disabled: false,\n})\n\nconst emit = defineEmits<DropdownItemEmits>()\n\nconst dropdown = useDropdown()\n\nconst tag = computed(() => props.as ?? (props.href ? 'a' : 'button'))\n\nconst nativeAttrs = computed(() => {\n if (props.href) {\n return {\n href: props.disabled ? undefined : props.href,\n target: props.target,\n 'aria-disabled': props.disabled ? 'true' : undefined,\n tabindex: props.disabled ? -1 : undefined,\n }\n }\n if (props.as) return { 'aria-disabled': props.disabled ? 'true' : undefined }\n return { type: 'button' as const, disabled: props.disabled }\n})\n\nconst classes = computed(() => [\n 'wx-dropdown-item',\n `wx-dropdown-item--${props.tone}`,\n { 'is-active': props.active, 'is-disabled': props.disabled },\n])\n\nfunction onClick(event: MouseEvent) {\n if (props.disabled) {\n event.preventDefault()\n event.stopPropagation()\n return\n }\n\n emit('click', event)\n\n /*\n * The panel closes here as well as on its own click handler: an item rendered\n * outside the dropdown's panel — in a collapsed actions row, say — still behaves.\n */\n if (dropdown?.closeOnSelect()) dropdown.close()\n}\n</script>\n\n<template>\n <component :is=\"tag\" v-bind=\"{ ...nativeAttrs, ...$attrs }\" :class=\"classes\" @click=\"onClick\">\n <span v-if=\"icon || $slots.before\" class=\"wx-dropdown-item__before\">\n <slot name=\"before\">\n <wx-icon v-if=\"icon\" :name=\"icon\" />\n </slot>\n </span>\n\n <span class=\"wx-dropdown-item__label\"><slot /></span>\n\n <span v-if=\"$slots.after\" class=\"wx-dropdown-item__after\">\n <slot name=\"after\" />\n </span>\n </component>\n</template>\n\n<style scoped>\n.wx-dropdown-item {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n box-sizing: border-box;\n width: 100%;\n padding: var(--wx-space-6) var(--wx-space-10);\n background: none;\n border: none;\n border-radius: var(--wx-radius-xs);\n color: var(--wx-dropdown-item-color, var(--wx-text-default));\n font-family: inherit;\n font-size: var(--wx-font-size-sm);\n font-weight: var(--wx-font-weight-medium);\n line-height: var(--wx-font-line-height-normal);\n text-align: start;\n text-decoration: none;\n cursor: pointer;\n transition: background-color var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-dropdown-item:hover:not(.is-disabled),\n.wx-dropdown-item.is-active {\n background: var(--wx-dropdown-item-bg, var(--wx-bg-fill));\n}\n\n.wx-dropdown-item:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-dropdown-item--default {\n --wx-dropdown-item-color: var(--wx-text-default);\n}\n\n.wx-dropdown-item--default:hover:not(.is-disabled),\n.wx-dropdown-item--default.is-active {\n --wx-dropdown-item-color: var(--wx-color-primary);\n}\n\n.wx-dropdown-item--primary {\n --wx-dropdown-item-color: var(--wx-color-primary);\n --wx-dropdown-item-bg: var(--wx-color-primary-soft);\n}\n\n.wx-dropdown-item--danger {\n --wx-dropdown-item-color: var(--wx-color-danger);\n --wx-dropdown-item-bg: var(--wx-color-danger-soft);\n}\n\n.wx-dropdown-item--success {\n --wx-dropdown-item-color: var(--wx-color-success-active);\n --wx-dropdown-item-bg: var(--wx-color-success-soft);\n}\n\n.wx-dropdown-item--warning {\n --wx-dropdown-item-color: var(--wx-color-warning-active);\n --wx-dropdown-item-bg: var(--wx-color-warning-soft);\n}\n\n.wx-dropdown-item.is-disabled,\n.wx-dropdown-item:disabled {\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n.wx-dropdown-item__before,\n.wx-dropdown-item__after {\n display: inline-flex;\n align-items: center;\n flex: 0 0 auto;\n font-size: 16px;\n}\n\n.wx-dropdown-item__after {\n margin-left: auto;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n}\n\n.wx-dropdown-item__label {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport type { EmptyProps } from './types'\n\ndefineOptions({ name: 'WxEmpty' })\n\nconst props = withDefaults(defineProps<EmptyProps>(), {\n icon: 'file',\n title: undefined,\n description: undefined,\n size: 'md',\n plain: false,\n})\n\ndefineSlots<{\n /** Replaces the glyph — an illustration, a logo, whatever says it better. */\n icon?: () => unknown\n title?: () => unknown\n /** The explanation. Overrides `description`. */\n default?: () => unknown\n /** What to do about it: a button that clears the filter, one that adds a record. */\n actions?: () => unknown\n}>()\n\nconst classes = computed(() => ['wx-empty', `wx-empty--${props.size}`])\n</script>\n\n<template>\n <div :class=\"classes\">\n <div v-if=\"!plain\" class=\"wx-empty__icon\" aria-hidden=\"true\">\n <slot name=\"icon\">\n <wx-icon :name=\"icon\" />\n </slot>\n </div>\n\n <p v-if=\"title || $slots.title\" class=\"wx-empty__title\">\n <slot name=\"title\">{{ title }}</slot>\n </p>\n\n <p v-if=\"description || $slots.default\" class=\"wx-empty__description\">\n <slot>{{ description }}</slot>\n </p>\n\n <div v-if=\"$slots.actions\" class=\"wx-empty__actions\">\n <slot name=\"actions\" />\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n gap: var(--wx-empty-gap);\n padding: var(--wx-empty-padding);\n color: var(--wx-text-muted);\n font-family: var(--wx-font-family-sans);\n text-align: center;\n}\n\n.wx-empty--sm {\n --wx-empty-gap: var(--wx-space-6);\n --wx-empty-padding: var(--wx-space-16) var(--wx-space-12);\n --wx-empty-glyph: 24px;\n}\n\n.wx-empty--md {\n --wx-empty-gap: var(--wx-space-8);\n --wx-empty-padding: var(--wx-space-32) var(--wx-space-16);\n --wx-empty-glyph: 36px;\n}\n\n.wx-empty--lg {\n --wx-empty-gap: var(--wx-space-12);\n --wx-empty-padding: var(--wx-space-64) var(--wx-space-24);\n --wx-empty-glyph: 48px;\n}\n\n/*\n * The glyph is decoration, not information — the words below it carry the message,\n * so it is dimmed rather than drawn in a colour that asks to be looked at.\n */\n.wx-empty__icon {\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--wx-text-placeholder);\n}\n\n.wx-empty__icon :deep(.wx-icon) {\n width: var(--wx-empty-glyph);\n height: var(--wx-empty-glyph);\n}\n\n.wx-empty__title {\n margin: 0;\n color: var(--wx-text-default);\n font-size: var(--wx-font-size-sm);\n font-weight: var(--wx-font-weight-semibold);\n}\n\n.wx-empty__description {\n max-width: 42ch;\n margin: 0;\n font-size: var(--wx-font-size-sm);\n line-height: var(--wx-font-line-height-normal);\n}\n\n.wx-empty--lg .wx-empty__title {\n font-size: var(--wx-font-size-lg);\n}\n\n.wx-empty__actions {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: center;\n gap: var(--wx-space-8);\n margin-top: var(--wx-space-4);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, useSlots } from 'vue'\nimport type { EntityCardEmits, EntityCardProps } from './types'\n\ndefineOptions({ name: 'WxEntityCard' })\n\nconst props = withDefaults(defineProps<EntityCardProps>(), {\n title: undefined,\n href: undefined,\n subtitle: undefined,\n image: undefined,\n imageAlt: undefined,\n shape: 'rounded',\n imageSize: undefined,\n meta: () => [],\n titleLines: 1,\n size: 'md',\n variant: 'card',\n bordered: false,\n selected: false,\n})\n\nconst emit = defineEmits<EntityCardEmits>()\n\nconst slots = useSlots()\n\nconst defaultImageSize: Record<string, string> = { sm: '32px', md: '44px', lg: '64px' }\n\nconst imageSize = computed(() => {\n if (props.imageSize === undefined) return defaultImageSize[props.size]\n return typeof props.imageSize === 'number' ? `${props.imageSize}px` : props.imageSize\n})\n\nconst hasMedia = computed(() => Boolean(props.image || slots.media))\n\n/** With no picture, the first letter stands in — a list of rows stays aligned. */\nconst initial = computed(() => props.title?.trim().charAt(0).toUpperCase() ?? '')\n\nconst hasMeta = computed(() => Boolean(slots.meta || props.meta.length > 0))\n\nconst classes = computed(() => [\n 'wx-entity-card',\n `wx-entity-card--${props.size}`,\n `wx-entity-card--${props.variant}`,\n {\n 'wx-entity-card--bordered': props.bordered,\n 'wx-entity-card--clamp': props.titleLines > 1,\n 'is-selected': props.selected,\n },\n])\n</script>\n\n<template>\n <div\n :class=\"classes\"\n :style=\"{ '--wx-entity-card-image': imageSize, '--wx-entity-card-title-lines': titleLines }\"\n @click=\"emit('click', $event)\"\n >\n <div v-if=\"hasMedia\" class=\"wx-entity-card__media\" :class=\"`wx-entity-card__media--${shape}`\">\n <slot name=\"media\">\n <img :src=\"image\" :alt=\"imageAlt ?? title ?? ''\" class=\"wx-entity-card__image\" />\n </slot>\n </div>\n <div\n v-else-if=\"title\"\n class=\"wx-entity-card__media wx-entity-card__media--empty\"\n :class=\"`wx-entity-card__media--${shape}`\"\n aria-hidden=\"true\"\n >\n {{ initial }}\n </div>\n\n <div class=\"wx-entity-card__body\">\n <component\n :is=\"href ? 'a' : 'span'\"\n v-if=\"title || $slots.title\"\n class=\"wx-entity-card__title\"\n :href=\"href\"\n >\n <slot name=\"title\">{{ title }}</slot>\n </component>\n\n <span v-if=\"subtitle || $slots.subtitle\" class=\"wx-entity-card__subtitle\">\n <slot name=\"subtitle\">{{ subtitle }}</slot>\n </span>\n\n <div v-if=\"hasMeta\" class=\"wx-entity-card__meta\">\n <slot name=\"meta\">\n <span v-for=\"(item, index) in meta\" :key=\"index\" class=\"wx-entity-card__meta-item\">\n <span v-if=\"item.label\" class=\"wx-entity-card__meta-label\">{{ item.label }}:</span>\n <span v-if=\"item.text\" class=\"wx-entity-card__meta-text\">{{ item.text }}</span>\n </span>\n </slot>\n </div>\n\n <div v-if=\"$slots.default\" class=\"wx-entity-card__content\">\n <slot />\n </div>\n </div>\n\n <div v-if=\"$slots.actions\" class=\"wx-entity-card__actions\" @click.stop>\n <slot name=\"actions\" />\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-entity-card {\n display: flex;\n align-items: center;\n /* Wrapping is what makes a narrow card work: the actions drop to their own line\n instead of squeezing the title into two characters. */\n flex-wrap: wrap;\n gap: var(--wx-space-12);\n box-sizing: border-box;\n padding: var(--wx-entity-card-padding, var(--wx-space-12));\n border: 1px solid transparent;\n border-radius: var(--wx-radius-md);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n transition:\n background-color var(--wx-duration-fast) var(--wx-easing-standard),\n border-color var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-entity-card--sm {\n --wx-entity-card-padding: var(--wx-space-8);\n gap: var(--wx-space-8);\n}\n\n.wx-entity-card--lg {\n --wx-entity-card-padding: var(--wx-space-16);\n gap: var(--wx-space-16);\n}\n\n.wx-entity-card--card {\n background: var(--wx-bg-surface);\n box-shadow: var(--wx-shadow-card);\n}\n\n.wx-entity-card--plain {\n padding: 0;\n background: transparent;\n}\n\n.wx-entity-card--bordered {\n border-color: var(--wx-border-default);\n}\n\n/*\n * A border needs something to enclose: without this a plain card — which drops its\n * padding so it can sit inside another one — glues the thumbnail and the actions to\n * the outline.\n */\n.wx-entity-card--plain.wx-entity-card--bordered,\n.wx-entity-card--plain.is-selected {\n padding: var(--wx-entity-card-padding, var(--wx-space-12));\n}\n\n.wx-entity-card.is-selected {\n border-color: var(--wx-color-primary);\n background: var(--wx-color-primary-soft);\n}\n\n.wx-entity-card__media {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: var(--wx-entity-card-image, 44px);\n height: var(--wx-entity-card-image, 44px);\n overflow: hidden;\n background: var(--wx-bg-fill);\n}\n\n.wx-entity-card__media--rounded {\n border-radius: var(--wx-radius-xs);\n}\n\n.wx-entity-card__media--square {\n border-radius: 0;\n}\n\n.wx-entity-card__media--circle {\n border-radius: var(--wx-radius-full);\n}\n\n.wx-entity-card__media--empty {\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-lg);\n font-weight: var(--wx-font-weight-semibold);\n user-select: none;\n}\n\n.wx-entity-card__image {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.wx-entity-card__body {\n display: flex;\n flex-direction: column;\n gap: 2px;\n /* The basis is the point where the actions wrap; `min-width: 0` is what lets a long\n title be cut rather than stretch the row. */\n flex: 1 1 180px;\n min-width: 0;\n}\n\n.wx-entity-card__title {\n color: var(--wx-text-strong);\n font-size: var(--wx-font-size-md);\n font-weight: var(--wx-font-weight-semibold);\n line-height: var(--wx-font-line-height-tight);\n text-decoration: none;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/*\n * More than one line, and the cut moves from the end of the line to the end of the last one\n * allowed. Only then: a single line is what most lists want, and `-webkit-box` would turn the\n * title into a block for all of them.\n */\n.wx-entity-card--clamp .wx-entity-card__title {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: var(--wx-entity-card-title-lines, 1);\n line-clamp: var(--wx-entity-card-title-lines, 1);\n white-space: normal;\n}\n\n.wx-entity-card--sm .wx-entity-card__title {\n font-size: var(--wx-font-size-sm);\n}\n\na.wx-entity-card__title:hover {\n color: var(--wx-text-link);\n}\n\n.wx-entity-card__subtitle {\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wx-entity-card__meta {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-4) var(--wx-space-12);\n margin-top: 2px;\n color: var(--wx-text-default);\n font-size: var(--wx-font-size-xs);\n line-height: var(--wx-font-line-height-normal);\n}\n\n.wx-entity-card__meta-item {\n display: inline-flex;\n align-items: center;\n gap: var(--wx-space-4);\n min-width: 0;\n}\n\n.wx-entity-card__meta-label {\n color: var(--wx-text-muted);\n}\n\n.wx-entity-card__meta-text {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wx-entity-card__content {\n margin-top: var(--wx-space-8);\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-entity-card__actions {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n flex: 0 0 auto;\n margin-left: auto;\n}\n</style>\n","import type { LightboxSource, LightboxVideo } from './types'\n\n/** What the lightbox plays: a file in a `<video>`, or an address in an `<iframe>`. */\nexport type ResolvedVideo = { kind: 'file'; src: string } | { kind: 'embed'; src: string }\n\n/** An item with every default filled in, so the template asks no questions. */\nexport interface ResolvedItem {\n src: string\n alt: string\n caption: string\n thumb: string\n original: string | undefined\n video: ResolvedVideo | undefined\n}\n\nconst YOUTUBE_HOSTS = new Set([\n 'youtube.com',\n 'www.youtube.com',\n 'm.youtube.com',\n 'music.youtube.com',\n 'youtu.be',\n 'www.youtube-nocookie.com',\n 'youtube-nocookie.com',\n])\n\nconst YOUTUBE_ID = /^[A-Za-z0-9_-]{11}$/\n\n/** The id of a YouTube video in any form of its address — watch, short link, shorts, embed — or `null`. */\nexport function youTubeId(address: string): string | null {\n let url: URL\n\n try {\n url = new URL(address.trim())\n } catch {\n return null\n }\n\n const host = url.hostname.toLowerCase()\n if (!/^https?:$/.test(url.protocol) || !YOUTUBE_HOSTS.has(host)) return null\n\n if (host === 'youtu.be') {\n const id = url.pathname.split('/')[1] ?? ''\n return YOUTUBE_ID.test(id) ? id : null\n }\n\n const watched = url.pathname === '/watch' ? url.searchParams.get('v') : null\n if (watched !== null) return YOUTUBE_ID.test(watched) ? watched : null\n\n const [, kind, id] = url.pathname.split('/')\n\n return ['shorts', 'embed', 'live'].includes(kind ?? '') && YOUTUBE_ID.test(id ?? '')\n ? (id ?? null)\n : null\n}\n\n/*\n * The no-cookie host: a gallery should not hand its visitors to an advertiser for having\n * looked at a product. The player is only created on play, so `autoplay` is what the press\n * of the button asked for rather than a video that starts by itself.\n */\nfunction youTubeEmbed(id: string) {\n return `https://www.youtube-nocookie.com/embed/${id}?autoplay=1&rel=0`\n}\n\n/** An embed address that starts playing — the press of play has already happened. */\nfunction playing(address: string) {\n try {\n const url = new URL(address, 'https://example.invalid')\n if (!url.searchParams.has('autoplay')) url.searchParams.set('autoplay', '1')\n return url.origin === 'https://example.invalid' ? address : url.toString()\n } catch {\n return address\n }\n}\n\nfunction resolveVideo(video: string | LightboxVideo | undefined): ResolvedVideo | undefined {\n if (!video) return undefined\n\n if (typeof video === 'string') {\n const id = youTubeId(video)\n return id ? { kind: 'embed', src: youTubeEmbed(id) } : { kind: 'file', src: video }\n }\n\n const { embed, src } = video\n if (embed) {\n const id = youTubeId(embed)\n return { kind: 'embed', src: id ? youTubeEmbed(id) : playing(embed) }\n }\n if (src) return { kind: 'file', src }\n\n return undefined\n}\n\nexport function resolveItem(source: LightboxSource): ResolvedItem {\n const item = typeof source === 'string' ? { src: source } : source\n const src = item.src ?? ''\n const video = resolveVideo(item.video)\n\n return {\n src,\n alt: item.alt ?? '',\n caption: item.caption ?? item.alt ?? '',\n thumb: item.thumb ?? src,\n /* A video's poster is not what \"the original\" means; only an address given for it is. */\n original: item.original ?? (video ? undefined : src || undefined),\n video,\n }\n}\n\nexport function counter(\n text: string | ((index: number, total: number) => string),\n index: number,\n total: number,\n) {\n if (typeof text === 'function') return text(index, total)\n\n return text.replace('{index}', String(index)).replace('{total}', String(total))\n}\n","<script setup lang=\"ts\">\nimport { computed, nextTick, reactive, ref, watch } from 'vue'\nimport { DialogContent, DialogOverlay, DialogPortal, DialogRoot, DialogTitle } from 'reka-ui'\nimport WxIcon from '../Icon/Icon.vue'\nimport { clamp } from '../../composables/useOverlayPanel'\nimport { counter, resolveItem } from './items'\nimport type { LightboxEmits, LightboxProps } from './types'\n\ndefineOptions({ name: 'WxLightbox' })\n\n/*\n * A gallery over the whole screen: one item at a time, arrows and keys between them, a\n * strip of the rest, zoom and pan on a picture, and a player behind a video's poster.\n *\n * Reka's dialog brings what has no look of its own — the focus trap, Escape, the scroll\n * lock, the portal, giving focus back to whatever opened it. Everything that is seen is ours,\n * and the dimming is its own token: a photograph judged on a page that shows through it is\n * judged on the wrong colours.\n */\nconst props = withDefaults(defineProps<LightboxProps>(), {\n loop: false,\n /* `undefined` and not `false`: absent means \"when there is more than one\". */\n thumbnails: undefined,\n maxZoom: 4,\n original: true,\n ariaLabel: 'Gallery',\n prevLabel: 'Previous',\n nextLabel: 'Next',\n closeLabel: 'Close',\n zoomInLabel: 'Zoom in',\n zoomOutLabel: 'Zoom out',\n originalLabel: 'Open the original',\n playLabel: 'Play',\n counterText: '{index} of {total}',\n})\n\nconst emit = defineEmits<LightboxEmits>()\n\nconst open = defineModel<boolean>('open', { default: false })\nconst index = defineModel<number>('index', { default: 0 })\n\nconst list = computed(() => props.items.map(resolveItem))\nconst total = computed(() => list.value.length)\nconst position = computed(() => clamp(index.value, 0, Math.max(0, total.value - 1)))\nconst current = computed(() => list.value[position.value])\nconst many = computed(() => total.value > 1)\nconst strip = computed(() => (props.thumbnails ?? many.value) && many.value)\n\nconst canPrev = computed(() => many.value && (props.loop || position.value > 0))\nconst canNext = computed(() => many.value && (props.loop || position.value < total.value - 1))\n\nconst counterLabel = computed(() => counter(props.counterText, position.value + 1, total.value))\n\nfunction go(to: number) {\n if (!many.value) return\n const next = props.loop ? (to + total.value) % total.value : clamp(to, 0, total.value - 1)\n if (next === position.value) return\n index.value = next\n emit('change', next)\n}\n\nconst prev = () => go(position.value - 1)\nconst next = () => go(position.value + 1)\n\nfunction close() {\n open.value = false\n}\n\n/* ---------------------------------------------------------------- the item on screen */\n\nconst loaded = ref(false)\nconst failed = ref(false)\nconst playing = ref(false)\n\nconst isVideo = computed(() => Boolean(current.value?.video))\nconst zoomable = computed(() => !isVideo.value && loaded.value && !failed.value)\n\n/* ---------------------------------------------------------------- zoom and pan */\n\nconst stage = ref<HTMLElement | null>(null)\nconst picture = ref<HTMLImageElement | null>(null)\n\n/*\n * The picture is laid out to fit, and everything after that is a transform on top: `scale`\n * is a multiple of the fitted size, and `x`/`y` move the picture's centre away from the\n * stage's. Nothing is re-laid out while a finger moves.\n */\nconst view = reactive({ scale: 1, x: 0, y: 0 })\n\n/* A swipe in progress: how far the picture follows the finger before it lets go. */\nconst drag = reactive({ x: 0, y: 0, active: false })\n\nfunction resetView() {\n view.scale = 1\n view.x = 0\n view.y = 0\n}\n\n/** Actual pixels, as a multiple of the fitted size: what \"100%\" is for this picture. */\nfunction actualScale() {\n const img = picture.value\n if (!img || !img.offsetWidth || !img.naturalWidth) return 1\n return img.naturalWidth / img.offsetWidth\n}\n\nconst maxScale = () => Math.max(props.maxZoom, actualScale())\n\n/** Keeps the picture from being dragged off its own edge. */\nfunction clampPan() {\n const img = picture.value\n const box = stage.value\n if (!img || !box) return\n const spareX = Math.max(0, (img.offsetWidth * view.scale - box.clientWidth) / 2)\n const spareY = Math.max(0, (img.offsetHeight * view.scale - box.clientHeight) / 2)\n view.x = clamp(view.x, -spareX, spareX)\n view.y = clamp(view.y, -spareY, spareY)\n}\n\n/**\n * Zooms keeping the point `(px, py)` — measured from the stage's centre — where it is on\n * screen, which is what makes zooming at the cursor and between two fingers feel anchored.\n */\nfunction zoomTo(scale: number, px = 0, py = 0) {\n if (!zoomable.value) return\n const next = clamp(scale, 1, maxScale())\n const ratio = next / view.scale\n view.x = px - (px - view.x) * ratio\n view.y = py - (py - view.y) * ratio\n view.scale = next\n clampPan()\n}\n\nconst ZOOM_STEP = 1.5\n\nconst zoomIn = () => zoomTo(view.scale * ZOOM_STEP)\nconst zoomOut = () => zoomTo(view.scale / ZOOM_STEP)\nconst canZoomIn = computed(() => zoomable.value && view.scale < maxScale() - 0.001)\nconst canZoomOut = computed(() => zoomable.value && view.scale > 1)\n\nfunction fromCentre(clientX: number, clientY: number) {\n const box = stage.value?.getBoundingClientRect()\n if (!box) return { px: 0, py: 0 }\n return { px: clientX - box.left - box.width / 2, py: clientY - box.top - box.height / 2 }\n}\n\n/** Fitted ↔ close up: actual pixels, or twice the fit for a picture smaller than the screen. */\nfunction toggleZoom(clientX: number, clientY: number) {\n if (view.scale > 1) {\n resetView()\n return\n }\n const { px, py } = fromCentre(clientX, clientY)\n zoomTo(Math.max(actualScale(), 2), px, py)\n}\n\nfunction onWheel(event: WheelEvent) {\n if (!zoomable.value) return\n event.preventDefault()\n const { px, py } = fromCentre(event.clientX, event.clientY)\n zoomTo(view.scale * Math.exp(-event.deltaY * 0.002), px, py)\n}\n\n/* ---------------------------------------------------------------- pointers */\n\nconst pointers = new Map<number, { x: number; y: number }>()\n\n/* A finger or a button is down: the picture follows it with no easing. */\nconst moving = ref(false)\n\n/** Where a one-finger gesture started; the pinch keeps its own. */\nlet gesture: { x: number; y: number; viewX: number; viewY: number; moved: boolean } | null = null\nlet pinch: { distance: number } | null = null\nlet lastTap = { time: 0, x: 0, y: 0 }\n\n/** A tap moves less than this; a swipe needs more than the other. */\nconst TAP_SLOP = 6\nconst SWIPE = 60\nconst SWIPE_CLOSE = 110\nconst DOUBLE_TAP_MS = 300\n\nfunction spread() {\n const [a, b] = [...pointers.values()]\n if (!a || !b) return { distance: 0, x: 0, y: 0 }\n return {\n distance: Math.hypot(a.x - b.x, a.y - b.y),\n x: (a.x + b.x) / 2,\n y: (a.y + b.y) / 2,\n }\n}\n\nfunction onPointerDown(event: PointerEvent) {\n /* A playing video keeps its own controls: a drag across them is a seek, not a swipe. */\n if (playing.value || event.button !== 0) return\n pointers.set(event.pointerId, { x: event.clientX, y: event.clientY })\n ;(event.currentTarget as HTMLElement).setPointerCapture?.(event.pointerId)\n moving.value = true\n\n if (pointers.size === 2 && zoomable.value) {\n pinch = { distance: spread().distance }\n gesture = null\n drag.active = false\n drag.x = drag.y = 0\n return\n }\n\n if (pointers.size === 1) {\n gesture = { x: event.clientX, y: event.clientY, viewX: view.x, viewY: view.y, moved: false }\n }\n}\n\nfunction onPointerMove(event: PointerEvent) {\n if (!pointers.has(event.pointerId)) return\n pointers.set(event.pointerId, { x: event.clientX, y: event.clientY })\n\n if (pinch && pointers.size === 2) {\n const now = spread()\n if (!pinch.distance) return\n const { px, py } = fromCentre(now.x, now.y)\n zoomTo(view.scale * (now.distance / pinch.distance), px, py)\n pinch.distance = now.distance\n return\n }\n\n if (!gesture) return\n const dx = event.clientX - gesture.x\n const dy = event.clientY - gesture.y\n if (!gesture.moved && Math.hypot(dx, dy) < TAP_SLOP) return\n gesture.moved = true\n\n if (view.scale > 1) {\n view.x = gesture.viewX + dx\n view.y = gesture.viewY + dy\n clampPan()\n } else {\n drag.active = true\n drag.x = dx\n /* Only downwards: that is the gesture that closes. */\n drag.y = Math.max(0, dy)\n }\n}\n\nfunction onPointerUp(event: PointerEvent) {\n if (!pointers.delete(event.pointerId)) return\n moving.value = pointers.size > 0\n\n if (pinch) {\n if (pointers.size < 2) pinch = null\n return\n }\n\n const done = gesture\n gesture = null\n if (!done) return\n\n if (!done.moved) {\n onTap(event)\n return\n }\n\n if (drag.active) {\n const { x, y } = drag\n drag.active = false\n drag.x = drag.y = 0\n if (Math.abs(x) > SWIPE && Math.abs(x) > y) {\n if (x < 0) next()\n else prev()\n } else if (y > SWIPE_CLOSE && y > Math.abs(x)) {\n close()\n }\n }\n}\n\nfunction onPointerCancel(event: PointerEvent) {\n pointers.delete(event.pointerId)\n moving.value = pointers.size > 0\n gesture = null\n pinch = null\n drag.active = false\n drag.x = drag.y = 0\n}\n\n/*\n * Double-tap is counted here rather than left to `dblclick`: with `touch-action: none` a\n * phone does not send one, and a mouse sending both would zoom in and straight back out.\n */\nfunction onTap(event: PointerEvent) {\n const now = event.timeStamp\n const near = Math.hypot(event.clientX - lastTap.x, event.clientY - lastTap.y) < 24\n if (now - lastTap.time < DOUBLE_TAP_MS && near) {\n lastTap = { time: 0, x: 0, y: 0 }\n toggleZoom(event.clientX, event.clientY)\n return\n }\n lastTap = { time: now, x: event.clientX, y: event.clientY }\n}\n\nconst pictureStyle = computed(() => {\n const x = view.x + drag.x\n const y = view.y + drag.y\n return {\n transform: `translate3d(${x}px, ${y}px, 0) scale(${view.scale})`,\n /* The page shows through a little more the further a picture is pulled down to close. */\n opacity: drag.y ? String(Math.max(0.4, 1 - drag.y / 400)) : undefined,\n }\n})\n\n/* ---------------------------------------------------------------- keys */\n\nfunction onKeydown(event: KeyboardEvent) {\n if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey) return\n /* A focused player uses the arrows to seek. */\n if (event.target instanceof HTMLVideoElement) return\n\n const actions: Record<string, () => void> = {\n ArrowLeft: prev,\n ArrowRight: next,\n Home: () => go(0),\n End: () => go(total.value - 1),\n '+': zoomIn,\n '=': zoomIn,\n '-': zoomOut,\n '0': resetView,\n }\n\n const action = actions[event.key]\n if (!action) return\n event.preventDefault()\n action()\n}\n\n/* ---------------------------------------------------------------- moving between items */\n\n/* Every item starts fitted, stopped and unknown. */\nwatch(\n () => [position.value, current.value?.src, open.value],\n () => {\n loaded.value = false\n failed.value = false\n playing.value = false\n resetView()\n },\n)\n\n/* The items list shrank under an open lightbox: stay on the last one there is. */\nwatch(total, () => {\n if (total.value && index.value !== position.value) index.value = position.value\n})\n\n/* The neighbours are fetched before they are asked for, so an arrow is never a wait. */\nwatch(\n () => [open.value, position.value],\n () => {\n if (!open.value || typeof Image === 'undefined') return\n for (const step of [1, -1]) {\n const neighbour = list.value[(position.value + step + total.value) % total.value]\n if (neighbour?.src) new Image().src = neighbour.src\n }\n },\n { immediate: true },\n)\n\nconst thumbs = ref<HTMLElement | null>(null)\n\n/*\n * The strip is scrolled by hand: `scrollIntoView` would scroll every scrollable ancestor\n * too, the page under the lightbox — and a page in a frame — included.\n */\nwatch(\n () => [open.value, position.value],\n async () => {\n if (!open.value) return\n await nextTick()\n const row = thumbs.value\n const thumb = row?.children[position.value] as HTMLElement | undefined\n if (!row || !thumb) return\n row.scrollLeft = thumb.offsetLeft - (row.clientWidth - thumb.offsetWidth) / 2\n },\n { immediate: true },\n)\n\nconst root = ref<HTMLElement | null>(null)\n\n/* Focus goes to the gallery itself, so the arrows work at once and no button looks pressed. */\nfunction onOpenAutoFocus(event: Event) {\n event.preventDefault()\n root.value?.focus()\n}\n</script>\n\n<template>\n <dialog-root v-model:open=\"open\">\n <dialog-portal>\n <dialog-overlay class=\"wx-lightbox__overlay\" />\n\n <dialog-content\n class=\"wx-lightbox\"\n :aria-describedby=\"undefined\"\n @open-auto-focus=\"onOpenAutoFocus\"\n >\n <div ref=\"root\" class=\"wx-lightbox__frame\" tabindex=\"-1\" @keydown=\"onKeydown\">\n <dialog-title class=\"wx-lightbox__title\">\n {{ current?.caption || ariaLabel }}\n </dialog-title>\n\n <div class=\"wx-lightbox__bar\">\n <span v-if=\"many\" class=\"wx-lightbox__chip wx-lightbox__counter\" aria-live=\"polite\">\n {{ counterLabel }}\n </span>\n <span v-else />\n\n <div class=\"wx-lightbox__chip wx-lightbox__tools\">\n <template v-if=\"!isVideo\">\n <button\n type=\"button\"\n class=\"wx-lightbox__tool\"\n :aria-label=\"zoomOutLabel\"\n :title=\"zoomOutLabel\"\n :disabled=\"!canZoomOut\"\n @click=\"zoomOut\"\n >\n <wx-icon name=\"zoom-out\" />\n </button>\n <button\n type=\"button\"\n class=\"wx-lightbox__tool\"\n :aria-label=\"zoomInLabel\"\n :title=\"zoomInLabel\"\n :disabled=\"!canZoomIn\"\n @click=\"zoomIn\"\n >\n <wx-icon name=\"zoom-in\" />\n </button>\n </template>\n <a\n v-if=\"original && current?.original\"\n class=\"wx-lightbox__tool\"\n :href=\"current.original\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n :aria-label=\"originalLabel\"\n :title=\"originalLabel\"\n >\n <wx-icon name=\"external-link\" />\n </a>\n <button\n type=\"button\"\n class=\"wx-lightbox__tool\"\n :aria-label=\"closeLabel\"\n :title=\"closeLabel\"\n @click=\"close\"\n >\n <wx-icon name=\"close\" />\n </button>\n </div>\n </div>\n\n <div\n ref=\"stage\"\n class=\"wx-lightbox__stage\"\n :class=\"{\n 'is-zoomed': view.scale > 1,\n 'is-moving': moving,\n 'is-zoomable': zoomable,\n }\"\n @pointerdown=\"onPointerDown\"\n @pointermove=\"onPointerMove\"\n @pointerup=\"onPointerUp\"\n @pointercancel=\"onPointerCancel\"\n @wheel=\"onWheel\"\n >\n <template v-if=\"current\">\n <template v-if=\"current.video && playing\">\n <iframe\n v-if=\"current.video.kind === 'embed'\"\n :key=\"`embed-${position}`\"\n class=\"wx-lightbox__player\"\n :src=\"current.video.src\"\n :title=\"current.caption || ariaLabel\"\n allow=\"autoplay; fullscreen; picture-in-picture; encrypted-media\"\n allowfullscreen\n />\n <video\n v-else\n :key=\"`video-${position}`\"\n class=\"wx-lightbox__player\"\n :src=\"current.video.src\"\n :poster=\"current.src || undefined\"\n controls\n autoplay\n playsinline\n />\n </template>\n\n <template v-else>\n <!--\n The thumbnail stretched underneath, as `WxImage` does: on a slow line the\n picture arrives into its own blurred outline instead of into nothing.\n -->\n <img\n v-if=\"!loaded && !failed && current.thumb && current.thumb !== current.src\"\n class=\"wx-lightbox__blur\"\n :src=\"current.thumb\"\n alt=\"\"\n aria-hidden=\"true\"\n />\n <img\n v-if=\"current.src && !failed\"\n ref=\"picture\"\n :key=\"`picture-${position}`\"\n class=\"wx-lightbox__picture\"\n :class=\"{ 'is-loaded': loaded }\"\n :src=\"current.src\"\n :alt=\"current.alt\"\n :style=\"pictureStyle\"\n draggable=\"false\"\n @load=\"loaded = true\"\n @error=\"failed = true\"\n />\n <div v-else-if=\"!current.video\" class=\"wx-lightbox__failed\">\n <wx-icon name=\"image\" />\n </div>\n\n <button\n v-if=\"current.video\"\n type=\"button\"\n class=\"wx-lightbox__play\"\n :aria-label=\"playLabel\"\n @pointerdown.stop\n @click=\"playing = true\"\n >\n <wx-icon name=\"play\" />\n </button>\n </template>\n </template>\n </div>\n\n <button\n v-if=\"many\"\n type=\"button\"\n class=\"wx-lightbox__arrow wx-lightbox__arrow--prev\"\n :aria-label=\"prevLabel\"\n :title=\"prevLabel\"\n :disabled=\"!canPrev\"\n @click=\"prev\"\n >\n <wx-icon name=\"chevron-left\" />\n </button>\n <button\n v-if=\"many\"\n type=\"button\"\n class=\"wx-lightbox__arrow wx-lightbox__arrow--next\"\n :aria-label=\"nextLabel\"\n :title=\"nextLabel\"\n :disabled=\"!canNext\"\n @click=\"next\"\n >\n <wx-icon name=\"chevron-right\" />\n </button>\n\n <div class=\"wx-lightbox__foot\">\n <p v-if=\"current?.caption\" class=\"wx-lightbox__chip wx-lightbox__caption\">\n {{ current.caption }}\n </p>\n\n <div v-if=\"strip\" ref=\"thumbs\" class=\"wx-lightbox__thumbs\">\n <button\n v-for=\"(item, i) in list\"\n :key=\"i\"\n type=\"button\"\n class=\"wx-lightbox__thumb\"\n :class=\"{ 'is-current': i === position }\"\n :aria-label=\"counter(counterText, i + 1, total)\"\n :aria-current=\"i === position ? 'true' : undefined\"\n @click=\"go(i)\"\n >\n <img v-if=\"item.thumb\" :src=\"item.thumb\" alt=\"\" loading=\"lazy\" draggable=\"false\" />\n <wx-icon v-else :name=\"item.video ? 'play' : 'image'\" />\n <span v-if=\"item.video && item.thumb\" class=\"wx-lightbox__thumb-play\">\n <wx-icon name=\"play\" />\n </span>\n </button>\n </div>\n </div>\n </div>\n </dialog-content>\n </dialog-portal>\n </dialog-root>\n</template>\n\n<style scoped>\n/*\n * A layer of its own, above dialogs, for both the dimming and the gallery: a lightbox is most\n * often opened from a dialog — a file picker, a gallery field — and a dimming on the overlay\n * layer is drawn under that dialog, which then stands between the photo and its strip.\n */\n.wx-lightbox__overlay {\n position: fixed;\n inset: 0;\n z-index: var(--wx-z-index-lightbox);\n background: var(--wx-bg-lightbox);\n}\n\n.wx-lightbox {\n position: fixed;\n inset: 0;\n z-index: var(--wx-z-index-lightbox);\n outline: none;\n}\n\n.wx-lightbox__frame {\n position: relative;\n display: grid;\n grid-template-rows: auto minmax(0, 1fr) auto;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n font-family: var(--wx-font-family-sans);\n outline: none;\n}\n\n.wx-lightbox__title {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n\n/* ------------------------------------------------------------ bar and chips */\n\n.wx-lightbox__bar {\n position: relative;\n z-index: 1;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--wx-space-12);\n padding: var(--wx-space-12) var(--wx-space-16);\n}\n\n/* Everything with words or buttons on it sits on a surface, never straight on the dimming. */\n.wx-lightbox__chip {\n box-sizing: border-box;\n background: var(--wx-bg-surface);\n color: var(--wx-text-default);\n border-radius: var(--wx-radius-full);\n box-shadow: var(--wx-shadow-popover);\n}\n\n.wx-lightbox__counter {\n padding: var(--wx-space-6) var(--wx-space-14);\n font-size: var(--wx-font-size-sm);\n font-variant-numeric: tabular-nums;\n}\n\n.wx-lightbox__tools {\n display: flex;\n gap: var(--wx-space-2);\n padding: var(--wx-space-4);\n}\n\n.wx-lightbox__tool,\n.wx-lightbox__arrow,\n.wx-lightbox__play {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n border: none;\n color: inherit;\n cursor: pointer;\n transition:\n background-color var(--wx-duration-fast) var(--wx-easing-standard),\n opacity var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-lightbox__tool {\n width: var(--wx-size-control-sm);\n height: var(--wx-size-control-sm);\n background: transparent;\n border-radius: var(--wx-radius-full);\n}\n\n.wx-lightbox__tool:hover:not(:disabled) {\n background: var(--wx-bg-fill);\n}\n\n.wx-lightbox__tool:disabled,\n.wx-lightbox__arrow:disabled {\n cursor: default;\n opacity: 0.4;\n}\n\n.wx-lightbox__tool:focus-visible,\n.wx-lightbox__arrow:focus-visible,\n.wx-lightbox__play:focus-visible,\n.wx-lightbox__thumb:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n/* ------------------------------------------------------------ stage */\n\n.wx-lightbox__stage {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 0;\n overflow: hidden;\n padding: 0 var(--wx-space-64);\n /* Every gesture here is ours: the phone must not scroll or zoom the page underneath. */\n touch-action: none;\n user-select: none;\n}\n\n.wx-lightbox__stage.is-zoomable {\n cursor: zoom-in;\n}\n\n.wx-lightbox__stage.is-zoomed {\n cursor: grab;\n}\n\n.wx-lightbox__stage.is-zoomed.is-moving {\n cursor: grabbing;\n}\n\n.wx-lightbox__picture,\n.wx-lightbox__blur {\n display: block;\n max-width: 100%;\n max-height: 100%;\n object-fit: contain;\n}\n\n.wx-lightbox__picture {\n position: relative;\n opacity: 0;\n transform-origin: center;\n transition:\n opacity var(--wx-duration-normal) var(--wx-easing-standard),\n transform var(--wx-duration-normal) var(--wx-easing-standard);\n will-change: transform;\n -webkit-user-drag: none;\n}\n\n.wx-lightbox__picture.is-loaded {\n opacity: 1;\n}\n\n/* Under a finger the picture follows at once; the easing is for letting go and for buttons. */\n.wx-lightbox__stage.is-moving .wx-lightbox__picture {\n transition: none;\n}\n\n.wx-lightbox__blur {\n position: absolute;\n width: 100%;\n height: 100%;\n filter: blur(16px);\n opacity: 0.6;\n}\n\n.wx-lightbox__failed {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 160px;\n height: 160px;\n border-radius: var(--wx-radius-lg);\n background: var(--wx-bg-surface);\n color: var(--wx-text-placeholder);\n}\n\n.wx-lightbox__failed :deep(.wx-icon) {\n width: 40px;\n height: 40px;\n}\n\n.wx-lightbox__player {\n display: block;\n width: min(100%, calc((100vh - 220px) * 16 / 9));\n max-height: 100%;\n aspect-ratio: 16 / 9;\n border: none;\n background: var(--wx-color-black);\n}\n\nvideo.wx-lightbox__player {\n width: auto;\n max-width: 100%;\n aspect-ratio: auto;\n}\n\n.wx-lightbox__play {\n position: absolute;\n top: 50%;\n left: 50%;\n width: 72px;\n height: 72px;\n margin: -36px 0 0 -36px;\n background: var(--wx-bg-surface);\n color: var(--wx-text-default);\n border-radius: var(--wx-radius-full);\n box-shadow: var(--wx-shadow-dialog);\n}\n\n.wx-lightbox__play:hover {\n background: var(--wx-bg-subtle);\n}\n\n.wx-lightbox__play :deep(.wx-icon) {\n width: 30px;\n height: 30px;\n /* A triangle is heavier on its left; nudged, it looks centred. */\n margin-left: 4px;\n}\n\n/* ------------------------------------------------------------ arrows */\n\n.wx-lightbox__arrow {\n position: absolute;\n top: 50%;\n z-index: 1;\n width: var(--wx-size-control-lg);\n height: var(--wx-size-control-lg);\n margin-top: calc(var(--wx-size-control-lg) / -2);\n background: var(--wx-bg-surface);\n color: var(--wx-text-default);\n border-radius: var(--wx-radius-full);\n box-shadow: var(--wx-shadow-popover);\n}\n\n.wx-lightbox__arrow:hover:not(:disabled) {\n background: var(--wx-bg-subtle);\n}\n\n.wx-lightbox__arrow--prev {\n left: var(--wx-space-12);\n}\n\n.wx-lightbox__arrow--next {\n right: var(--wx-space-12);\n}\n\n/* ------------------------------------------------------------ caption and strip */\n\n.wx-lightbox__foot {\n position: relative;\n z-index: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--wx-space-10);\n min-width: 0;\n padding: var(--wx-space-12) var(--wx-space-16) var(--wx-space-16);\n}\n\n.wx-lightbox__caption {\n max-width: min(720px, 100%);\n margin: 0;\n padding: var(--wx-space-6) var(--wx-space-16);\n border-radius: var(--wx-radius-lg);\n font-size: var(--wx-font-size-sm);\n line-height: var(--wx-font-line-height-normal);\n text-align: center;\n}\n\n.wx-lightbox__thumbs {\n position: relative;\n display: flex;\n gap: var(--wx-space-8);\n max-width: 100%;\n padding: var(--wx-space-4);\n overflow-x: auto;\n scrollbar-width: none;\n scroll-behavior: smooth;\n}\n\n.wx-lightbox__thumb {\n position: relative;\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 64px;\n height: 48px;\n padding: 0;\n overflow: hidden;\n background: var(--wx-bg-surface);\n color: var(--wx-text-placeholder);\n border: 2px solid transparent;\n border-radius: var(--wx-radius-md);\n cursor: pointer;\n opacity: 0.55;\n transition:\n opacity var(--wx-duration-fast) var(--wx-easing-standard),\n border-color var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-lightbox__thumb:hover {\n opacity: 0.85;\n}\n\n.wx-lightbox__thumb.is-current {\n border-color: var(--wx-color-primary);\n opacity: 1;\n}\n\n.wx-lightbox__thumb img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.wx-lightbox__thumb-play {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--wx-color-white);\n background: color-mix(in srgb, var(--wx-color-black) 30%, transparent);\n}\n\n/* ------------------------------------------------------------ small screens */\n\n@media (max-width: 640px) {\n .wx-lightbox__stage {\n padding: 0;\n }\n\n /* A phone swipes; the arrows would only cover the picture. */\n .wx-lightbox__arrow,\n .wx-lightbox__thumbs {\n display: none;\n }\n}\n\n/* ------------------------------------------------------------ motion */\n\n.wx-lightbox__overlay[data-state='open'],\n.wx-lightbox[data-state='open'] {\n animation: wx-lightbox-in var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-lightbox__overlay[data-state='closed'],\n.wx-lightbox[data-state='closed'] {\n animation: wx-lightbox-out var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n@keyframes wx-lightbox-in {\n from {\n opacity: 0;\n }\n}\n\n@keyframes wx-lightbox-out {\n to {\n opacity: 0;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-lightbox__overlay,\n .wx-lightbox,\n .wx-lightbox__picture,\n .wx-lightbox__thumb,\n .wx-lightbox__thumbs {\n animation: none !important;\n transition: none !important;\n scroll-behavior: auto;\n }\n}\n</style>\n","import { inject, type InjectionKey } from 'vue'\nimport type { LightboxItem } from '../components/Lightbox/types'\n\n/** One picture in a group: where it is on the page, and what it opens as. */\nexport interface ImageGroupEntry {\n el: () => Element | null\n item: () => LightboxItem\n}\n\nexport interface ImageGroupContext {\n /** Joins the group; the answer leaves it. */\n register: (entry: ImageGroupEntry) => () => void\n /** Opens the group's lightbox on this picture. */\n open: (entry: ImageGroupEntry) => void\n}\n\nexport const imageGroupKey: InjectionKey<ImageGroupContext> = Symbol('wx-image-group')\n\n/** The `WxImageGroup` around this component, if there is one. */\nexport function useImageGroup() {\n return inject(imageGroupKey, null)\n}\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport WxLightbox from '../Lightbox/Lightbox.vue'\nimport { useImageGroup, type ImageGroupEntry } from '../../composables/useImageGroup'\nimport type { ImageEmits, ImageProps } from './types'\n\ndefineOptions({ name: 'WxImage' })\n\nconst props = withDefaults(defineProps<ImageProps>(), {\n src: undefined,\n alt: undefined,\n fit: 'cover',\n width: undefined,\n height: undefined,\n radius: undefined,\n lazy: true,\n placeholder: undefined,\n preview: false,\n previewList: undefined,\n previewStart: undefined,\n previewLabel: 'View full size',\n})\n\nconst emit = defineEmits<ImageEmits>()\n\ndefineSlots<{\n /** Shown while the picture is on its way. */\n placeholder?: () => unknown\n /** Shown instead of a picture that will not load. */\n error?: () => unknown\n}>()\n\nconst loaded = ref(false)\nconst failed = ref(false)\nconst previewing = ref(false)\n\n/* A new picture starts over: the last one's outcome says nothing about this one. */\nwatch(\n () => props.src,\n () => {\n loaded.value = false\n failed.value = false\n },\n)\n\nfunction onLoad(event: Event) {\n loaded.value = true\n emit('load', event)\n}\n\nfunction onError(event: Event) {\n failed.value = true\n emit('error', event)\n}\n\nconst root = ref<HTMLElement | null>(null)\n\n/*\n * Inside a `WxImageGroup` the picture is one item of the group's gallery, unless it brings a\n * gallery of its own. The group reads `src` and `alt` when it opens, so a picture that\n * changed since it joined is shown as it is now.\n */\nconst group = useImageGroup()\nconst entry: ImageGroupEntry = {\n el: () => root.value,\n item: () => ({ src: props.src, alt: props.alt }),\n}\n\nwatch(\n () => Boolean(group && props.preview && !props.previewList),\n (joined, _, onCleanup) => {\n if (joined && group) onCleanup(group.register(entry))\n },\n { immediate: true },\n)\n\nconst previewItems = computed(() => props.previewList ?? [{ src: props.src, alt: props.alt }])\n\nfunction startIndex() {\n if (props.previewStart !== undefined) return props.previewStart\n const found = previewItems.value.findIndex(\n (item) => (typeof item === 'string' ? item : item.src) === props.src,\n )\n return Math.max(0, found)\n}\n\n/* The lightbox is made on the first click: a library of a hundred pictures needs none of them until then. */\nconst lightboxMade = ref(false)\nconst lightboxIndex = ref(0)\n\nfunction openPreview() {\n if (group && !props.previewList) {\n group.open(entry)\n return\n }\n lightboxIndex.value = startIndex()\n lightboxMade.value = true\n previewing.value = true\n}\n\nfunction length(value: number | string | undefined) {\n if (value === undefined) return undefined\n return typeof value === 'number' ? `${value}px` : value\n}\n\nconst style = computed(() => ({\n width: length(props.width),\n height: length(props.height),\n borderRadius: length(props.radius),\n}))\n</script>\n\n<template>\n <div\n ref=\"root\"\n class=\"wx-image\"\n :class=\"{ 'is-loaded': loaded, 'is-failed': failed }\"\n :style=\"style\"\n >\n <!--\n The placeholder is underneath rather than instead of: the picture lands on top\n of it when it arrives, so nothing in the layout moves and there is no frame in\n which the box is empty.\n -->\n <div v-if=\"!loaded && !failed\" class=\"wx-image__placeholder\">\n <slot name=\"placeholder\">\n <img\n v-if=\"placeholder\"\n class=\"wx-image__blur\"\n :src=\"placeholder\"\n alt=\"\"\n aria-hidden=\"true\"\n />\n </slot>\n </div>\n\n <div v-if=\"failed\" class=\"wx-image__failed\">\n <slot name=\"error\">\n <wx-icon name=\"image\" />\n </slot>\n </div>\n\n <img\n v-if=\"src && !failed\"\n class=\"wx-image__img\"\n :src=\"src\"\n :alt=\"alt ?? ''\"\n :loading=\"lazy ? 'lazy' : 'eager'\"\n :decoding=\"lazy ? 'async' : 'auto'\"\n :style=\"{ objectFit: fit }\"\n @load=\"onLoad\"\n @error=\"onError\"\n />\n\n <button\n v-if=\"preview && loaded\"\n type=\"button\"\n class=\"wx-image__preview\"\n :aria-label=\"previewLabel\"\n @click=\"openPreview\"\n >\n <wx-icon name=\"search\" />\n </button>\n\n <wx-lightbox\n v-if=\"lightboxMade\"\n v-model:open=\"previewing\"\n v-model:index=\"lightboxIndex\"\n :items=\"previewItems\"\n />\n </div>\n</template>\n\n<style scoped>\n.wx-image {\n position: relative;\n display: inline-block;\n box-sizing: border-box;\n overflow: hidden;\n background: var(--wx-bg-fill);\n vertical-align: middle;\n}\n\n.wx-image__img {\n display: block;\n width: 100%;\n height: 100%;\n border-radius: inherit;\n opacity: 0;\n transition: opacity var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-image.is-loaded .wx-image__img {\n opacity: 1;\n}\n\n.wx-image__placeholder,\n.wx-image__failed {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--wx-text-placeholder);\n}\n\n.wx-image__blur {\n width: 100%;\n height: 100%;\n /* A thumbnail stretched to full size is a smear unless it is blurred on purpose. */\n filter: blur(12px);\n object-fit: cover;\n transform: scale(1.06);\n}\n\n.wx-image__failed :deep(.wx-icon) {\n width: 32px;\n height: 32px;\n}\n\n.wx-image__preview {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n background: color-mix(in srgb, var(--wx-bg-inverse) 45%, transparent);\n border: none;\n color: var(--wx-text-inverse);\n cursor: zoom-in;\n opacity: 0;\n transition: opacity var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-image__preview:hover,\n.wx-image__preview:focus-visible {\n outline: none;\n opacity: 1;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-image__img,\n .wx-image__preview {\n transition: none;\n }\n}\n</style>\n","import { computed, inject, provide, ref, type ComputedRef, type InjectionKey, type Ref } from 'vue'\n\n/**\n * One language the *content* is written in — not the language the panel is drawn in.\n *\n * A panel in English routinely edits a site published in Ukrainian and Russian, so the two lists\n * are unrelated: this one comes from the site's own settings.\n */\nexport interface LocaleOption {\n code: string\n /** What the selector shows. The code in capitals when nothing better is given. */\n label?: string\n}\n\n/** A field's value in every language it is written in: `{ uk: 'Двигуни', ru: 'Двигатели' }`. */\nexport type LocalizedValue = Record<string, string>\n\nexport interface LocalesContext {\n list: Ref<LocaleOption[]>\n /**\n * The language being edited, shared by every field on the screen.\n *\n * One selector per field, all moving together: switching a page to Russian and then finding\n * the field below still in Ukrainian is how half-translated records get saved.\n */\n active: Ref<string>\n}\n\nexport const localesKey: InjectionKey<LocalesContext> = Symbol('wx-locales')\n\n/*\n * The fallback, for a field used outside a panel — a story, a test, a form assembled by hand.\n * Module-level so those fields still agree with each other, and replaced by `provideLocales`\n * wherever there is a real application to ask.\n */\nconst standalone: LocalesContext = { list: ref([]), active: ref('') }\n\n/**\n * Tells every localized field below which languages the site publishes in.\n *\n * ```ts\n * provideLocales(computed(() => admin.i18n.state.contentLocales))\n * ```\n */\nexport function provideLocales(list: Ref<LocaleOption[]> | ComputedRef<LocaleOption[]>): void {\n provide(localesKey, { list, active: ref(list.value[0]?.code ?? '') })\n}\n\nexport function useLocales(): LocalesContext {\n return inject(localesKey, standalone)\n}\n\n/** The label a selector shows for a locale. */\nexport function localeLabel(locale: LocaleOption): string {\n return locale.label ?? locale.code.toUpperCase()\n}\n\n/**\n * Reads a localized value for display: the asked-for language, then anything that is filled in.\n *\n * A record half-translated is the normal state of a site being worked on, and a blank cell in a\n * table says less than the language that does have the words.\n */\nexport function localizedValue(\n value: LocalizedValue | string | null | undefined,\n locale?: string,\n fallback = '',\n): string {\n if (value === null || value === undefined) return fallback\n if (typeof value === 'string') return value\n\n const asked = locale === undefined ? undefined : value[locale]\n if (asked) return asked\n\n for (const line of Object.values(value)) {\n if (line) return line\n }\n\n return fallback\n}\n\nexport interface LocalizedFieldProps {\n /**\n * Edits the value in every language the site publishes in, with a selector on the field.\n *\n * The model then carries `{ uk: '…', ru: '…' }` rather than a string.\n */\n localized?: boolean\n}\n\n/**\n * What a text control needs to render itself once per language.\n *\n * The non-localized case is the same code path with one nameless slot, so a control has one\n * template rather than two that drift apart.\n */\nexport function useLocalized(props: LocalizedFieldProps, model: Ref<unknown>) {\n const locales = useLocales()\n\n const on = computed(() => props.localized === true && locales.list.value.length > 0)\n\n const active = computed({\n get: () => {\n const chosen = locales.active.value\n const known = locales.list.value.some((locale) => locale.code === chosen)\n\n return known ? chosen : (locales.list.value[0]?.code ?? '')\n },\n set: (code: string) => {\n locales.active.value = code\n },\n })\n\n /** One entry per rendered control: the locales, or a single `undefined` when off. */\n const slots = computed<(string | undefined)[]>(() =>\n on.value ? locales.list.value.map((locale) => locale.code) : [undefined],\n )\n\n function read(code: string | undefined): string {\n const value = model.value\n\n if (code === undefined) {\n return value === null || value === undefined ? '' : String(value)\n }\n\n /*\n * A plain string under `localized` is a column that used to hold one language — switching\n * the field on should show those words, not hide them. They belong to the first locale,\n * and the first write turns the value into a record.\n */\n if (typeof value === 'string') {\n return code === locales.list.value[0]?.code ? value : ''\n }\n\n if (typeof value !== 'object' || value === null) return ''\n\n return String((value as LocalizedValue)[code] ?? '')\n }\n\n function write(code: string | undefined, next: string): void {\n if (code === undefined) {\n model.value = next\n\n return\n }\n\n const current = model.value\n const base: LocalizedValue =\n typeof current === 'string'\n ? { [locales.list.value[0]?.code ?? code]: current }\n : typeof current === 'object' && current !== null\n ? { ...(current as LocalizedValue) }\n : {}\n\n model.value = { ...base, [code]: next }\n }\n\n /** `title` becomes `title[uk]`, which is the shape a classic form post is read back in. */\n function nameFor(name: unknown, code: string | undefined): string | undefined {\n if (typeof name !== 'string' || name === '') return undefined\n\n return code === undefined ? name : `${name}[${code}]`\n }\n\n return { on, active, slots, list: locales.list, read, write, nameFor }\n}\n","<script setup lang=\"ts\">\nimport { localeLabel, type LocaleOption } from '../../composables/useLocalized'\n\n/**\n * The chip in the corner of a localized field.\n *\n * Folded up it shows the language being edited; pointed at, every language unrolls beneath it\n * in the site's own order — the current one included and marked, so the list never reshuffles\n * under the pointer. Not exported: a field gets this by asking for `localized`, and a section\n * gets it through `WxLocales`.\n */\ndefineOptions({ name: 'WxLocalePicker' })\n\nconst props = defineProps<{\n locales: LocaleOption[]\n active: string\n}>()\n\nconst emit = defineEmits<{ choose: [code: string] }>()\n\nconst current = () => props.locales.find((locale) => locale.code === props.active)\n</script>\n\n<template>\n <div class=\"wx-locale-picker\">\n <button\n type=\"button\"\n class=\"wx-locale-picker__current\"\n :aria-label=\"active\"\n @click=\"emit('choose', active)\"\n >\n {{ current() ? localeLabel(current() as LocaleOption) : active }}\n </button>\n\n <button\n v-for=\"locale in locales\"\n :key=\"locale.code\"\n type=\"button\"\n :class=\"['wx-locale-picker__code', { 'is-active': locale.code === active }]\"\n :aria-label=\"locale.code\"\n tabindex=\"-1\"\n @click=\"emit('choose', locale.code)\"\n >\n {{ localeLabel(locale) }}\n </button>\n </div>\n</template>\n\n<style scoped>\n/*\n * It floats rather than taking space, so turning a field localized does not move the form\n * around it, and unrolls over whatever is below rather than pushing it down.\n */\n.wx-locale-picker {\n /*\n * The host may set these; the defaults live in the `var()` fallbacks rather than as\n * declarations here, because a property declared on this element would override the one\n * inherited from the host and the host could never say anything.\n *\n * A single-line field centres the chip on its middle line; a textarea is tall, so it pins the\n * chip near the top and makes it a size smaller.\n */\n position: absolute;\n top: var(--wx-locale-picker-top, 50%);\n right: var(--wx-space-4);\n /*\n * Unrolled it hangs over whatever is below — including the next field's own chip, which sits\n * at this same corner one control down. Two pickers at the same depth overlap into an\n * unreadable stack, so the one being pointed at leaves the others well beneath it.\n */\n z-index: 2;\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 2px;\n border: 1px solid transparent;\n border-radius: var(--wx-radius-sm);\n background: transparent;\n /*\n * The chip belongs on the middle line of the control, so the box is lifted by half the chip\n * — not by half of itself: unrolled, the box is four chips tall, and lifting by half of that\n * would drag the chip up as the list appears. The 3px is the border and the padding above it.\n */\n transform: translateY(\n var(--wx-locale-picker-shift, calc(-1 * (var(--wx-locale-picker-height, 24px) / 2 + 3px)))\n );\n transition:\n background-color var(--wx-duration-fast) var(--wx-easing-standard),\n border-color var(--wx-duration-fast) var(--wx-easing-standard),\n box-shadow var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-locale-picker:hover,\n.wx-locale-picker:focus-within {\n z-index: 40;\n border-color: var(--wx-border-default);\n background: var(--wx-bg-surface);\n box-shadow: var(--wx-shadow-sm);\n}\n\n.wx-locale-picker__current,\n.wx-locale-picker__code {\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 32px;\n height: var(--wx-locale-picker-height, 24px);\n padding: 0 var(--wx-space-6);\n border: none;\n border-radius: var(--wx-radius-xs);\n background: transparent;\n color: var(--wx-text-muted);\n font-family: inherit;\n font-size: var(--wx-font-size-sm);\n font-weight: 600;\n line-height: 1;\n text-transform: uppercase;\n cursor: pointer;\n}\n\n/* The chip: always there, and the one thing a keyboard reaches. */\n.wx-locale-picker__current,\n.wx-locale-picker__code.is-active {\n background: var(--wx-bg-fill);\n color: var(--wx-text-default);\n}\n\n/* The list unrolls under the chip, separated by a hairline so the two do not read as one. */\n.wx-locale-picker__code {\n display: none;\n}\n\n.wx-locale-picker:hover .wx-locale-picker__code,\n.wx-locale-picker:focus-within .wx-locale-picker__code {\n display: flex;\n}\n\n.wx-locale-picker:hover .wx-locale-picker__code:first-of-type,\n.wx-locale-picker:focus-within .wx-locale-picker__code:first-of-type {\n margin-top: 2px;\n border-top: 1px solid var(--wx-border-muted);\n border-radius: 0 0 var(--wx-radius-xs) var(--wx-radius-xs);\n padding-top: 2px;\n}\n\n.wx-locale-picker__code:not(.is-active):hover {\n background: var(--wx-bg-fill);\n color: var(--wx-text-default);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * The button that opens every placeholder a plain field offers.\n *\n * It does not take focus on press: the field keeps its caret, and the list then knows where the\n * choice goes. Pressed from the keyboard it is focused, and the field takes the focus back.\n */\ndefineOptions({ name: 'WxTokenButton' })\n\ndefineProps<{ label: string; disabled?: boolean }>()\n\ndefineEmits<{ click: [] }>()\n</script>\n\n<template>\n <button\n type=\"button\"\n class=\"wx-token-button\"\n :title=\"label\"\n :aria-label=\"label\"\n :disabled=\"disabled\"\n @mousedown.prevent\n @click=\"$emit('click')\"\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M9 4H6v16h3M15 4h3v16h-3\"\n stroke=\"currentColor\"\n stroke-width=\"1.7\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n</template>\n\n<style>\n/* One look for every field that carries it; each field only says where it sits. */\n.wx-token-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 22px;\n height: 22px;\n padding: 0;\n background: transparent;\n border: none;\n border-radius: var(--wx-radius-xs);\n color: var(--wx-text-muted);\n cursor: pointer;\n transition: background-color var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-token-button svg {\n width: 16px;\n height: 16px;\n}\n\n.wx-token-button:hover:not(:disabled) {\n background: var(--wx-bg-fill);\n color: var(--wx-text-default);\n}\n\n.wx-token-button:focus-visible {\n outline: 2px solid var(--wx-border-focus);\n outline-offset: 1px;\n}\n\n.wx-token-button:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n</style>\n","import { computed, ref, shallowRef } from 'vue'\n\n/**\n * One placeholder a text field offers: `[name]` in the text, which whoever prints the text swaps\n * for something else — a phone number kept in settings, the year, a company name.\n *\n * The field never swaps anything itself. It stores the brackets as typed and only helps to type\n * them: a list that opens on `[`, a button with every placeholder there is, and the known ones\n * drawn as chips so they read as one thing rather than as punctuation.\n */\nexport interface TokenOption {\n /** What goes between the brackets: `/^[a-z][a-z0-9_-]{0,63}$/`. */\n name: string\n /** What it stands for right now, shown beside the name as a hint. */\n value?: string\n /** One line about what it is, for a name that does not say. */\n description?: string\n}\n\n/** The props every field that offers placeholders shares. */\nexport interface TokenFieldProps {\n /** Placeholders to suggest on `[` and to draw as chips. Nothing changes without them. */\n tokens?: TokenOption[]\n /** Heading of the list the help button opens. */\n tokensTitle?: string\n /** Accessible name and tooltip of the help button. */\n tokensLabel?: string\n}\n\nexport const TOKEN_NAME = /^[a-z][a-z0-9_-]{0,63}$/\n\n/**\n * A placeholder in the text, the way the site reads it: `[name]`, arguments after a space\n * (`[phone format=intl]`), and `[[name]]` as the brackets themselves. Kept in step with the\n * server's own pattern, so a chip is drawn exactly where the site will put something.\n */\nconst TOKEN =\n /(\\[?)\\[([a-z][a-z0-9_-]{0,63})((?:\\s+[a-z][a-z0-9_-]*=(?:\"[^\"\\]]*\"|'[^'\\]]*'|[^\\s\\]\"']+))*)\\s*\\](\\]?)/g\n\nexport interface TokenSpan {\n from: number\n to: number\n name: string\n}\n\n/** Where the known placeholders of a text are. Unknown names and `[[escaped]]` ones are text. */\nexport function tokenSpans(text: string, known: ReadonlySet<string>): TokenSpan[] {\n if (known.size === 0 || !text.includes('[')) return []\n\n const spans: TokenSpan[] = []\n\n for (const match of text.matchAll(TOKEN)) {\n const [whole, open = '', name = '', , close = ''] = match\n\n if (!known.has(name) || (open !== '' && close !== '')) continue\n\n const from = (match.index ?? 0) + open.length\n spans.push({ from, to: from + whole.length - open.length - close.length, name })\n }\n\n return spans\n}\n\nexport interface TokenSegment {\n text: string\n token: string | null\n}\n\n/** The text cut at its placeholders — what a mirror behind a plain field draws. */\nexport function tokenSegments(text: string, known: ReadonlySet<string>): TokenSegment[] {\n const segments: TokenSegment[] = []\n let at = 0\n\n for (const span of tokenSpans(text, known)) {\n if (span.from > at) segments.push({ text: text.slice(at, span.from), token: null })\n segments.push({ text: text.slice(span.from, span.to), token: span.name })\n at = span.to\n }\n\n if (at < text.length || segments.length === 0)\n segments.push({ text: text.slice(at), token: null })\n\n return segments\n}\n\n/**\n * The placeholder being typed right before the caret: `[` and the start of a name. A `[` after\n * another `[` is the start of an escaped one, and nobody wants a list for that.\n */\nexport function tokenQuery(before: string): { from: number; query: string } | null {\n const match = /(?:^|[^[])\\[([a-z][a-z0-9_-]{0,63})?$/.exec(before)\n\n if (!match) return null\n\n const query = match[1] ?? ''\n\n return { from: before.length - query.length - 1, query }\n}\n\n/** The text a chosen placeholder is written as. */\nexport function tokenText(token: TokenOption): string {\n return `[${token.name}]`\n}\n\n/** Where the list hangs from: a rectangle in the viewport, and the element it scrolls with. */\nexport interface TokenAnchor {\n getBoundingClientRect: () => DOMRect\n contextElement?: Element\n}\n\nexport function tokenAnchor(rect: DOMRect, owner: Element | null): TokenAnchor {\n return { getBoundingClientRect: () => rect, contextElement: owner ?? undefined }\n}\n\n/** A rectangle by hand: `new DOMRect` is not everywhere these fields are rendered. */\nexport function rectOf(x: number, y: number, width: number, height: number): DOMRect {\n return {\n x,\n y,\n width,\n height,\n left: x,\n top: y,\n right: x + width,\n bottom: y + height,\n toJSON: () => ({ x, y, width, height }),\n }\n}\n\n/**\n * Under the field, at the caret's column: the list of a one-line field hangs from the field's\n * bottom edge rather than from the caret, so it never covers the line being typed.\n */\nexport function fieldAnchor(\n owner: HTMLElement | null,\n caret: DOMRect | null,\n): TokenAnchor | undefined {\n if (!owner) return undefined\n\n const box = owner.getBoundingClientRect()\n const x = caret ? caret.left : box.left\n\n return tokenAnchor(rectOf(x, box.top, 0, box.height), owner)\n}\n\n/**\n * The rectangle of one character of an element's text, by its offset — the caret's place in a\n * mirror that draws the same text as the field in the same box. Null where layout is not\n * measured (a test), and the caller falls back to the field.\n */\nexport function textRect(root: HTMLElement, offset: number): DOMRect | null {\n if (typeof document === 'undefined' || typeof document.createRange !== 'function') return null\n\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT)\n let left = offset\n let node = walker.nextNode() as Text | null\n\n while (node) {\n const length = node.data.length\n\n if (left <= length) {\n const range = document.createRange()\n range.setStart(node, left)\n range.setEnd(node, left)\n\n const rect =\n typeof range.getBoundingClientRect === 'function' ? range.getBoundingClientRect() : null\n\n return rect && (rect.height > 0 || rect.width > 0) ? rect : null\n }\n\n left -= length\n node = walker.nextNode() as Text | null\n }\n\n return null\n}\n\nexport interface TokenRange {\n from: number\n to: number\n}\n\n/**\n * The list of placeholders and what the keyboard does to it, for any field — where the text is\n * and how a choice is written back is the field's business.\n *\n * Two ways in: typing (`[ph` before the caret, the list filtered by it, the choice replacing it)\n * and browsing (the help button, every placeholder, the choice going where the caret is).\n */\nexport function useTokenMenu(tokens: () => TokenOption[] | undefined) {\n const open = ref(false)\n const browsing = ref(false)\n const query = ref('')\n const active = ref(0)\n const anchor = shallowRef<TokenAnchor | undefined>(undefined)\n let range: TokenRange = { from: 0, to: 0 }\n\n /* A name the site would not read as a placeholder is not offered as one. */\n const all = computed(() => (tokens() ?? []).filter((token) => TOKEN_NAME.test(token.name)))\n const known = computed<ReadonlySet<string>>(() => new Set(all.value.map((token) => token.name)))\n const items = computed(() =>\n browsing.value ? all.value : all.value.filter((token) => token.name.startsWith(query.value)),\n )\n\n function close(): void {\n open.value = false\n browsing.value = false\n }\n\n /**\n * After a keystroke: opens, narrows or closes the list by what is before the caret. A prefix\n * that matches nothing closes it rather than showing \"nothing\" — `[` is also just a bracket.\n */\n function suggest(before: string, caret: number, at: () => TokenAnchor | undefined): void {\n const found = tokenQuery(before)\n\n if (!found || !all.value.some((token) => token.name.startsWith(found.query))) {\n close()\n return\n }\n\n const wasOpen = open.value && !browsing.value\n\n browsing.value = false\n query.value = found.query\n range = { from: caret - before.length + found.from, to: caret }\n active.value = wasOpen ? Math.min(active.value, items.value.length - 1) : 0\n anchor.value = at()\n open.value = true\n }\n\n /** The help button: everything, inserted over `at` — the caret, or what is selected. */\n function browse(at: TokenRange, where: TokenAnchor | undefined): void {\n browsing.value = true\n query.value = ''\n range = at\n active.value = 0\n anchor.value = where\n open.value = true\n }\n\n function choose(token: TokenOption, insert: (token: TokenOption, at: TokenRange) => void): void {\n const at = range\n close()\n insert(token, at)\n }\n\n /** True when the key was the list's, and the field should not act on it. */\n function keydown(\n event: KeyboardEvent,\n insert: (token: TokenOption, at: TokenRange) => void,\n ): boolean {\n // Keys of an input method belong to it: Enter there picks a word, not a placeholder.\n if (!open.value || event.isComposing) return false\n\n const count = items.value.length\n\n switch (event.key) {\n case 'ArrowDown':\n active.value = count ? (active.value + 1) % count : 0\n break\n case 'ArrowUp':\n active.value = count ? (active.value - 1 + count) % count : 0\n break\n case 'Enter':\n case 'Tab': {\n const token = items.value[active.value]\n if (!token) return false\n choose(token, insert)\n break\n }\n case 'Escape':\n close()\n break\n default:\n return false\n }\n\n event.preventDefault()\n // Escape inside a dialog closes the list, not the dialog.\n event.stopPropagation()\n\n return true\n }\n\n return {\n open,\n browsing,\n items,\n active,\n anchor,\n all,\n known,\n close,\n suggest,\n browse,\n choose,\n keydown,\n }\n}\n\nexport type TokenMenu = ReturnType<typeof useTokenMenu>\n","<script setup lang=\"ts\">\nimport { nextTick, ref, watch } from 'vue'\nimport { PopoverAnchor, PopoverContent, PopoverPortal, PopoverRoot } from 'reka-ui'\nimport { rectOf, type TokenAnchor, type TokenOption } from '../composables/useTokens'\n\n/**\n * The list of placeholders under a field's caret.\n *\n * A Reka popover rather than a box of our own: inside a dialog the page behind is inert, and a\n * click on a list teleported out of the dialog would otherwise count as a click outside it and\n * close the dialog. Focus never moves into the list — the field keeps the caret and the keys, and\n * says which option is active through `aria-activedescendant`.\n */\ndefineOptions({ name: 'WxTokenMenu' })\n\nconst props = defineProps<{\n open: boolean\n items: TokenOption[]\n active: number\n anchor?: TokenAnchor\n /** The id of the list, for the field's `aria-controls`. */\n listId: string\n /** Shown over the list when it was opened by the button rather than by typing. */\n title?: string\n /** The field: a click inside it is the caret moving, not a reason to close. */\n owner?: HTMLElement | null\n}>()\n\nconst emit = defineEmits<{\n choose: [token: TokenOption]\n hover: [index: number]\n close: []\n}>()\n\nfunction onOutside(event: Event): void {\n const target = event.target as Node | null\n if (target && props.owner?.contains(target)) event.preventDefault()\n}\n\n/*\n * One reference for the popover's whole life, reading whichever anchor the field gave last.\n * Handed a new reference in the same render that opens it, Reka positions the list against the\n * one before — the hidden fallback in the page's corner the first time the button is pressed.\n * And a list already open does not follow a new reference on its own, so the content is drawn\n * again (`placement`) whenever the anchor moves: the next line, the next field.\n */\nconst reference: TokenAnchor = {\n getBoundingClientRect: () =>\n props.anchor?.getBoundingClientRect() ??\n props.owner?.getBoundingClientRect() ??\n rectOf(0, 0, 0, 0),\n get contextElement() {\n return props.anchor?.contextElement ?? props.owner ?? undefined\n },\n}\n\nconst placement = ref(0)\nlet placedAt = ''\n\nwatch(\n () => props.anchor,\n (anchor) => {\n const rect = anchor?.getBoundingClientRect()\n const at = rect ? `${rect.left}:${rect.top}:${rect.height}` : ''\n\n if (at !== placedAt) {\n placedAt = at\n placement.value++\n }\n },\n)\n\n/* The active option stays in view while the arrows walk past the edge of a long list. */\nwatch(\n () => [props.active, props.open],\n () =>\n void nextTick(() => {\n const option = document.getElementById(`${props.listId}-${props.active}`)\n option?.scrollIntoView?.({ block: 'nearest' })\n }),\n)\n</script>\n\n<template>\n <popover-root :open=\"open\" @update:open=\"(value: boolean) => !value && emit('close')\">\n <popover-anchor :reference=\"reference\" as-child><span hidden /></popover-anchor>\n <popover-portal>\n <popover-content\n :key=\"placement\"\n class=\"wx-token-menu\"\n side=\"bottom\"\n align=\"start\"\n :side-offset=\"4\"\n :collision-padding=\"8\"\n @open-auto-focus.prevent\n @close-auto-focus.prevent\n @interact-outside=\"onOutside\"\n >\n <div v-if=\"title\" class=\"wx-token-menu__title\">{{ title }}</div>\n <div :id=\"listId\" class=\"wx-token-menu__list\" role=\"listbox\">\n <div\n v-for=\"(item, index) in items\"\n :id=\"`${listId}-${index}`\"\n :key=\"item.name\"\n class=\"wx-token-menu__option\"\n :class=\"{ 'is-active': index === active }\"\n role=\"option\"\n :aria-selected=\"index === active\"\n @mousedown.prevent\n @mouseenter=\"emit('hover', index)\"\n @click=\"emit('choose', item)\"\n >\n <span class=\"wx-token-menu__name\">[{{ item.name }}]</span>\n <span v-if=\"item.value\" class=\"wx-token-menu__value\">{{ item.value }}</span>\n <span v-if=\"item.description\" class=\"wx-token-menu__description\">{{\n item.description\n }}</span>\n </div>\n </div>\n </popover-content>\n </popover-portal>\n </popover-root>\n</template>\n\n<style>\n/* Teleported, so not scoped. */\n.wx-token-menu {\n z-index: var(--wx-z-index-popover);\n box-sizing: border-box;\n min-width: 220px;\n max-width: min(360px, calc(100vw - var(--wx-space-16)));\n padding: var(--wx-space-4);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-sm);\n box-shadow: var(--wx-shadow-popover);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-token-menu__title {\n padding: var(--wx-space-4) var(--wx-space-8) var(--wx-space-6);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n font-weight: var(--wx-font-weight-semibold);\n}\n\n.wx-token-menu__list {\n max-height: 260px;\n overflow-y: auto;\n}\n\n.wx-token-menu__option {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr);\n align-items: baseline;\n gap: 0 var(--wx-space-10);\n padding: var(--wx-space-6) var(--wx-space-8);\n border-radius: var(--wx-radius-xs);\n cursor: pointer;\n user-select: none;\n}\n\n.wx-token-menu__option.is-active {\n background: var(--wx-bg-fill);\n}\n\n.wx-token-menu__name {\n color: var(--wx-text-strong);\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-xs);\n white-space: nowrap;\n}\n\n.wx-token-menu__value {\n overflow: hidden;\n color: var(--wx-text-muted);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wx-token-menu__description {\n grid-column: 1 / -1;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport { useFormField } from '../../composables/useFormField'\nimport { useLocalized } from '../../composables/useLocalized'\nimport LocalePicker from '../Locales/LocalePicker.vue'\nimport WxTokenButton from '../../internal/TokenButton.vue'\nimport WxTokenMenu from '../../internal/TokenMenu.vue'\nimport {\n fieldAnchor,\n textRect,\n tokenSegments,\n tokenText,\n useTokenMenu,\n type TokenOption,\n type TokenRange,\n} from '../../composables/useTokens'\nimport type { InputEmits, InputModelValue, InputProps } from './types'\nimport { useControlAttrs } from '../../composables/useControlAttrs'\n\ndefineOptions({ name: 'WxInput', inheritAttrs: false })\n\n/* `class` and `style` belong to the control; the rest belongs to its input. */\nconst { rootAttrs, controlAttrs } = useControlAttrs()\n\nconst props = withDefaults(defineProps<InputProps>(), {\n type: 'text',\n size: undefined,\n status: undefined,\n id: undefined,\n placeholder: undefined,\n disabled: undefined,\n readonly: false,\n clearable: false,\n maxlength: undefined,\n showCount: false,\n autocomplete: undefined,\n ariaLabel: undefined,\n localized: false,\n tokens: undefined,\n tokensTitle: 'Placeholders',\n tokensLabel: 'Insert a placeholder',\n})\n\nconst emit = defineEmits<InputEmits>()\n\nconst model = defineModel<InputModelValue>({ default: '' })\n\nconst field = useFormField(props)\nconst inputRef = ref<HTMLInputElement | null>(null)\nconst focused = ref(false)\n\nconst locales = useLocalized(props, model)\n\n/** The language on screen, or nothing at all when the field is plain. */\nconst editing = computed(() => (locales.on.value ? locales.active.value : undefined))\n\nconst currentValue = computed(() => locales.read(editing.value))\n\n/**\n * The languages not on screen, carried along as hidden inputs.\n *\n * One visible control and the rest hidden, rather than one styled box per language: the box is\n * this component's root, and a component's root is what a parent's scoped CSS is stamped on and\n * what `class` lands on. They are here at all because a control that is not in the DOM is one a\n * classic form post leaves out, and saving would wipe every language nobody was looking at.\n */\nconst carried = computed(() =>\n locales.on.value\n ? locales.list.value\n .filter((locale) => locale.code !== locales.active.value)\n .map((locale) => ({ code: locale.code, value: locales.read(locale.code) }))\n : [],\n)\n\nconst showClear = computed(\n () =>\n props.clearable && !field.disabled.value && !props.readonly && currentValue.value.length > 0,\n)\n\nconst counter = computed(() =>\n props.showCount && props.maxlength ? `${currentValue.value.length}/${props.maxlength}` : null,\n)\n\nconst classes = computed(() => [\n 'wx-input',\n `wx-input--${field.size.value}`,\n {\n [`wx-input--${field.status.value}`]: field.status.value !== 'default',\n 'is-focused': focused.value,\n 'is-disabled': field.disabled.value,\n 'is-readonly': props.readonly,\n 'is-localized': locales.on.value,\n 'is-tokenized': tokenized.value,\n },\n])\n\nconst rootRef = ref<HTMLElement | null>(null)\nconst mirrorRef = ref<HTMLElement | null>(null)\n\nconst tokens = useTokenMenu(() => props.tokens)\nconst hasTokens = computed(() => tokens.all.value.length > 0)\nconst listId = computed(() => `${field.id.value}-tokens`)\n\n/**\n * The text again, in a layer over the input, with the known placeholders wrapped as chips.\n *\n * The input cannot draw a chip — it holds one string in one colour — so while there is a chip to\n * draw the input's own letters go transparent and the mirror's show instead, at the same places:\n * same font, same box, same horizontal scroll. The input stays the control: caret, selection,\n * input methods and the value are all still its own, and the value is still `[name]`.\n */\nconst segments = computed(() =>\n hasTokens.value ? tokenSegments(String(currentValue.value), tokens.known.value) : [],\n)\nconst tokenized = computed(() => segments.value.some((segment) => segment.token !== null))\n\nfunction syncMirror(): void {\n const input = inputRef.value\n const mirror = mirrorRef.value\n if (!input || !mirror) return\n\n mirror.style.left = `${input.offsetLeft}px`\n mirror.style.top = `${input.offsetTop}px`\n mirror.style.width = `${input.offsetWidth}px`\n mirror.style.height = `${input.offsetHeight}px`\n mirror.scrollLeft = input.scrollLeft\n}\n\n/* The input's width moves with the panel, and the mirror has to move with it. */\nlet resizing: ResizeObserver | null = null\n\nonMounted(() => {\n void nextTick(syncMirror)\n if (typeof ResizeObserver !== 'undefined' && inputRef.value) {\n resizing = new ResizeObserver(() => syncMirror())\n resizing.observe(inputRef.value)\n }\n})\nonBeforeUnmount(() => resizing?.disconnect())\nwatch(segments, () => void nextTick(syncMirror))\n\nfunction caretAnchor(offset: number) {\n return fieldAnchor(rootRef.value, mirrorRef.value ? textRect(mirrorRef.value, offset) : null)\n}\n\n/** After the text or the caret moved: open, narrow or close the list by what is before it. */\nfunction suggestTokens(): void {\n const input = inputRef.value\n if (!hasTokens.value || !input) return\n\n const caret = input.selectionStart ?? input.value.length\n if (caret !== input.selectionEnd) return tokens.close()\n\n const before = input.value.slice(0, caret)\n tokens.suggest(before, caret, () => caretAnchor(before.lastIndexOf('[')))\n}\n\nfunction insertToken(token: TokenOption, at: TokenRange): void {\n const input = inputRef.value\n const value = String(currentValue.value)\n const text = tokenText(token)\n const next = value.slice(0, at.from) + text + value.slice(at.to)\n\n locales.write(editing.value, next)\n emit('input', next)\n\n if (!input) return\n\n // Written straight away rather than on the next render, so the caret lands after the chip.\n input.value = next\n input.focus()\n input.setSelectionRange(at.from + text.length, at.from + text.length)\n void nextTick(syncMirror)\n}\n\n/** The help button: every placeholder, going where the caret is — or at the end, if nowhere. */\nfunction browseTokens(): void {\n const input = inputRef.value\n if (!input) return\n if (tokens.open.value && tokens.browsing.value) return tokens.close()\n\n const length = input.value.length\n const had = document.activeElement === input\n\n input.focus()\n if (!had) input.setSelectionRange(length, length)\n\n const from = had ? (input.selectionStart ?? length) : length\n const to = had ? (input.selectionEnd ?? from) : length\n\n tokens.browse({ from, to }, fieldAnchor(rootRef.value, null))\n}\n\nfunction onKeydown(event: KeyboardEvent): void {\n tokens.keydown(event, insertToken)\n}\n\n/* The caret moved without typing: the list follows it, or goes. Only an open list cares. */\nfunction onCaretMove(event: Event): void {\n syncMirror()\n if (!tokens.open.value) return\n if (\n event instanceof KeyboardEvent &&\n !['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)\n )\n return\n suggestTokens()\n}\n\nfunction onInput(event: Event) {\n const value = (event.target as HTMLInputElement).value\n locales.write(editing.value, value)\n emit('input', value)\n suggestTokens()\n syncMirror()\n}\n\nfunction onChange(event: Event) {\n emit('change', (event.target as HTMLInputElement).value)\n}\n\nfunction onFocus(event: FocusEvent) {\n focused.value = true\n emit('focus', event)\n}\n\nfunction onBlur(event: FocusEvent) {\n focused.value = false\n tokens.close()\n emit('blur', event)\n}\n\nfunction clear() {\n locales.write(editing.value, '')\n emit('input', '')\n emit('change', '')\n emit('clear')\n inputRef.value?.focus()\n}\n\n/**\n * Switching the language is done to type in it, so the caret goes straight into the field\n * that was switched — this one, not every localized field on the screen.\n */\nfunction choose(code: string): void {\n locales.active.value = code\n void nextTick(() => inputRef.value?.focus())\n}\n\ndefineExpose({\n focus: () => inputRef.value?.focus(),\n blur: () => inputRef.value?.blur(),\n select: () => inputRef.value?.select(),\n input: inputRef,\n})\n</script>\n\n<template>\n <div ref=\"rootRef\" :class=\"classes\" v-bind=\"rootAttrs\">\n <span v-if=\"$slots.prefix\" class=\"wx-input__affix wx-input__affix--prefix\">\n <slot name=\"prefix\" />\n </span>\n\n <input\n :id=\"field.id.value\"\n ref=\"inputRef\"\n v-bind=\"controlAttrs\"\n class=\"wx-input__inner\"\n :type=\"type\"\n :name=\"locales.nameFor(controlAttrs.name, editing)\"\n :value=\"currentValue\"\n :placeholder=\"placeholder\"\n :disabled=\"field.disabled.value\"\n :readonly=\"readonly\"\n :maxlength=\"maxlength\"\n :autocomplete=\"autocomplete\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"field.describedBy.value\"\n :aria-invalid=\"field.status.value === 'error' || undefined\"\n :aria-autocomplete=\"hasTokens ? 'list' : undefined\"\n :aria-controls=\"tokens.open.value ? listId : undefined\"\n :aria-activedescendant=\"tokens.open.value ? `${listId}-${tokens.active.value}` : undefined\"\n @input=\"onInput\"\n @change=\"onChange\"\n @focus=\"onFocus\"\n @blur=\"onBlur\"\n @keydown=\"onKeydown\"\n @keyup=\"onCaretMove\"\n @click=\"onCaretMove\"\n @scroll=\"syncMirror\"\n />\n\n <span\n v-if=\"hasTokens\"\n ref=\"mirrorRef\"\n class=\"wx-input__mirror\"\n :class=\"{ 'is-shown': tokenized }\"\n aria-hidden=\"true\"\n ><span class=\"wx-input__mirror-text\"\n ><template v-for=\"(segment, index) in segments\" :key=\"index\"\n ><span v-if=\"segment.token\" class=\"wx-token\">{{ segment.text }}</span\n ><template v-else>{{ segment.text }}</template></template\n ></span\n ></span\n >\n\n <input\n v-for=\"other in carried\"\n :key=\"other.code\"\n type=\"hidden\"\n :name=\"locales.nameFor(controlAttrs.name, other.code)\"\n :value=\"other.value\"\n />\n\n <button\n v-if=\"showClear\"\n class=\"wx-input__clear\"\n type=\"button\"\n tabindex=\"-1\"\n aria-label=\"Clear\"\n @click=\"clear\"\n >\n ✕\n </button>\n\n <wx-token-button\n v-if=\"hasTokens\"\n :label=\"tokensLabel\"\n :disabled=\"field.disabled.value || readonly\"\n @click=\"browseTokens\"\n />\n\n <span v-if=\"counter\" class=\"wx-input__count\">{{ counter }}</span>\n\n <span v-if=\"$slots.suffix\" class=\"wx-input__affix wx-input__affix--suffix\">\n <slot name=\"suffix\" />\n </span>\n\n <wx-token-menu\n v-if=\"hasTokens\"\n :open=\"tokens.open.value\"\n :items=\"tokens.items.value\"\n :active=\"tokens.active.value\"\n :anchor=\"tokens.anchor.value\"\n :list-id=\"listId\"\n :title=\"tokens.browsing.value ? tokensTitle : undefined\"\n :owner=\"rootRef\"\n @choose=\"(token) => tokens.choose(token, insertToken)\"\n @hover=\"(index) => (tokens.active.value = index)\"\n @close=\"tokens.close()\"\n />\n\n <locale-picker\n v-if=\"locales.on.value\"\n :locales=\"locales.list.value\"\n :active=\"locales.active.value\"\n @choose=\"choose\"\n />\n </div>\n</template>\n\n<style scoped>\n.wx-input {\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: var(--wx-space-8);\n box-sizing: border-box;\n width: 100%;\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-control);\n color: var(--wx-text-default);\n transition:\n border-color var(--wx-duration-normal) var(--wx-easing-standard),\n background-color var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-input:hover:not(.is-disabled) {\n border-color: var(--wx-border-strong);\n}\n\n/* The reference marks focus with a tinted border rather than a ring. */\n.wx-input.is-focused {\n border-color: var(--wx-border-focus);\n}\n\n.wx-input--sm {\n height: var(--wx-size-control-sm);\n padding: 0 var(--wx-space-10);\n font-size: var(--wx-font-size-control-sm);\n}\n\n.wx-input--md {\n height: var(--wx-size-control-md);\n padding: 0 var(--wx-space-12);\n font-size: var(--wx-font-size-control-md);\n}\n\n.wx-input--lg {\n height: var(--wx-size-control-lg);\n padding: 0 var(--wx-space-16);\n font-size: var(--wx-font-size-control-lg);\n}\n\n/* Room for the language chip in the corner, so a long title does not run under it. */\n.wx-input.is-localized {\n padding-right: var(--wx-space-40);\n}\n\n.wx-input--error,\n.wx-input--error.is-focused {\n border-color: var(--wx-color-danger);\n}\n\n.wx-input--success,\n.wx-input--success.is-focused {\n border-color: var(--wx-color-success);\n}\n\n.wx-input--warning,\n.wx-input--warning.is-focused {\n border-color: var(--wx-color-warning);\n}\n\n.wx-input.is-disabled {\n background: var(--wx-bg-disabled);\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n.wx-input__inner {\n flex: 1 1 auto;\n min-width: 0;\n height: 100%;\n padding: 0;\n background: transparent;\n border: none;\n outline: none;\n color: inherit;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n.wx-input__inner::placeholder {\n color: var(--wx-text-placeholder);\n}\n\n/*\n * A field the browser filled in is painted by the browser, in a colour that belongs to no\n * theme — a yellow block in a light panel and an olive one in a dark panel. The background is\n * set with !important in the user agent stylesheet and cannot be overridden, so it is covered\n * instead: an inset shadow the size of the field paints over it.\n *\n * The absurd transition is the companion trick for Chrome, which repaints its tint on focus.\n */\n.wx-input__inner:-webkit-autofill,\n.wx-input__inner:-webkit-autofill:hover,\n.wx-input__inner:-webkit-autofill:focus,\n.wx-input__inner:autofill {\n box-shadow: 0 0 0 100vmax var(--wx-bg-surface) inset;\n -webkit-text-fill-color: var(--wx-text-default);\n caret-color: var(--wx-text-default);\n transition: background-color 100000s ease-in-out 0s;\n}\n\n.wx-input__inner:disabled {\n cursor: not-allowed;\n}\n\n/*\n * The mirror is placed over the input by measurement (see `syncMirror`) and always there while\n * the field has placeholders — transparent until it has a chip to draw, because it is also what\n * the caret's column is measured on.\n */\n.wx-input__mirror {\n position: absolute;\n display: flex;\n align-items: center;\n box-sizing: border-box;\n overflow: hidden;\n color: transparent;\n font: inherit;\n letter-spacing: inherit;\n white-space: pre;\n pointer-events: none;\n}\n\n/* One run of inline text, so the chips sit in the line instead of becoming flex items. */\n.wx-input__mirror-text {\n flex: 0 0 auto;\n}\n\n.wx-input__mirror.is-shown {\n color: inherit;\n}\n\n/* Only the letters go: the caret, the selection and the placeholder are still the input's. */\n.wx-input.is-tokenized .wx-input__inner {\n color: transparent;\n caret-color: var(--wx-text-default);\n}\n\n.wx-input__affix,\n.wx-input__count {\n display: inline-flex;\n align-items: center;\n flex: 0 0 auto;\n color: var(--wx-text-muted);\n}\n\n.wx-input__count {\n font-size: var(--wx-font-size-xs);\n font-variant-numeric: tabular-nums;\n}\n\n.wx-input__clear {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 18px;\n height: 18px;\n padding: 0;\n background: transparent;\n border: none;\n border-radius: var(--wx-radius-full);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n line-height: 1;\n cursor: pointer;\n transition: background-color var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-input__clear:hover {\n background: var(--wx-bg-fill);\n color: var(--wx-text-default);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, watch } from 'vue'\nimport { PopoverArrow, PopoverContent, PopoverPortal, PopoverRoot, PopoverTrigger } from 'reka-ui'\nimport WxButton from '../Button/Button.vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport type { PopconfirmEmits, PopconfirmProps } from './types'\n\ndefineOptions({ name: 'WxPopconfirm', inheritAttrs: false })\n\n/*\n * The question asked where the answer will land, rather than in a dialog in the\n * middle of the screen. Deleting one row out of forty is a small decision made in\n * one place, and a modal that blanks the page to ask about it loses the row the\n * reader was looking at. `WxDialog` is for the decisions worth stopping for.\n */\nconst props = withDefaults(defineProps<PopconfirmProps>(), {\n title: undefined,\n description: undefined,\n confirmText: 'Yes',\n cancelText: 'Cancel',\n confirmType: 'primary',\n icon: 'warning',\n side: 'top',\n align: 'center',\n offset: 8,\n arrow: true,\n width: 260,\n disabled: false,\n loading: false,\n})\n\nconst emit = defineEmits<PopconfirmEmits>()\n\ndefineSlots<{\n /** The control that asks. Exactly one element. */\n trigger?: (props: { open: boolean }) => unknown\n /** Replaces the question and its explanation. */\n default?: () => unknown\n /** Replaces the two buttons. */\n actions?: (props: { confirm: () => void; cancel: () => void }) => unknown\n}>()\n\nconst open = defineModel<boolean>('open', { default: false })\n\n/* Whether this closing has already been reported, so it is not reported twice. */\nlet answered = false\n\nfunction confirm() {\n answered = true\n emit('confirm')\n /* An answer that takes time keeps the panel open; the caller closes it when done. */\n if (!props.loading) open.value = false\n}\n\nfunction cancel() {\n answered = true\n emit('cancel')\n open.value = false\n}\n\n/*\n * Dismissed by Escape or by a click outside — which is a cancel, and says so. The\n * buttons above have already spoken for themselves, so the flag keeps this from\n * being a second answer to the same question.\n */\nwatch(open, (value, was) => {\n if (value) {\n answered = false\n return\n }\n\n if (was && !answered && !props.loading) emit('cancel')\n})\n\nconst panelStyle = computed(() => {\n const { width } = props\n const bare = typeof width === 'number' || /^\\d+(\\.\\d+)?$/.test(width)\n return { width: bare ? `${width}px` : width }\n})\n\ndefineExpose({ close: cancel })\n</script>\n\n<template>\n <popover-root v-model:open=\"open\">\n <popover-trigger as-child :disabled=\"disabled\">\n <slot name=\"trigger\" :open=\"open\" />\n </popover-trigger>\n\n <popover-portal>\n <popover-content\n v-bind=\"$attrs\"\n class=\"wx-popconfirm\"\n :side=\"side\"\n :align=\"align\"\n :side-offset=\"offset\"\n :style=\"panelStyle\"\n >\n <div class=\"wx-popconfirm__body\">\n <wx-icon v-if=\"icon\" class=\"wx-popconfirm__icon\" :name=\"icon\" />\n\n <div class=\"wx-popconfirm__text\">\n <slot>\n <p v-if=\"title\" class=\"wx-popconfirm__title\">{{ title }}</p>\n <p v-if=\"description\" class=\"wx-popconfirm__description\">{{ description }}</p>\n </slot>\n </div>\n </div>\n\n <div class=\"wx-popconfirm__actions\">\n <slot name=\"actions\" :confirm=\"confirm\" :cancel=\"cancel\">\n <wx-button size=\"sm\" variant=\"text\" :disabled=\"loading\" @click=\"cancel\">\n {{ cancelText }}\n </wx-button>\n <wx-button size=\"sm\" :type=\"confirmType\" :loading=\"loading\" @click=\"confirm\">\n {{ confirmText }}\n </wx-button>\n </slot>\n </div>\n\n <popover-arrow v-if=\"arrow\" class=\"wx-popconfirm__arrow\" :width=\"12\" :height=\"6\" />\n </popover-content>\n </popover-portal>\n </popover-root>\n</template>\n\n<style>\n/* Teleported, so the styles cannot be scoped to the component. */\n.wx-popconfirm {\n z-index: var(--wx-z-index-popover);\n box-sizing: border-box;\n padding: var(--wx-space-12);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-sm);\n box-shadow: var(--wx-shadow-popover);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n}\n\n.wx-popconfirm__body {\n display: flex;\n align-items: flex-start;\n gap: var(--wx-space-8);\n}\n\n.wx-popconfirm__icon {\n flex: 0 0 auto;\n margin-top: 1px;\n color: var(--wx-color-warning);\n}\n\n.wx-popconfirm__text {\n min-width: 0;\n}\n\n.wx-popconfirm__title {\n margin: 0;\n font-size: var(--wx-font-size-sm);\n font-weight: var(--wx-font-weight-semibold);\n line-height: var(--wx-font-line-height-tight);\n}\n\n.wx-popconfirm__description {\n margin: var(--wx-space-4) 0 0;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n line-height: var(--wx-font-line-height-normal);\n}\n\n.wx-popconfirm__actions {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: var(--wx-space-6);\n margin-top: var(--wx-space-12);\n}\n\n.wx-popconfirm__arrow {\n fill: var(--wx-bg-surface);\n stroke: var(--wx-border-default);\n stroke-width: 1px;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, useSlots, watch } from 'vue'\nimport {\n PopoverArrow,\n PopoverClose,\n PopoverContent,\n PopoverPortal,\n PopoverRoot,\n PopoverTrigger,\n} from 'reka-ui'\nimport WxIcon from '../Icon/Icon.vue'\nimport type { PopoverEmits, PopoverProps } from './types'\n\ndefineOptions({ name: 'WxPopover', inheritAttrs: false })\n\n/*\n * A panel, not a menu. `WxDropdown` is the menu — it closes on any click inside,\n * because picking an item is the whole interaction. Here the click is part of the work\n * being done in the panel, so the panel stays until something closes it: the ×, a\n * button in the footer, Escape, or a click outside.\n */\nconst props = withDefaults(defineProps<PopoverProps>(), {\n side: 'bottom',\n align: 'center',\n offset: 8,\n alignOffset: 0,\n arrow: true,\n title: undefined,\n width: undefined,\n teleport: true,\n modal: false,\n disabled: false,\n closable: false,\n closeLabel: 'Close',\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<PopoverEmits>()\n\ndefineSlots<{\n /** The control the panel hangs off. Exactly one element. */\n trigger?: (props: { open: boolean }) => unknown\n /** The panel. */\n default?: (props: { close: () => void }) => unknown\n /** Replaces `title`. */\n title?: () => unknown\n /** A row under the panel — where the Save and Cancel usually go. */\n footer?: (props: { close: () => void }) => unknown\n}>()\n\nconst open = defineModel<boolean>('open', { default: false })\n\nconst slots = useSlots()\n\nfunction close() {\n open.value = false\n}\n\nwatch(open, (value) => {\n if (value) emit('open')\n else emit('close')\n})\n\nconst hasHeader = computed(() => Boolean(props.title || slots.title || props.closable))\n\nconst panelStyle = computed(() => {\n const { width } = props\n if (width === undefined) return undefined\n\n /*\n * `width=\"280\"` in a template is the string \"280\", which is not a CSS length and\n * would be dropped without a word. A bare number means pixels, however it arrives.\n */\n const bare = typeof width === 'number' || /^\\d+(\\.\\d+)?$/.test(width)\n return { width: bare ? `${width}px` : width }\n})\n\ndefineExpose({ close })\n</script>\n\n<template>\n <popover-root v-model:open=\"open\" :modal=\"modal\">\n <!--\n `as-child`: the trigger is whatever the caller already has — a button, an icon\n button, a tab — and wrapping it in a button of ours would nest one inside another.\n -->\n <popover-trigger as-child :disabled=\"disabled\">\n <slot name=\"trigger\" :open=\"open\" />\n </popover-trigger>\n\n <popover-portal :disabled=\"!teleport\">\n <popover-content\n v-bind=\"$attrs\"\n class=\"wx-popover\"\n :style=\"panelStyle\"\n :side=\"side\"\n :align=\"align\"\n :side-offset=\"offset\"\n :align-offset=\"alignOffset\"\n :aria-label=\"ariaLabel\"\n >\n <header v-if=\"hasHeader\" class=\"wx-popover__header\">\n <div class=\"wx-popover__title\">\n <slot name=\"title\">{{ title }}</slot>\n </div>\n\n <popover-close v-if=\"closable\" class=\"wx-popover__close\" :aria-label=\"closeLabel\">\n <wx-icon name=\"close\" />\n </popover-close>\n </header>\n\n <div class=\"wx-popover__body\">\n <slot :close=\"close\" />\n </div>\n\n <footer v-if=\"$slots.footer\" class=\"wx-popover__footer\">\n <slot name=\"footer\" :close=\"close\" />\n </footer>\n\n <popover-arrow v-if=\"arrow\" class=\"wx-popover__arrow\" :width=\"12\" :height=\"6\" />\n </popover-content>\n </popover-portal>\n </popover-root>\n</template>\n\n<style>\n/* The panel is teleported, so its styles cannot be scoped to the component. */\n.wx-popover {\n /*\n * Every floating panel of ours sits on this one layer — a select opened inside a\n * popover has to cover it, and the panels are added to the document as they open, so\n * the last one opened is the one on top. Separate layers would rank them by kind\n * instead, and a list would disappear behind the panel it was opened from.\n */\n z-index: var(--wx-z-index-popover);\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-10);\n width: max-content;\n min-width: 200px;\n max-width: min(90vw, 360px);\n padding: var(--wx-space-14) var(--wx-space-16);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-sm);\n box-shadow: var(--wx-shadow-popover);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n font-size: var(--wx-font-size-sm);\n line-height: var(--wx-font-line-height-normal);\n}\n\n/* Reka focuses the panel when it opens; the ring belongs on what is inside it. */\n.wx-popover:focus,\n.wx-popover:focus-visible {\n outline: none;\n}\n\n.wx-popover__header {\n display: flex;\n align-items: flex-start;\n gap: var(--wx-space-8);\n}\n\n.wx-popover__title {\n flex: 1 1 auto;\n min-width: 0;\n color: var(--wx-text-strong);\n font-size: var(--wx-font-size-md);\n font-weight: var(--wx-font-weight-semibold);\n line-height: var(--wx-font-line-height-tight);\n}\n\n.wx-popover__close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n /* Pulled into the padding so the × sits in the corner, not inside the text block. */\n margin: -4px -6px 0 0;\n width: 24px;\n height: 24px;\n padding: 0;\n background: none;\n border: none;\n border-radius: var(--wx-radius-full);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-md);\n cursor: pointer;\n}\n\n.wx-popover__close:hover {\n background: var(--wx-bg-fill);\n color: var(--wx-text-default);\n}\n\n.wx-popover__close:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n/*\n * A column rather than a plain block: two fields dropped into a panel with nothing\n * around them would otherwise sit against each other. A `WxForm` inside keeps its own\n * rhythm — one child has nothing to be spaced from.\n */\n.wx-popover__body {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-10);\n min-width: 0;\n}\n\n.wx-popover__footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: var(--wx-space-8);\n}\n\n/*\n * The arrow is an open path — filled it is the triangle, stroked it is only the two\n * slanted edges, which is exactly the panel's border continuing around the point. The\n * pixel of overlap hides the border line that would otherwise run across its base.\n */\n.wx-popover__arrow {\n transform: translateY(-1px);\n fill: var(--wx-bg-surface);\n stroke: var(--wx-border-default);\n stroke-width: 1px;\n}\n</style>\n","import { onBeforeUnmount, onMounted, ref, watch, type Ref } from 'vue'\n\n/**\n * The width of an element, kept up to date — the measurement every layout that\n * answers to its own box rather than to the window is built on.\n *\n * `0` means nothing has been measured yet: on the server, and until the element is\n * mounted. Treat it as \"assume the roomy case\" rather than as zero width, the way\n * `useResponsiveShell` does — the real number arrives before paint.\n *\n * ```ts\n * const el = ref<HTMLElement | null>(null)\n * const width = useElementWidth(el)\n * ```\n *\n * Pass nothing to measure the page itself.\n */\nexport function useElementWidth(target?: Ref<HTMLElement | null | undefined>): Ref<number> {\n const width = ref(0)\n\n let observer: ResizeObserver | null = null\n let observed: HTMLElement | null = null\n\n function element() {\n if (target) return target.value ?? null\n return typeof document === 'undefined' ? null : document.documentElement\n }\n\n function observe() {\n const el = element()\n /* Mounting and the watch on `target` both land here; the same element is measured once. */\n if (el === observed) return\n\n observer?.disconnect()\n observed = el\n if (!el || typeof ResizeObserver === 'undefined') return\n\n /* A first reading, since an observer only reports once something changes. */\n const measured = Math.round(el.getBoundingClientRect().width)\n if (measured > 0) width.value = measured\n\n observer = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (entry) width.value = Math.round(entry.contentRect.width)\n })\n observer.observe(el)\n }\n\n onMounted(observe)\n\n if (target) watch(target, observe)\n\n onBeforeUnmount(() => {\n observer?.disconnect()\n observer = null\n observed = null\n })\n\n return width\n}\n","import { resolveIcon } from '../Icon/icons'\nimport type { IconName } from '../Icon/types'\n\n/**\n * The extension of a file name, lower case and without the dot. A URL is accepted too:\n * the query and the fragment are cut off first, because `photo.jpg?v=2` is a JPEG.\n */\nexport function extensionOf(name: string): string {\n const path = name.split(/[?#]/)[0]\n const base = path.slice(path.lastIndexOf('/') + 1)\n const dot = base.lastIndexOf('.')\n /* A leading dot is a dotfile, not an extension: `.gitignore` has none. */\n return dot > 0 ? base.slice(dot + 1).toLowerCase() : ''\n}\n\n/** Extensions a browser will draw in an `<img>`. */\nconst PICTURES = new Set(['jpg', 'jpeg', 'png', 'gif', 'webp', 'avif', 'bmp', 'svg', 'ico'])\n\n/**\n * Whether the file is a picture, and so has a preview rather than a glyph.\n *\n * The MIME type is asked first because it is the one that knows: an extension is a\n * guess a file name makes about itself. `image/*` minus the formats no browser draws —\n * a TIFF is an image and still renders as a broken picture.\n */\nexport function isPicture(name: string, type?: string): boolean {\n if (type) {\n if (!type.startsWith('image/')) return false\n const subtype = type.slice('image/'.length).split(';')[0].trim().toLowerCase()\n return PICTURES.has(subtype === 'svg+xml' ? 'svg' : subtype)\n }\n return PICTURES.has(extensionOf(name))\n}\n\n/**\n * The icon for a file, by extension.\n *\n * The registry is what answers, not a list kept here, so `registerIcons({ 'file-dwg': … })`\n * in an application is all it takes for a `.dwg` to have its own drawing — no release of\n * this library, and nothing to pass per card.\n */\nexport function fileIconName(name: string): IconName {\n const ext = extensionOf(name)\n if (!ext) return 'file-generic'\n const named = `file-${ext}`\n return resolveIcon(named) ? named : 'file-generic'\n}\n","<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, ref, useTemplateRef, watch } from 'vue'\nimport WxAction from '../Action/Action.vue'\nimport WxActions from '../Actions/Actions.vue'\nimport WxButton from '../Button/Button.vue'\nimport WxDropdownItem from '../DropdownItem/DropdownItem.vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport WxImage from '../Image/Image.vue'\nimport WxInput from '../Input/Input.vue'\nimport WxPopconfirm from '../Popconfirm/Popconfirm.vue'\nimport WxPopover from '../Popover/Popover.vue'\nimport WxTooltip from '../Tooltip/Tooltip.vue'\nimport { useElementWidth } from '../../composables/useElementWidth'\nimport { extensionOf, fileIconName, isPicture } from './files'\nimport type { FileCardEmits, FileCardProps } from './types'\n\ndefineOptions({ name: 'WxFileCard' })\n\n/*\n * One file in a media library: what it looks like, what it is called, and the three or\n * four things that can be done to it.\n *\n * It does none of them. Renaming reports a name, the edit action reports that somebody\n * wants an editor, deleting reports a wish — the file is not touched until whatever\n * holds the cards says so. The one exception is the clipboard, which is not the server:\n * copying a URL is finished the moment it happens.\n */\nconst props = withDefaults(defineProps<FileCardProps>(), {\n url: undefined,\n thumbnail: undefined,\n type: undefined,\n icon: undefined,\n extension: undefined,\n showExtension: false,\n selected: false,\n size: 'md',\n disabled: false,\n renamable: false,\n editable: false,\n viewable: false,\n removable: false,\n confirmRemove: true,\n copyable: false,\n actionsMenu: false,\n renameLabel: 'Rename',\n saveLabel: 'Save',\n cancelLabel: 'Cancel',\n editLabel: 'Edit picture',\n viewLabel: 'View',\n removeLabel: 'Delete',\n removeConfirmText: undefined,\n copyLabel: 'Copy link',\n downloadUrl: undefined,\n downloadLabel: 'Download',\n copiedLabel: 'Copied',\n moreLabel: 'More',\n actionsLabel: undefined,\n})\n\nconst emit = defineEmits<FileCardEmits>()\n\ndefineSlots<{\n /** The whole preview box — a video still, a player, whatever the file really needs. */\n preview?: (props: { picture: boolean }) => unknown\n /** Actions of your own, after the ones the card offers. */\n actions?: () => unknown\n /** Under the name: a size, a date, dimensions. */\n meta?: () => unknown\n}>()\n\nconst picture = computed(() => isPicture(props.name, props.type))\nconst source = computed(() => props.thumbnail ?? props.url)\nconst extension = computed(() => props.extension?.toLowerCase() || extensionOf(props.name))\nconst glyph = computed(\n () => props.icon ?? fileIconName(props.extension ? `file.${extension.value}` : props.name),\n)\n\n/* ------------------------------------------------------------------ renaming --- */\n\nconst renaming = ref(false)\nconst draft = ref('')\nconst field = useTemplateRef<{ select: () => void; input: HTMLInputElement | null }>('field')\n\n/**\n * A panel is opened on the next turn of the loop rather than inside the handler that\n * asked for it.\n *\n * The item that asks is often inside another panel — the folded-up menu — and the layer\n * the new panel puts up is created part-way through that very click. It then sees the\n * rest of the same click finish somewhere that is not inside it, reads that as a click\n * on the page behind, and dismisses itself before anyone has seen it. Opening after the\n * click is over is what separates the two.\n */\nfunction openLater(open: () => void) {\n openTimers.push(setTimeout(open))\n}\n\nconst openTimers: ReturnType<typeof setTimeout>[] = []\n\nfunction startRename() {\n if (props.disabled || !props.renamable) return\n draft.value = props.name\n openLater(() => {\n renaming.value = true\n })\n}\n\n/* Cleared on the way out, so a card unmounted mid-rename leaves nothing running. */\nconst selectTimers: ReturnType<typeof setTimeout>[] = []\n\nfunction stopSelecting() {\n for (const timer of selectTimers.splice(0)) clearTimeout(timer)\n}\n\n/**\n * The name, focused and selected whole — extension and all, because a rename is usually a\n * new name, and the reader who only wanted to fix a typo has lost nothing by pressing End\n * first.\n *\n * Hung off the field appearing rather than off the panel opening, because the two are not\n * the same moment: opened from the folded-up menu, the panel waits for that menu to\n * finish closing and the field arrives several ticks after the open.\n */\nwatch(\n () => field.value?.input,\n (el) => {\n if (!el || !renaming.value) return\n\n const take = () => {\n if (!renaming.value || !el.isConnected) return\n if (document.activeElement !== el) el.focus()\n el.select()\n }\n\n take()\n\n /*\n * And again twice. That same menu hands focus back to its own trigger on the way out,\n * which takes it straight out of the field the panel has just put it in. Opened from\n * the row or from a double click there is nothing to fight, and the first call is the\n * only one that does anything.\n */\n selectTimers.push(setTimeout(take, 0), setTimeout(take, 120))\n },\n)\n\nfunction commitRename() {\n if (!renaming.value) return\n const next = draft.value.trim()\n renaming.value = false\n if (next && next !== props.name) emit('rename', next)\n}\n\n/*\n * Every way out of the panel that is not Save: Escape, a click on the page behind it,\n * Cancel. A panel dismissed is a panel dismissed — it does not quietly save on the way\n * out, the way an input in place had to.\n */\nfunction cancelRename() {\n stopSelecting()\n draft.value = props.name\n renaming.value = false\n}\n\n/* ------------------------------------------------------------------ deleting --- */\n\nconst confirming = ref(false)\n\n/** The question, with the file in it, since a grid of thumbnails looks much alike. */\nconst removeQuestion = computed(() => props.removeConfirmText ?? `Delete ${props.name}?`)\n\nfunction askRemove() {\n if (!props.confirmRemove) {\n emit('remove')\n return\n }\n openLater(() => {\n confirming.value = true\n })\n}\n\nfunction confirmRemoval() {\n confirming.value = false\n emit('remove')\n}\n\n/* ----------------------------------------------------------------- clipboard --- */\n\nconst copied = ref(false)\nlet copiedTimer: ReturnType<typeof setTimeout> | undefined\n\nasync function copy() {\n const url = props.url\n if (!url) return\n\n /*\n * Asked for rather than assumed. The clipboard is missing outside a secure context,\n * and `await undefined` would have the card report a copy that never happened.\n *\n * When it is there and still refuses — an iframe that was not granted it, a browser that\n * wants a gesture it did not see — the old way is tried before giving up. The card is what\n * tells the person it worked, so the fallback has to live here rather than in whatever\n * placed the card: a green tick that only appears for half the browsers is worse than none.\n */\n try {\n if (navigator.clipboard?.writeText) {\n await navigator.clipboard.writeText(url)\n } else if (!copyByHand(url)) {\n throw new Error('The clipboard is not available here')\n }\n\n confirmCopied(url)\n } catch (error) {\n if (copyByHand(url)) {\n confirmCopied(url)\n\n return\n }\n\n emit('copy-error', error)\n }\n}\n\nfunction confirmCopied(url: string) {\n copied.value = true\n clearTimeout(copiedTimer)\n copiedTimer = setTimeout(() => {\n copied.value = false\n }, 1600)\n emit('copy', url)\n}\n\n/** `document.execCommand`, which is deprecated everywhere and still works everywhere. */\nfunction copyByHand(url: string): boolean {\n const area = document.createElement('textarea')\n area.value = url\n area.setAttribute('readonly', '')\n area.style.position = 'fixed'\n area.style.opacity = '0'\n document.body.appendChild(area)\n area.select()\n\n let done = false\n\n try {\n done = document.execCommand('copy')\n } catch {\n done = false\n }\n\n area.remove()\n\n return done\n}\n\nonBeforeUnmount(() => {\n clearTimeout(copiedTimer)\n stopSelecting()\n for (const timer of openTimers.splice(0)) clearTimeout(timer)\n})\n\n/* ---------------------------------------------------------------------- name --- */\n\nconst label = useTemplateRef<HTMLElement>('label')\nconst labelWidth = useElementWidth(label)\n\n/*\n * A tip repeating a name that is fully visible is noise, so the tip is only armed when\n * the name is actually cut off. The width is watched because the answer changes with\n * the column, not only with the name.\n */\nconst truncated = ref(false)\n\nwatch(\n [labelWidth, () => props.name],\n async () => {\n await nextTick()\n const el = label.value\n truncated.value = Boolean(el) && el!.scrollWidth > el!.clientWidth + 1\n },\n { immediate: true },\n)\n\n/* -------------------------------------------------------------------- render --- */\n\nconst shows = computed(() => ({\n view: props.viewable && picture.value && !props.disabled,\n rename: props.renamable && !props.disabled,\n /* Nothing to open for a `.zip`: the editor this asks for is an image editor. */\n edit: props.editable && picture.value && !props.disabled,\n copy: props.copyable && Boolean(props.url) && !props.disabled,\n download: Boolean(props.downloadUrl) && !props.disabled,\n remove: props.removable && !props.disabled,\n}))\n\nconst hasActions = computed(() => Object.values(shows.value).some(Boolean))\n\n/*\n * The folded-up menu's panel is teleported, so the pointer that opened it is no longer\n * over the card — and a row that waits for a hover would fade out from under the menu\n * hanging off it. `WxActions` reports the state for exactly this.\n */\nconst menuOpen = ref(false)\n\nconst classes = computed(() => [\n 'wx-file-card',\n `wx-file-card--${props.size}`,\n {\n 'is-selected': props.selected,\n 'is-disabled': props.disabled,\n /* Every reason the buttons have to stay put while nothing is hovering them. */\n 'is-busy': renaming.value || confirming.value || menuOpen.value,\n },\n])\n</script>\n\n<template>\n <div :class=\"classes\">\n <div class=\"wx-file-card__preview\">\n <slot name=\"preview\" :picture=\"picture\">\n <wx-image\n v-if=\"picture && source\"\n class=\"wx-file-card__picture\"\n :src=\"source\"\n :alt=\"name\"\n fit=\"cover\"\n >\n <!--\n A picture that will not load is a file like any other, and is drawn as one —\n the same glyph and the same extension, rather than a broken-picture mark that\n says only that something went wrong.\n -->\n <template #error>\n <span class=\"wx-file-card__file\">\n <wx-icon :name=\"glyph\" class=\"wx-file-card__glyph\" />\n <span v-if=\"extension\" class=\"wx-file-card__extension\">{{ extension }}</span>\n </span>\n </template>\n </wx-image>\n\n <span v-else class=\"wx-file-card__file\">\n <wx-icon :name=\"glyph\" class=\"wx-file-card__glyph\" />\n <span v-if=\"extension\" class=\"wx-file-card__extension\">{{ extension }}</span>\n </span>\n </slot>\n\n <!-- Under a glyph the extension is already written out; over a picture it is a badge. -->\n <span\n v-if=\"showExtension && extension && picture && source\"\n class=\"wx-file-card__badge\"\n aria-hidden=\"true\"\n >{{ extension }}</span\n >\n\n <!--\n Over the preview, and on a pointer that can hover they stay out of the way until\n it does. There is no hovering on a touch screen, so there they simply stand.\n -->\n <span v-if=\"hasActions || $slots.actions\" class=\"wx-file-card__tools\">\n <!--\n What the rename panel hangs from: an empty box over the buttons, rather than\n the rename button itself, because that button is not always there — folded up,\n the row is a single \"more\" and the panel still has to drop from what was\n pressed. It is empty and not a wrapper because a trigger that contained the\n buttons opened the panel whenever one of them was clicked, `disabled` or not:\n the click reaches the trigger on its way up.\n -->\n <wx-popover\n v-model:open=\"renaming\"\n side=\"bottom\"\n align=\"end\"\n :width=\"240\"\n :arrow=\"false\"\n disabled\n :aria-label=\"renameLabel\"\n @close=\"cancelRename\"\n >\n <template #trigger>\n <span class=\"wx-file-card__anchor\" aria-hidden=\"true\" />\n </template>\n\n <wx-input\n ref=\"field\"\n v-model=\"draft\"\n class=\"wx-file-card__field\"\n size=\"sm\"\n :aria-label=\"renameLabel\"\n @keydown.enter.prevent=\"commitRename\"\n />\n\n <template #footer>\n <wx-button size=\"sm\" variant=\"text\" @click=\"renaming = false\">{{\n cancelLabel\n }}</wx-button>\n <wx-button size=\"sm\" type=\"primary\" @click=\"commitRename\">{{ saveLabel }}</wx-button>\n </template>\n </wx-popover>\n\n <!--\n The question before a deletion, on an anchor of its own for the same reason the\n rename panel has one: it is asked from the row and from the folded-up menu, and\n the menu item is gone by the time the answer is wanted.\n -->\n <wx-popconfirm\n v-if=\"shows.remove && confirmRemove\"\n v-model:open=\"confirming\"\n side=\"bottom\"\n align=\"end\"\n :title=\"removeQuestion\"\n :confirm-text=\"removeLabel\"\n :cancel-text=\"cancelLabel\"\n confirm-type=\"danger\"\n :arrow=\"false\"\n disabled\n @confirm=\"confirmRemoval\"\n >\n <template #trigger>\n <span class=\"wx-file-card__anchor\" aria-hidden=\"true\" />\n </template>\n </wx-popconfirm>\n\n <wx-actions\n v-model:menu-open=\"menuOpen\"\n class=\"wx-file-card__actions\"\n size=\"sm\"\n align=\"end\"\n :collapse=\"actionsMenu ? 'always' : true\"\n :aria-label=\"actionsLabel ?? `Actions for ${name}`\"\n :more-label=\"moreLabel\"\n >\n <wx-action v-if=\"shows.view\" type=\"view\" :title=\"viewLabel\" @click=\"emit('view')\" />\n <wx-action\n v-if=\"shows.edit\"\n type=\"edit\"\n icon=\"crop\"\n :title=\"editLabel\"\n @click=\"emit('edit')\"\n />\n <wx-action v-if=\"shows.rename\" type=\"edit\" :title=\"renameLabel\" @click=\"startRename\" />\n <wx-action\n v-if=\"shows.copy\"\n type=\"link\"\n :icon=\"copied ? 'check' : 'link'\"\n :tone=\"copied ? 'success' : undefined\"\n :title=\"copied ? copiedLabel : copyLabel\"\n @click=\"copy\"\n />\n <wx-action\n v-if=\"shows.download\"\n type=\"download\"\n :href=\"downloadUrl\"\n download\n :title=\"downloadLabel\"\n />\n <wx-action v-if=\"shows.remove\" type=\"remove\" :title=\"removeLabel\" @click=\"askRemove\" />\n <slot name=\"actions\" />\n\n <!--\n Folded up, the same actions need their names: a menu of four unlabelled icons\n is worse than the row it replaced. Left alone, `WxActions` puts the row itself\n in the panel, which is exactly those four icons.\n -->\n <template #collapsed>\n <wx-dropdown-item v-if=\"shows.view\" icon=\"eye\" @click=\"emit('view')\">\n {{ viewLabel }}\n </wx-dropdown-item>\n <wx-dropdown-item v-if=\"shows.edit\" icon=\"crop\" @click=\"emit('edit')\">\n {{ editLabel }}\n </wx-dropdown-item>\n <wx-dropdown-item v-if=\"shows.rename\" icon=\"edit\" @click=\"startRename\">\n {{ renameLabel }}\n </wx-dropdown-item>\n <wx-dropdown-item v-if=\"shows.copy\" icon=\"link\" @click=\"copy\">\n {{ copied ? copiedLabel : copyLabel }}\n </wx-dropdown-item>\n <wx-dropdown-item v-if=\"shows.download\" icon=\"download\" :href=\"downloadUrl\" download>\n {{ downloadLabel }}\n </wx-dropdown-item>\n <wx-dropdown-item v-if=\"shows.remove\" icon=\"trash\" tone=\"danger\" @click=\"askRemove\">\n {{ removeLabel }}\n </wx-dropdown-item>\n <slot name=\"actions\" />\n </template>\n </wx-actions>\n </span>\n </div>\n\n <div class=\"wx-file-card__body\">\n <wx-tooltip :content=\"name\" :disabled=\"!truncated || renaming\">\n <span ref=\"label\" class=\"wx-file-card__name\" @dblclick=\"startRename\">{{ name }}</span>\n </wx-tooltip>\n\n <span v-if=\"$slots.meta\" class=\"wx-file-card__meta\"><slot name=\"meta\" /></span>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-file-card {\n --wx-file-card-glyph: 32px;\n\n position: relative;\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-6);\n box-sizing: border-box;\n min-width: 0;\n padding: var(--wx-space-6);\n border: 1px solid transparent;\n border-radius: var(--wx-radius-md);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n font-size: var(--wx-font-size-sm);\n transition:\n background var(--wx-duration-fast) var(--wx-easing-standard),\n border-color var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-file-card--sm {\n --wx-file-card-glyph: 24px;\n\n font-size: var(--wx-font-size-xs);\n}\n\n.wx-file-card--lg {\n --wx-file-card-glyph: 44px;\n}\n\n.wx-file-card.is-selected {\n background: var(--wx-color-primary-soft);\n border-color: color-mix(in srgb, var(--wx-color-primary) 40%, transparent);\n}\n\n.wx-file-card.is-disabled {\n opacity: 0.55;\n}\n\n.wx-file-card__preview {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n aspect-ratio: 4 / 3;\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-muted);\n border-radius: var(--wx-radius-sm);\n}\n\n.wx-file-card__picture {\n width: 100%;\n height: 100%;\n}\n\n.wx-file-card__file {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--wx-space-4);\n min-width: 0;\n padding: var(--wx-space-4);\n}\n\n.wx-file-card__glyph {\n width: var(--wx-file-card-glyph);\n height: var(--wx-file-card-glyph);\n color: var(--wx-text-placeholder);\n}\n\n/*\n * The extension in words. The glyphs go by family — a `.docx` and an `.odt` share one —\n * and this is the line that tells them apart, and that says anything at all about the\n * `.sketch` nobody has drawn an icon for.\n */\n.wx-file-card__extension {\n max-width: 100%;\n overflow: hidden;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n font-weight: var(--wx-font-weight-semibold);\n letter-spacing: 0.04em;\n text-overflow: ellipsis;\n text-transform: uppercase;\n white-space: nowrap;\n}\n\n/*\n * The same word over a picture, where it has to be readable on any of them: a near-opaque\n * surface with a border of its own, the pill the actions sit in. Bottom left, out of their way.\n */\n.wx-file-card__badge {\n position: absolute;\n bottom: var(--wx-space-4);\n left: var(--wx-space-4);\n padding: 0 var(--wx-space-4);\n background: color-mix(in srgb, var(--wx-bg-surface) 88%, transparent);\n border: 1px solid var(--wx-border-muted);\n border-radius: var(--wx-radius-xs);\n color: var(--wx-text-default);\n font-size: var(--wx-font-size-xs);\n font-weight: var(--wx-font-weight-semibold);\n letter-spacing: 0.04em;\n line-height: 1.5;\n text-transform: uppercase;\n pointer-events: none;\n}\n\n/*\n * The wrapper carries the place and the width; the row inside carries the look. They are\n * two elements because `WxActions` measures itself against its parent, so the parent has\n * to be the thing with a width — and because the rename panel hangs from the wrapper,\n * which stays put whether the row is four buttons or the one it folds into.\n *\n * `collapse` folds those four as soon as they stop fitting, which on a card a hundred\n * pixels wide is at once. The cap is for the frame before the first measurement, so the\n * row is never seen hanging out of the card it belongs to.\n */\n/*\n * Both edges, so the width is the preview's and not the row's. Left to shrink around its\n * contents it would be the width of whatever it currently holds — and once the row had\n * folded into a single button, that is the width the row would be measured against next\n * time, so it could never come back out.\n */\n.wx-file-card__tools {\n position: absolute;\n top: var(--wx-space-4);\n right: var(--wx-space-4);\n left: var(--wx-space-4);\n display: block;\n /* The row inside sits at the end of it; the span itself is only a measuring stick. */\n pointer-events: none;\n}\n\n.wx-file-card__tools > * {\n pointer-events: auto;\n}\n\n/* The box the panel is placed against: exactly the buttons, and nothing to click. */\n.wx-file-card__anchor {\n position: absolute;\n inset: 0;\n display: block;\n pointer-events: none;\n}\n\n/*\n * Shrunk to its buttons and pushed to the end of the measuring stick above, so the\n * background is a pill around them rather than a bar across the picture.\n */\n.wx-file-card__actions {\n width: fit-content;\n margin-inline-start: auto;\n padding: 2px;\n background: color-mix(in srgb, var(--wx-bg-surface) 88%, transparent);\n border: 1px solid var(--wx-border-muted);\n border-radius: var(--wx-radius-sm);\n backdrop-filter: blur(2px);\n}\n\n/*\n * Out of the way until the pointer arrives — but only where there is a pointer that can\n * arrive. A touch screen never hovers, and actions that wait for a hover that cannot\n * happen are actions nobody can reach.\n */\n@media (hover: hover) {\n .wx-file-card__tools {\n opacity: 0;\n transition: opacity var(--wx-duration-fast) var(--wx-easing-standard);\n }\n\n /*\n * `is-busy` among them because every panel the buttons open is teleported: the menu,\n * the rename field, the question before a deletion. The pointer and the focus are both\n * outside the card while one of them is up, so neither `:hover` nor `:focus-within`\n * holds — and the buttons would fade out from under the panel hanging off them.\n */\n .wx-file-card:hover .wx-file-card__tools,\n .wx-file-card:focus-within .wx-file-card__tools,\n .wx-file-card.is-busy .wx-file-card__tools {\n opacity: 1;\n }\n}\n\n.wx-file-card__body {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.wx-file-card__name {\n display: block;\n min-width: 0;\n overflow: hidden;\n color: var(--wx-text-default);\n line-height: var(--wx-font-line-height-normal);\n text-align: center;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wx-file-card__meta {\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n text-align: center;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-file-card,\n .wx-file-card__tools {\n transition: none;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { FooterProps } from './types'\n\ndefineOptions({ name: 'WxFooter' })\n\nconst props = withDefaults(defineProps<FooterProps>(), {\n height: undefined,\n bordered: true,\n padding: 'md',\n})\n\nconst height = computed(() => {\n if (props.height === undefined) return undefined\n return typeof props.height === 'number' ? `${props.height}px` : props.height\n})\n\nconst classes = computed(() => [\n 'wx-footer',\n `wx-footer--padding-${props.padding}`,\n { 'wx-footer--bordered': props.bordered },\n])\n</script>\n\n<template>\n <footer :class=\"classes\" :style=\"height ? { '--wx-footer-height': height } : undefined\">\n <slot />\n <!-- The far end of the bar: the copyright, a version, a link to the status page. -->\n <div v-if=\"$slots.end\" class=\"wx-footer__end\">\n <slot name=\"end\" />\n </div>\n </footer>\n</template>\n\n<style scoped>\n.wx-footer {\n display: flex;\n align-items: center;\n gap: var(--wx-space-12);\n box-sizing: border-box;\n flex: 0 0 auto;\n /* No fixed height by default: a footer of links grows with what it holds. */\n min-height: var(--wx-footer-height, 48px);\n padding-block: var(--wx-space-8);\n padding-inline: var(--wx-footer-padding, var(--wx-space-16));\n background: var(--wx-bg-surface);\n color: var(--wx-text-muted);\n font-family: var(--wx-font-family-sans);\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-footer__end {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n /* Everything before it keeps its place; this group takes the far end. */\n margin-inline-start: auto;\n min-width: 0;\n}\n\n.wx-footer--padding-none {\n --wx-footer-padding: 0px;\n}\n\n.wx-footer--padding-sm {\n --wx-footer-padding: var(--wx-space-6);\n}\n\n/* The same gutter as the header, so the two bars stay a pair. */\n.wx-footer--padding-md {\n --wx-footer-padding: var(--wx-space-10);\n}\n\n.wx-footer--padding-lg {\n --wx-footer-padding: var(--wx-space-16);\n}\n\n.wx-footer--bordered {\n border-top: 1px solid var(--wx-border-default);\n}\n\n/* The same give as the header on a small screen. */\n@media (max-width: 640px) {\n .wx-footer--padding-lg {\n --wx-footer-padding: var(--wx-space-10);\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, provide, toRef } from 'vue'\nimport { formContextKey, type ValidationErrors } from '../../composables/useFormField'\nimport type { FormEmits, FormProps } from './types'\n\ndefineOptions({ name: 'WxForm' })\n\nconst props = withDefaults(defineProps<FormProps>(), {\n errors: undefined,\n disabled: false,\n size: 'md',\n labelPosition: 'top',\n labelWidth: undefined,\n gap: 'md',\n})\n\nconst emit = defineEmits<FormEmits>()\n\nconst errors = computed<ValidationErrors>(() => props.errors ?? {})\n\nprovide(formContextKey, {\n errors,\n disabled: toRef(props, 'disabled'),\n size: toRef(props, 'size'),\n labelPosition: toRef(props, 'labelPosition'),\n labelWidth: toRef(props, 'labelWidth'),\n})\n\n/** Native submit is always prevented: forms here talk to a data adapter, not a URL. */\nfunction onSubmit(event: SubmitEvent) {\n event.preventDefault()\n emit('submit', event)\n}\n\nfunction onReset(event: Event) {\n emit('reset', event)\n}\n</script>\n\n<template>\n <form\n :class=\"['wx-form', `wx-form--gap-${gap}`, `wx-form--label-${labelPosition}`]\"\n novalidate\n @submit=\"onSubmit\"\n @reset=\"onReset\"\n >\n <slot />\n </form>\n</template>\n\n<style scoped>\n.wx-form {\n display: flex;\n flex-direction: column;\n}\n\n.wx-form--gap-sm {\n gap: var(--wx-space-8);\n}\n\n/*\n * The default is the panel's step (§6 of the visual spec), the same number a card puts\n * between the things inside it — so a form laid out by a card and a form laid out by itself\n * have the same rhythm. The step inside a field, label to control, is smaller on purpose and\n * lives in `WxFormItem`.\n */\n.wx-form--gap-md {\n gap: var(--wx-gap, var(--wx-space-16));\n}\n\n.wx-form--gap-lg {\n gap: var(--wx-space-32);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, inject, ref } from 'vue'\nimport {\n formContextKey,\n provideFormItem,\n useId,\n type ControlSize,\n type ControlStatus,\n} from '../../composables/useFormField'\nimport type { FormItemProps } from './types'\n\ndefineOptions({ name: 'WxFormItem' })\n\nconst props = withDefaults(defineProps<FormItemProps>(), {\n label: undefined,\n name: undefined,\n required: false,\n error: undefined,\n help: undefined,\n disabled: false,\n size: undefined,\n labelWidth: undefined,\n reserveErrorSpace: false,\n wide: false,\n})\n\nconst form = inject(formContextKey, null)\n\nconst baseId = useId('wx-field')\nconst errorId = `${baseId}-error`\nconst helpId = `${baseId}-help`\n\n/**\n * Grouped controls (checkbox and radio groups) cannot be targeted by `for`,\n * so they register themselves and the label becomes a plain span instead.\n */\nconst labelMode = ref<'control' | 'group'>('control')\nconst controlId = ref<string>(baseId)\n\nfunction registerLabelTarget(id: string | undefined) {\n if (id === undefined) {\n labelMode.value = 'group'\n return\n }\n labelMode.value = 'control'\n controlId.value = id\n}\n\nconst messages = computed<string[]>(() => {\n if (props.error !== undefined) {\n return Array.isArray(props.error) ? props.error : [props.error]\n }\n if (props.name && form) return form.errors.value[props.name] ?? []\n return []\n})\n\nconst hasError = computed(() => messages.value.length > 0)\nconst status = computed<ControlStatus>(() => (hasError.value ? 'error' : 'default'))\n\n/**\n * Only ever names nodes that are actually rendered — the help text gives way to the\n * error, and a dangling `aria-describedby` is worse than none.\n */\nconst describedBy = computed(() => {\n if (hasError.value) return errorId\n return props.help ? helpId : undefined\n})\n\nconst size = computed<ControlSize | undefined>(() => props.size)\nconst disabled = computed(() => props.disabled)\n\nconst labelWidth = computed(() => props.labelWidth ?? form?.labelWidth.value)\nconst isInline = computed(() => form?.labelPosition.value === 'left')\n\nprovideFormItem({\n id: computed(() => baseId),\n describedBy,\n status,\n disabled,\n size,\n registerLabelTarget,\n})\n\ndefineExpose({ messages, hasError })\n</script>\n\n<template>\n <div\n :class=\"[\n 'wx-form-item',\n {\n 'wx-form-item--inline': isInline,\n 'wx-form-item--wide': wide,\n 'is-error': hasError,\n 'is-required': required,\n },\n ]\"\n :style=\"isInline && labelWidth ? { '--wx-form-item-label-width': labelWidth } : undefined\"\n >\n <component\n :is=\"labelMode === 'group' ? 'span' : 'label'\"\n v-if=\"label || $slots.label\"\n :id=\"`${baseId}-label`\"\n class=\"wx-form-item__label\"\n :for=\"labelMode === 'group' ? undefined : controlId\"\n >\n <slot name=\"label\">{{ label }}</slot>\n <span v-if=\"required\" class=\"wx-form-item__required\" aria-hidden=\"true\">*</span>\n </component>\n\n <div class=\"wx-form-item__control\">\n <slot />\n\n <p v-if=\"hasError\" :id=\"errorId\" class=\"wx-form-item__error\" role=\"alert\">\n {{ messages[0] }}\n </p>\n <p v-else-if=\"help\" :id=\"helpId\" class=\"wx-form-item__help\">{{ help }}</p>\n <p v-else-if=\"reserveErrorSpace\" class=\"wx-form-item__error\" aria-hidden=\"true\"> </p>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-form-item {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-6);\n min-width: 0;\n}\n\n.wx-form-item--inline {\n flex-direction: row;\n align-items: flex-start;\n gap: var(--wx-space-16);\n}\n\n.wx-form-item--inline .wx-form-item__label {\n flex: 0 0 auto;\n width: var(--wx-form-item-label-width, 160px);\n /* Line the label up with the first line of a control's text. */\n padding-top: calc((var(--wx-size-control-md) - 1lh) / 2);\n}\n\n.wx-form-item--inline .wx-form-item__control {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.wx-form-item__label {\n color: var(--wx-text-default);\n font-size: var(--wx-font-size-sm);\n font-weight: var(--wx-font-weight-medium);\n line-height: var(--wx-font-line-height-normal);\n}\n\n.wx-form-item__required {\n margin-left: var(--wx-space-2);\n color: var(--wx-color-danger);\n}\n\n/*\n * A field stops at a width it can be read at.\n *\n * A panel is as wide as the monitor it is opened on, and an input that follows it is a line\n * 1700px long whose label is a screen away from its end — on the same screen as a second\n * field of the same width, so nothing on it has a shape. The cap is on the control rather\n * than on the form, because the label, the hint and the error under it are text and wrap on\n * their own, and because a card that shrank with its fields would leave the screen looking\n * like a column of narrow boxes rather than a page.\n *\n * `--wx-field-max-width` so a screen can widen the fields it knows are not fields — and\n * `wide` for the single one.\n */\n.wx-form-item__control {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n min-width: 0;\n max-width: var(--wx-field-max-width, 640px);\n}\n\n/* Its own control, not every control inside it: a field that says it is wide because it holds\n an editor or a card of its own must not widen the ordinary fields that card is made of. */\n.wx-form-item--wide > .wx-form-item__control {\n max-width: none;\n}\n\n/*\n * A note about the field, not a paragraph of its own: one step below the label, so the eye can\n * tell where one field ends and the next begins. The error rides the same size because it takes\n * the help text's place — at 14 the line would jump on the first failed save.\n */\n.wx-form-item__error,\n.wx-form-item__help {\n margin: 0;\n font-size: var(--wx-font-size-xs);\n line-height: var(--wx-font-line-height-normal);\n}\n\n.wx-form-item__error {\n color: var(--wx-color-danger);\n}\n\n.wx-form-item__help {\n color: var(--wx-text-muted);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { HeaderProps } from './types'\n\ndefineOptions({ name: 'WxHeader' })\n\nconst props = withDefaults(defineProps<HeaderProps>(), {\n height: undefined,\n bordered: true,\n sticky: false,\n floating: false,\n padding: 'md',\n})\n\nconst height = computed(() => {\n if (props.height === undefined) return undefined\n return typeof props.height === 'number' ? `${props.height}px` : props.height\n})\n\nconst classes = computed(() => [\n 'wx-header',\n `wx-header--padding-${props.padding}`,\n {\n 'wx-header--bordered': props.bordered,\n 'wx-header--sticky': props.sticky,\n 'wx-header--floating': props.floating,\n },\n])\n</script>\n\n<template>\n <header :class=\"classes\" :style=\"height ? { '--wx-header-height': height } : undefined\">\n <slot />\n <!--\n The far end of the bar, where the user menu and the notifications live. It is a\n group of its own rather than a `margin-inline-start: auto` every admin panel\n would otherwise write for itself — and one everybody would spell differently.\n -->\n <div v-if=\"$slots.end\" class=\"wx-header__end\">\n <slot name=\"end\" />\n </div>\n </header>\n</template>\n\n<style scoped>\n.wx-header {\n display: flex;\n align-items: center;\n gap: var(--wx-space-12);\n box-sizing: border-box;\n flex: 0 0 auto;\n height: var(--wx-header-height, 56px);\n padding-inline: var(--wx-header-padding, var(--wx-space-16));\n background: var(--wx-bg-surface);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n}\n\n.wx-header__end {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n /* Everything before it keeps its place; this group takes the far end. */\n margin-inline-start: auto;\n /*\n * And keeps it. Left to shrink like any other flex item, the account menu is the\n * first thing a wide navigation bar squeezes — it slides under the bar and off the\n * edge of the header. Whatever is short of room, it is not this.\n */\n flex: 0 0 auto;\n}\n\n/*\n * A bar is chrome, not content: it is padded to the gutter the sidebar's icons stand\n * in — 10px, which puts the centre of a 36px control in the header exactly above the\n * centre of the rail below it. A header carrying nothing but a title can take `lg`.\n */\n.wx-header--padding-none {\n --wx-header-padding: 0px;\n}\n\n.wx-header--padding-sm {\n --wx-header-padding: var(--wx-space-6);\n}\n\n.wx-header--padding-md {\n --wx-header-padding: var(--wx-space-10);\n}\n\n.wx-header--padding-lg {\n --wx-header-padding: var(--wx-space-16);\n}\n\n.wx-header--bordered {\n border-bottom: 1px solid var(--wx-border-default);\n}\n\n.wx-header--sticky {\n position: sticky;\n top: var(--wx-header-top, 0px);\n z-index: var(--wx-z-index-sticky);\n}\n\n/* A card rather than a bar: the body colour runs all the way round it. */\n.wx-header--floating {\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n box-shadow: var(--wx-shadow-card);\n}\n\n/* On a phone the bar is mostly the title and one button; the roomy option gives way. */\n@media (max-width: 640px) {\n .wx-header--padding-lg {\n --wx-header-padding: var(--wx-space-10);\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { HeadingLevel, HeadingProps, HeadingSize } from './types'\n\ndefineOptions({ name: 'WxHeading' })\n\nconst props = withDefaults(defineProps<HeadingProps>(), {\n level: 2,\n size: undefined,\n tone: 'strong',\n align: undefined,\n truncate: false,\n})\n\n/** What each level looks like when `size` is left alone. */\nconst sizeForLevel: Record<HeadingLevel, HeadingSize> = {\n 1: '3xl',\n 2: '2xl',\n 3: 'xl',\n 4: 'lg',\n 5: 'md',\n 6: 'sm',\n}\n\nconst size = computed(() => props.size ?? sizeForLevel[props.level])\n\nconst classes = computed(() => [\n 'wx-heading',\n `wx-heading--${size.value}`,\n `wx-heading--tone-${props.tone}`,\n {\n [`wx-heading--align-${props.align}`]: Boolean(props.align),\n 'wx-heading--truncate': props.truncate,\n },\n])\n</script>\n\n<template>\n <component :is=\"`h${level}`\" :class=\"classes\">\n <slot />\n </component>\n</template>\n\n<style scoped>\n/*\n * No margin: spacing belongs to the layout around the heading, not to the heading\n * itself. `WxProse` puts the rhythm back for free-flowing content.\n */\n.wx-heading {\n margin: 0;\n color: var(--wx-heading-color, var(--wx-text-strong));\n font-family: var(--wx-font-family-sans);\n font-weight: var(--wx-font-weight-semibold);\n line-height: var(--wx-font-line-height-tight);\n text-wrap: balance;\n}\n\n.wx-heading--sm {\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-heading--md {\n font-size: var(--wx-font-size-md);\n}\n\n.wx-heading--lg {\n font-size: var(--wx-font-size-lg);\n}\n\n.wx-heading--xl {\n font-size: var(--wx-font-size-xl);\n}\n\n.wx-heading--2xl {\n font-size: var(--wx-font-size-2xl);\n}\n\n.wx-heading--3xl {\n font-size: var(--wx-font-size-3xl);\n font-weight: var(--wx-font-weight-bold);\n}\n\n.wx-heading--tone-default {\n --wx-heading-color: var(--wx-text-default);\n}\n\n.wx-heading--tone-strong {\n --wx-heading-color: var(--wx-text-strong);\n}\n\n.wx-heading--tone-muted {\n --wx-heading-color: var(--wx-text-muted);\n}\n\n.wx-heading--tone-placeholder {\n --wx-heading-color: var(--wx-text-placeholder);\n}\n\n.wx-heading--tone-primary {\n --wx-heading-color: var(--wx-color-primary);\n}\n\n.wx-heading--tone-success {\n --wx-heading-color: var(--wx-color-success-active);\n}\n\n.wx-heading--tone-warning {\n --wx-heading-color: var(--wx-color-warning-active);\n}\n\n.wx-heading--tone-danger {\n --wx-heading-color: var(--wx-color-danger);\n}\n\n.wx-heading--tone-info {\n --wx-heading-color: var(--wx-color-info-active);\n}\n\n.wx-heading--tone-inverse {\n --wx-heading-color: var(--wx-text-inverse);\n}\n\n.wx-heading--align-start {\n text-align: start;\n}\n\n.wx-heading--align-center {\n text-align: center;\n}\n\n.wx-heading--align-end {\n text-align: end;\n}\n\n.wx-heading--align-justify {\n text-align: justify;\n}\n\n.wx-heading--truncate {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, nextTick, ref, watch } from 'vue'\nimport { PopoverAnchor, PopoverContent, PopoverPortal, PopoverRoot } from 'reka-ui'\nimport { useControlAttrs } from '../../composables/useControlAttrs'\nimport { useFormField } from '../../composables/useFormField'\nimport { iconNames } from '../Icon/icons'\nimport WxIcon from '../Icon/Icon.vue'\nimport type { IconPickerEmits, IconPickerProps } from './types'\n\ndefineOptions({ name: 'WxIconPicker', inheritAttrs: false })\n\n/**\n * The icon set, picked from rather than typed into.\n *\n * An icon is a name in a set of a hundred and fifty, and a name that is not in it draws\n * nothing at all — no warning, no placeholder, just a label that has quietly moved to where\n * the picture should have been. A text field cannot say that; a grid of every icon there is\n * can only say it.\n *\n * So the box is the search and the panel is the answer: typing filters, clicking chooses, and\n * the value only ever becomes a name the set has.\n */\nconst props = withDefaults(defineProps<IconPickerProps>(), {\n clearable: false,\n placeholder: 'Search icons',\n emptyText: 'No icon of that name',\n unknownText: 'This name is not in the icon set, so nothing is drawn',\n clearLabel: 'Clear',\n teleport: true,\n disabled: undefined,\n size: undefined,\n status: undefined,\n id: undefined,\n name: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<IconPickerEmits>()\n\nconst model = defineModel<string | null>({ default: null })\n\n/* `class` and `style` belong to the control; the rest belongs to its input. */\nconst { rootAttrs, controlAttrs } = useControlAttrs()\n\nconst field = useFormField(props)\nconst open = ref(false)\nconst input = ref<HTMLInputElement | null>(null)\n\n/** What the box shows: the chosen name, or what is being searched for. */\nconst text = ref(model.value ?? '')\n\nwatch(model, (value) => {\n text.value = value ?? ''\n})\n\nconst all = iconNames()\n\n/**\n * The name it holds is not in the set.\n *\n * Picking cannot produce one, but a server can: a type imported from a file, a name that was\n * typed into this field before it was a picker, an icon a site registered and then stopped\n * registering. The field says so rather than showing the same emptiness as \"no icon yet\",\n * which is the very confusion the component exists to end.\n */\nconst unknown = computed(\n () => model.value !== null && model.value !== '' && !all.includes(model.value),\n)\n\nconst shown = computed(() => {\n const query = text.value.trim().toLowerCase()\n\n /* The whole set until somebody types: a picker that opens empty is a search box with a\n panel, and the point of it is that the icons are there to be looked at. */\n return query === '' || query === model.value ? all : all.filter((name) => name.includes(query))\n})\n\nconst classes = computed(() => [\n 'wx-icon-picker',\n `wx-icon-picker--${field.size.value}`,\n {\n [`wx-icon-picker--${field.status.value}`]: field.status.value !== 'default',\n 'is-open': open.value,\n 'is-disabled': field.disabled.value,\n },\n])\n\nfunction choose(name: string): void {\n model.value = name\n text.value = name\n emit('change', name)\n open.value = false\n}\n\nfunction clear(): void {\n model.value = null\n text.value = ''\n emit('change', null)\n void nextTick(() => input.value?.focus())\n}\n\nfunction onInput(event: Event): void {\n text.value = (event.target as HTMLInputElement).value\n open.value = true\n}\n\n/**\n * Opening on the next turn of the loop, not inside the handler.\n *\n * Focus arrives on mousedown, so a panel opened there is a dismissable layer created in the\n * middle of a click that ends outside it — and Reka closes it again on the mouseup. The field\n * would take focus and nothing would appear. A synthetic `focus()` in a test opens it either\n * way, which is why this can only be seen with a real mouse.\n */\nfunction onFocus(): void {\n setTimeout(() => {\n open.value = true\n })\n}\n\n/** One match left and Enter pressed: the search has already chosen. */\nfunction onEnter(): void {\n if (shown.value.length === 1) choose(shown.value[0]!)\n}\n\nconst grid = ref<HTMLElement | null>(null)\n\n/*\n * A search nobody finished is not a value: what the box holds goes back to what the model\n * holds the moment the panel closes. And on the way in, the panel opens where the chosen icon\n * is — a hundred and fifty tiles with the current one somewhere below the fold is a list that\n * has not answered the first question anybody has of it.\n */\nwatch(open, (value) => {\n if (!value) {\n text.value = model.value ?? ''\n\n return\n }\n\n void nextTick(() => {\n const box = grid.value\n const current = box?.querySelector<HTMLElement>('.is-current')\n\n /* Its own scroller and not `scrollIntoView`, which would also scroll the page under it. */\n if (box && current) box.scrollTop = current.offsetTop - box.clientHeight / 2\n })\n})\n</script>\n\n<template>\n <popover-root v-model:open=\"open\">\n <div :class=\"classes\" v-bind=\"rootAttrs\">\n <popover-anchor as-child>\n <div class=\"wx-icon-picker__field\">\n <span\n class=\"wx-icon-picker__preview\"\n :class=\"{ 'is-empty': !model, 'is-unknown': unknown }\"\n :title=\"unknown ? unknownText : undefined\"\n >\n <wx-icon v-if=\"unknown\" name=\"warning\" />\n <wx-icon v-else-if=\"model\" :name=\"model\" />\n </span>\n\n <input\n :id=\"field.id.value\"\n ref=\"input\"\n v-bind=\"controlAttrs\"\n class=\"wx-icon-picker__input\"\n type=\"text\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n role=\"combobox\"\n :aria-expanded=\"open\"\n :value=\"text\"\n :name=\"name\"\n :placeholder=\"placeholder\"\n :disabled=\"field.disabled.value\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"field.describedBy.value\"\n :aria-invalid=\"field.status.value === 'error' || undefined\"\n @input=\"onInput\"\n @focus=\"onFocus\"\n @keydown.enter.prevent=\"onEnter\"\n />\n\n <button\n v-if=\"clearable && model && !field.disabled.value\"\n class=\"wx-icon-picker__clear\"\n type=\"button\"\n tabindex=\"-1\"\n :aria-label=\"clearLabel\"\n @click.stop=\"clear\"\n >\n <wx-icon name=\"close\" />\n </button>\n </div>\n </popover-anchor>\n\n <popover-portal :disabled=\"!teleport\">\n <popover-content\n class=\"wx-icon-picker__panel\"\n :side-offset=\"4\"\n align=\"start\"\n @open-auto-focus.prevent\n >\n <div v-if=\"shown.length\" ref=\"grid\" class=\"wx-icon-picker__grid\">\n <button\n v-for=\"name in shown\"\n :key=\"name\"\n type=\"button\"\n class=\"wx-icon-picker__option\"\n :class=\"{ 'is-current': name === model }\"\n :title=\"name\"\n @click=\"choose(name)\"\n >\n <wx-icon :name=\"name\" size=\"lg\" />\n <span class=\"wx-icon-picker__name\">{{ name }}</span>\n </button>\n </div>\n <p v-else class=\"wx-icon-picker__empty\">{{ emptyText }}</p>\n </popover-content>\n </popover-portal>\n </div>\n </popover-root>\n</template>\n\n<style scoped>\n.wx-icon-picker {\n display: block;\n width: 100%;\n}\n\n.wx-icon-picker__field {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n padding-inline: var(--wx-space-10);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-control);\n background: var(--wx-bg-surface);\n block-size: var(--wx-size-control-md);\n}\n\n.wx-icon-picker.is-open .wx-icon-picker__field,\n.wx-icon-picker__field:focus-within {\n border-color: var(--wx-color-primary);\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-icon-picker--error .wx-icon-picker__field {\n border-color: var(--wx-color-danger);\n}\n\n.wx-icon-picker.is-disabled .wx-icon-picker__field {\n background: var(--wx-bg-disabled);\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n/* Where the chosen icon sits — and, when there is none, the hole it leaves. */\n.wx-icon-picker__preview {\n display: grid;\n flex: none;\n place-items: center;\n inline-size: 24px;\n block-size: 24px;\n border-radius: var(--wx-radius-xs);\n font-size: var(--wx-font-size-lg);\n color: var(--wx-text-default);\n}\n\n.wx-icon-picker__preview.is-empty {\n border: 1px dashed var(--wx-border-default);\n}\n\n.wx-icon-picker__preview.is-unknown {\n border: 0;\n color: var(--wx-color-warning);\n}\n\n.wx-icon-picker__input {\n flex: 1 1 auto;\n min-inline-size: 0;\n border: 0;\n background: none;\n font: inherit;\n color: inherit;\n outline: none;\n}\n\n.wx-icon-picker__clear {\n display: grid;\n place-items: center;\n flex: none;\n padding: 0;\n border: 0;\n background: none;\n color: var(--wx-text-muted);\n cursor: pointer;\n}\n\n.wx-icon-picker__clear:hover {\n color: var(--wx-text-default);\n}\n\n.wx-icon-picker--sm .wx-icon-picker__field {\n block-size: var(--wx-size-control-sm);\n padding-inline: var(--wx-space-8);\n}\n\n.wx-icon-picker--lg .wx-icon-picker__field {\n block-size: var(--wx-size-control-lg);\n padding-inline: var(--wx-space-14);\n}\n</style>\n\n<style>\n/* Teleported panel: it is portalled out of the component, so the scope attribute never\n reaches it and a scoped rule matches nothing at all — the panel would draw transparent. */\n.wx-icon-picker__panel {\n font-family: var(--wx-font-family-sans);\n inline-size: min(360px, calc(100vw - var(--wx-space-16)));\n padding: var(--wx-space-8);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n background: var(--wx-bg-surface);\n box-shadow: var(--wx-shadow-popover);\n z-index: var(--wx-z-index-popover);\n}\n\n/* Four across and a scroll: a hundred and fifty icons are a page, not a dropdown. */\n.wx-icon-picker__grid {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: var(--wx-space-4);\n max-block-size: 280px;\n overflow-y: auto;\n}\n\n.wx-icon-picker__option {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--wx-space-4);\n padding: var(--wx-space-8) var(--wx-space-4);\n border: 1px solid transparent;\n border-radius: var(--wx-radius-sm);\n background: none;\n color: inherit;\n font: inherit;\n cursor: pointer;\n}\n\n.wx-icon-picker__option:hover {\n background: var(--wx-bg-subtle);\n}\n\n.wx-icon-picker__option.is-current {\n border-color: var(--wx-color-primary);\n color: var(--wx-color-primary);\n}\n\n/* The name is what gets typed into a template, so it is shown whole or not at all. */\n.wx-icon-picker__name {\n max-inline-size: 100%;\n overflow: hidden;\n font-size: var(--wx-font-size-xs);\n color: var(--wx-text-muted);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wx-icon-picker__empty {\n margin: 0;\n padding: var(--wx-space-12);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n text-align: center;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { useFormField } from '../../composables/useFormField'\nimport type { InputNumberEmits, InputNumberModelValue, InputNumberProps } from './types'\nimport { useControlAttrs } from '../../composables/useControlAttrs'\n\ndefineOptions({ name: 'WxInputNumber', inheritAttrs: false })\n\n/* `class` and `style` belong to the control; the rest belongs to its input. */\nconst { rootAttrs, controlAttrs } = useControlAttrs()\n\nconst props = withDefaults(defineProps<InputNumberProps>(), {\n min: undefined,\n max: undefined,\n step: 1,\n precision: undefined,\n controls: true,\n controlsPosition: 'sides',\n wheel: false,\n size: undefined,\n status: undefined,\n id: undefined,\n name: undefined,\n placeholder: undefined,\n disabled: undefined,\n readonly: false,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<InputNumberEmits>()\n\nconst model = defineModel<InputNumberModelValue>({ default: null })\n\nconst field = useFormField(props)\nconst inputRef = ref<HTMLInputElement | null>(null)\nconst focused = ref(false)\n\n/** Decimals to keep: explicit `precision`, otherwise whatever `step` implies. */\nconst precision = computed(() => {\n if (props.precision !== undefined) return props.precision\n const [, decimals = ''] = String(props.step).split('.')\n return decimals.length\n})\n\n/** Rounds through a scaled integer so 0.1 + 0.2 does not leak into the model. */\nfunction round(value: number): number {\n const factor = 10 ** precision.value\n return Math.round((value + Number.EPSILON) * factor) / factor\n}\n\nfunction clamp(value: number): number {\n let next = value\n if (props.min !== undefined) next = Math.max(next, props.min)\n if (props.max !== undefined) next = Math.min(next, props.max)\n return round(next)\n}\n\nconst current = computed<number | null>(() =>\n typeof model.value === 'number' && Number.isFinite(model.value) ? model.value : null,\n)\n\n/**\n * A number as the field shows it: to the precision when it has a fraction — `2.50`, a price\n * reads in cents — and bare when it is whole. `1380.00` on a price that is a round sum read as\n * an amount somebody typed to the cent. The model keeps the number as it is either way.\n */\nfunction show(value: number): string {\n const text = value.toFixed(precision.value)\n return Number.isInteger(Number(text)) ? String(Math.trunc(Number(text))) : text\n}\n\n/** What the user sees. Kept as text so a half-typed \"-\" or \"1.\" survives. */\nconst display = ref(current.value === null ? '' : show(current.value))\n\nwatch(current, (value) => {\n if (focused.value) return\n display.value = value === null ? '' : show(value)\n})\n\nconst disabled = computed(() => field.disabled.value)\nconst canDecrease = computed(\n () =>\n !disabled.value &&\n !props.readonly &&\n (props.min === undefined || (current.value ?? 0) > props.min),\n)\nconst canIncrease = computed(\n () =>\n !disabled.value &&\n !props.readonly &&\n (props.max === undefined || (current.value ?? 0) < props.max),\n)\n\nconst classes = computed(() => [\n 'wx-input-number',\n `wx-input-number--${field.size.value}`,\n `wx-input-number--controls-${props.controls ? props.controlsPosition : 'none'}`,\n {\n [`wx-input-number--${field.status.value}`]: field.status.value !== 'default',\n 'is-focused': focused.value,\n 'is-disabled': disabled.value,\n },\n])\n\nfunction commit(value: number | null) {\n if (model.value === value) return\n model.value = value\n emit('change', value)\n}\n\nfunction stepBy(direction: 1 | -1) {\n if (disabled.value || props.readonly) return\n const base = current.value ?? clamp(0)\n const next = clamp(base + direction * props.step)\n commit(next)\n display.value = show(next)\n}\n\nfunction onInput(event: Event) {\n display.value = (event.target as HTMLInputElement).value\n const parsed = Number.parseFloat(display.value)\n // While typing, only push through values that already make sense.\n if (display.value === '') commit(null)\n else if (Number.isFinite(parsed)) commit(round(parsed))\n}\n\n/** Clamping and formatting happen on blur, so typing 5 into a min=10 field is possible. */\nfunction normalize() {\n if (display.value.trim() === '') {\n commit(null)\n display.value = ''\n return\n }\n const parsed = Number.parseFloat(display.value)\n if (!Number.isFinite(parsed)) {\n display.value = current.value === null ? '' : show(current.value)\n return\n }\n const next = clamp(parsed)\n commit(next)\n display.value = show(next)\n}\n\nfunction onFocus(event: FocusEvent) {\n focused.value = true\n emit('focus', event)\n}\n\nfunction onBlur(event: FocusEvent) {\n focused.value = false\n normalize()\n emit('blur', event)\n}\n\n/**\n * Only ever acts on a focused field, and swallows the scroll while it does — a\n * hovered field must not steal the page's scrolling.\n */\nfunction onWheel(event: WheelEvent) {\n if (!props.wheel || !focused.value || disabled.value || props.readonly) return\n event.preventDefault()\n stepBy(event.deltaY < 0 ? 1 : -1)\n}\n\nfunction onKeydown(event: KeyboardEvent) {\n if (event.key === 'ArrowUp') {\n event.preventDefault()\n stepBy(1)\n } else if (event.key === 'ArrowDown') {\n event.preventDefault()\n stepBy(-1)\n } else if (event.key === 'Enter') {\n normalize()\n }\n}\n\ndefineExpose({\n focus: () => inputRef.value?.focus(),\n blur: () => inputRef.value?.blur(),\n increase: () => stepBy(1),\n decrease: () => stepBy(-1),\n input: inputRef,\n})\n</script>\n\n<template>\n <div :class=\"classes\" v-bind=\"rootAttrs\">\n <button\n v-if=\"controls\"\n class=\"wx-input-number__button wx-input-number__button--decrease\"\n type=\"button\"\n tabindex=\"-1\"\n aria-label=\"Decrease\"\n :disabled=\"!canDecrease\"\n @click=\"stepBy(-1)\"\n >\n <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M3.5 8h9\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n </button>\n\n <input\n :id=\"field.id.value\"\n ref=\"inputRef\"\n v-bind=\"controlAttrs\"\n class=\"wx-input-number__inner\"\n type=\"text\"\n inputmode=\"decimal\"\n autocomplete=\"off\"\n :name=\"name\"\n :value=\"display\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"field.describedBy.value\"\n :aria-invalid=\"field.status.value === 'error' || undefined\"\n role=\"spinbutton\"\n :aria-valuenow=\"current ?? undefined\"\n :aria-valuemin=\"min\"\n :aria-valuemax=\"max\"\n @input=\"onInput\"\n @focus=\"onFocus\"\n @blur=\"onBlur\"\n @keydown=\"onKeydown\"\n @wheel=\"onWheel\"\n />\n\n <button\n v-if=\"controls\"\n class=\"wx-input-number__button wx-input-number__button--increase\"\n type=\"button\"\n tabindex=\"-1\"\n aria-label=\"Increase\"\n :disabled=\"!canIncrease\"\n @click=\"stepBy(1)\"\n >\n <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M8 3.5v9M3.5 8h9\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n </div>\n</template>\n\n<style scoped>\n/*\n * In a form a number is a few digits, and a field as wide as a title put its − and + a whole line\n * apart with the digits alone in the middle. Bare — in a filter row or a table cell — it keeps\n * the width it is given.\n */\n.wx-form-item .wx-input-number {\n max-width: 240px;\n}\n\n.wx-input-number {\n display: inline-flex;\n align-items: center;\n box-sizing: border-box;\n width: 100%;\n height: var(--wx-size-control-md);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-control);\n color: var(--wx-text-default);\n overflow: hidden;\n transition:\n border-color var(--wx-duration-normal) var(--wx-easing-standard),\n background-color var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-input-number--sm {\n height: var(--wx-size-control-sm);\n font-size: var(--wx-font-size-control-sm);\n}\n\n.wx-input-number--md {\n height: var(--wx-size-control-md);\n font-size: var(--wx-font-size-control-md);\n}\n\n.wx-input-number--lg {\n height: var(--wx-size-control-lg);\n font-size: var(--wx-font-size-control-lg);\n}\n\n.wx-input-number:hover:not(.is-disabled) {\n border-color: var(--wx-border-strong);\n}\n\n.wx-input-number.is-focused {\n border-color: var(--wx-border-focus);\n}\n\n.wx-input-number--error,\n.wx-input-number--error.is-focused {\n border-color: var(--wx-color-danger);\n}\n\n.wx-input-number--success {\n border-color: var(--wx-color-success);\n}\n\n.wx-input-number--warning {\n border-color: var(--wx-color-warning);\n}\n\n.wx-input-number.is-disabled {\n background: var(--wx-bg-disabled);\n color: var(--wx-text-disabled);\n}\n\n.wx-input-number__inner {\n flex: 1 1 auto;\n min-width: 0;\n height: 100%;\n padding: 0 var(--wx-space-12);\n background: transparent;\n border: none;\n outline: none;\n color: inherit;\n font-family: inherit;\n font-size: inherit;\n font-variant-numeric: tabular-nums;\n text-align: center;\n}\n\n.wx-input-number--controls-none .wx-input-number__inner {\n text-align: left;\n}\n\n.wx-input-number__inner::placeholder {\n color: var(--wx-text-placeholder);\n}\n\n.wx-input-number__inner:disabled {\n cursor: not-allowed;\n}\n\n.wx-input-number__button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: calc(var(--wx-size-control-md) - 8px);\n height: 100%;\n padding: 0;\n background: var(--wx-bg-fill);\n border: none;\n color: var(--wx-text-default);\n cursor: pointer;\n transition: background-color var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-input-number__button svg {\n width: 16px;\n height: 16px;\n}\n\n.wx-input-number__button:hover:not(:disabled) {\n background: var(--wx-bg-fill-hover);\n color: var(--wx-color-primary);\n}\n\n.wx-input-number__button:disabled {\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n/*\n * Stacked layout: the DOM order stays decrease → input → increase (which is what a\n * screen reader and the tab order want); grid puts the buttons where they belong.\n */\n.wx-input-number--controls-right {\n display: grid;\n grid-template-columns: 1fr auto;\n grid-template-rows: 1fr 1fr;\n}\n\n.wx-input-number--controls-right .wx-input-number__inner {\n grid-column: 1;\n grid-row: 1 / span 2;\n text-align: left;\n}\n\n.wx-input-number--controls-right .wx-input-number__button {\n width: calc(var(--wx-size-control-md) - 16px);\n height: 100%;\n border-left: 1px solid var(--wx-border-default);\n}\n\n.wx-input-number--controls-right .wx-input-number__button--increase {\n grid-column: 2;\n grid-row: 1;\n}\n\n.wx-input-number--controls-right .wx-input-number__button--decrease {\n grid-column: 2;\n grid-row: 2;\n border-top: 1px solid var(--wx-border-default);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport type { SegmentedEmits, SegmentedOption, SegmentedProps, SegmentedValue } from './types'\n\ndefineOptions({ name: 'WxSegmented' })\n\nconst props = withDefaults(defineProps<SegmentedProps>(), {\n options: () => [],\n size: 'md',\n block: false,\n disabled: false,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<SegmentedEmits>()\n\ndefineSlots<{\n /** A segment's contents, when a label and an icon are not enough. */\n option?: (props: { option: SegmentedOption; selected: boolean }) => unknown\n}>()\n\nconst model = defineModel<SegmentedValue | undefined>({ default: undefined })\n\nfunction choose(option: SegmentedOption) {\n if (props.disabled || option.disabled || option.value === model.value) return\n model.value = option.value\n emit('change', option.value)\n}\n\n/*\n * A row of radios, not a row of buttons. Choosing one of a few is what a radio group\n * is, and saying so out loud is what gets a screen reader to announce \"2 of 4\" and\n * the arrow keys to move between them — neither of which a row of buttons gets.\n */\nconst classes = computed(() => [\n 'wx-segmented',\n `wx-segmented--${props.size}`,\n {\n 'wx-segmented--block': props.block,\n 'is-disabled': props.disabled,\n },\n])\n</script>\n\n<template>\n <div :class=\"classes\" role=\"radiogroup\" :aria-label=\"ariaLabel\">\n <button\n v-for=\"option in options\"\n :key=\"option.value\"\n type=\"button\"\n role=\"radio\"\n class=\"wx-segmented__option\"\n :class=\"{ 'is-selected': option.value === model }\"\n :aria-checked=\"option.value === model\"\n :aria-label=\"option.ariaLabel\"\n :disabled=\"disabled || option.disabled\"\n :tabindex=\"option.value === model ? 0 : -1\"\n @click=\"choose(option)\"\n >\n <slot name=\"option\" :option=\"option\" :selected=\"option.value === model\">\n <wx-icon v-if=\"option.icon\" :name=\"option.icon\" class=\"wx-segmented__icon\" />\n <span v-if=\"option.label\" class=\"wx-segmented__label\">{{ option.label }}</span>\n </slot>\n </button>\n </div>\n</template>\n\n<style scoped>\n.wx-segmented {\n display: inline-flex;\n align-items: center;\n box-sizing: border-box;\n gap: 2px;\n max-width: 100%;\n /* As wide as its options, also in a column that stretches its children — a form field's\n control is one, and the track ran the width of the input under it with the segments\n huddled at its left end. */\n align-self: flex-start;\n padding: 2px;\n background: var(--wx-bg-fill);\n border-radius: var(--wx-radius-control);\n font-family: var(--wx-font-family-sans);\n}\n\n.wx-segmented--block {\n display: flex;\n align-self: stretch;\n width: 100%;\n}\n\n.wx-segmented--block .wx-segmented__option {\n flex: 1 1 0;\n}\n\n.wx-segmented__option {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n gap: var(--wx-space-6);\n min-width: 0;\n height: var(--wx-segmented-height);\n padding-inline: var(--wx-segmented-padding);\n background: transparent;\n border: none;\n /* Two pixels inside the track's own radius, so the corners stay concentric. */\n border-radius: calc(var(--wx-radius-control) - 2px);\n color: var(--wx-text-muted);\n font-family: inherit;\n font-size: var(--wx-segmented-text);\n font-weight: var(--wx-font-weight-medium);\n line-height: 1;\n white-space: nowrap;\n cursor: pointer;\n transition:\n background var(--wx-duration-fast) var(--wx-easing-standard),\n color var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-segmented--sm {\n --wx-segmented-height: calc(var(--wx-size-control-sm) - 4px);\n --wx-segmented-padding: var(--wx-space-10);\n --wx-segmented-text: var(--wx-font-size-control-sm);\n}\n\n.wx-segmented--md {\n --wx-segmented-height: calc(var(--wx-size-control-md) - 4px);\n --wx-segmented-padding: var(--wx-space-12);\n --wx-segmented-text: var(--wx-font-size-control-md);\n}\n\n.wx-segmented--lg {\n --wx-segmented-height: calc(var(--wx-size-control-lg) - 4px);\n --wx-segmented-padding: var(--wx-space-16);\n --wx-segmented-text: var(--wx-font-size-control-lg);\n}\n\n.wx-segmented__option:hover:not(:disabled):not(.is-selected) {\n color: var(--wx-text-default);\n}\n\n.wx-segmented__option:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n/* The chosen segment is the one lifted out of the track. */\n.wx-segmented__option.is-selected {\n background: var(--wx-bg-surface);\n box-shadow: var(--wx-shadow-card);\n color: var(--wx-text-strong);\n}\n\n.wx-segmented__option:disabled {\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n/* A line of its own height: the ellipsis needs `overflow: hidden`, and on the option's\n `line-height: 1` that cut the descenders off — the tail of a \"g\", a \"y\". */\n.wx-segmented__label {\n overflow: hidden;\n text-overflow: ellipsis;\n line-height: var(--wx-font-line-height-normal);\n}\n\n.wx-segmented__icon {\n flex: 0 0 auto;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-segmented__option {\n transition: none;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { SliderRange, SliderRoot, SliderThumb, SliderTrack } from 'reka-ui'\nimport { useFormField } from '../../composables/useFormField'\nimport type { SliderEmits, SliderModelValue, SliderProps } from './types'\nimport { useControlAttrs } from '../../composables/useControlAttrs'\n\ndefineOptions({ name: 'WxSlider', inheritAttrs: false })\n\n/* `class` and `style` belong to the control; the rest belongs to its input. */\nconst { rootAttrs, controlAttrs } = useControlAttrs()\n\nconst props = withDefaults(defineProps<SliderProps>(), {\n min: 0,\n max: 100,\n step: 1,\n range: false,\n minStepsBetweenThumbs: 0,\n showValue: false,\n marks: undefined,\n disabled: undefined,\n size: undefined,\n id: undefined,\n name: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<SliderEmits>()\n\nconst model = defineModel<SliderModelValue>({ default: null })\n\nconst field = useFormField(props)\n\n/**\n * The underlying slider always works with an array. A single slider keeps a plain\n * number in the model, because that is what a caller wants to store.\n */\nconst values = computed<number[]>(() => {\n if (props.range) {\n const pair = Array.isArray(model.value) ? model.value : []\n return [pair[0] ?? props.min, pair[1] ?? props.max]\n }\n const single = Array.isArray(model.value) ? model.value[0] : model.value\n return [single ?? props.min]\n})\n\nfunction onUpdate(next: number[] | undefined) {\n if (!next) return\n const value = props.range ? [...next] : next[0]\n model.value = value\n emit('change', value)\n}\n\nconst marks = computed(() =>\n Object.entries(props.marks ?? {}).map(([value, label]) => ({\n value: Number(value),\n label,\n offset: ((Number(value) - props.min) / (props.max - props.min)) * 100,\n })),\n)\n\nconst classes = computed(() => [\n 'wx-slider',\n `wx-slider--${field.size.value}`,\n { 'is-disabled': field.disabled.value, 'is-range': props.range },\n])\n</script>\n\n<template>\n <div :class=\"classes\" v-bind=\"rootAttrs\">\n <div class=\"wx-slider__row\">\n <slider-root\n :id=\"field.id.value\"\n v-bind=\"controlAttrs\"\n class=\"wx-slider__root\"\n :model-value=\"values\"\n :min=\"min\"\n :max=\"max\"\n :step=\"step\"\n :disabled=\"field.disabled.value\"\n :min-steps-between-thumbs=\"minStepsBetweenThumbs\"\n :name=\"name\"\n @update:model-value=\"onUpdate\"\n >\n <slider-track class=\"wx-slider__track\">\n <slider-range class=\"wx-slider__range\" />\n </slider-track>\n\n <slider-thumb\n v-for=\"index in values.length\"\n :key=\"index\"\n class=\"wx-slider__thumb\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"field.describedBy.value\"\n />\n </slider-root>\n\n <span v-if=\"showValue\" class=\"wx-slider__value\">\n {{ range ? `${values[0]} — ${values[1]}` : values[0] }}\n </span>\n </div>\n\n <div v-if=\"marks.length\" class=\"wx-slider__marks\" aria-hidden=\"true\">\n <span\n v-for=\"mark in marks\"\n :key=\"mark.value\"\n class=\"wx-slider__mark\"\n :style=\"{ left: `${mark.offset}%` }\"\n >\n {{ mark.label }}\n </span>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-slider {\n display: block;\n width: 100%;\n}\n\n.wx-slider__row {\n display: flex;\n align-items: center;\n gap: var(--wx-space-16);\n}\n\n.wx-slider__root {\n position: relative;\n display: flex;\n align-items: center;\n flex: 1 1 auto;\n height: var(--wx-size-control-md);\n touch-action: none;\n user-select: none;\n}\n\n.wx-slider--sm .wx-slider__root {\n height: var(--wx-size-control-sm);\n}\n\n.wx-slider--lg .wx-slider__root {\n height: var(--wx-size-control-lg);\n}\n\n.wx-slider__track {\n position: relative;\n flex: 1 1 auto;\n height: 4px;\n background: var(--wx-bg-fill-hover);\n border-radius: var(--wx-radius-full);\n}\n\n.wx-slider__range {\n position: absolute;\n height: 100%;\n background: var(--wx-color-primary);\n border-radius: var(--wx-radius-full);\n}\n\n.wx-slider__thumb {\n display: block;\n width: 18px;\n height: 18px;\n background: var(--wx-bg-surface);\n border: 2px solid var(--wx-color-primary);\n border-radius: var(--wx-radius-full);\n box-shadow: var(--wx-shadow-card);\n cursor: grab;\n transition: box-shadow var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-slider__thumb:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-slider__thumb:active {\n cursor: grabbing;\n}\n\n.wx-slider.is-disabled .wx-slider__range {\n background: var(--wx-color-primary-disabled);\n}\n\n.wx-slider.is-disabled .wx-slider__thumb {\n border-color: var(--wx-color-primary-disabled);\n cursor: not-allowed;\n}\n\n.wx-slider__value {\n flex: 0 0 auto;\n min-width: 4ch;\n color: var(--wx-text-default);\n font-size: var(--wx-font-size-sm);\n font-variant-numeric: tabular-nums;\n text-align: right;\n}\n\n.wx-slider__marks {\n position: relative;\n height: 18px;\n margin-top: calc(var(--wx-space-4) * -1);\n}\n\n.wx-slider__mark {\n position: absolute;\n transform: translateX(-50%);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n white-space: nowrap;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useFormField, type ChoiceValue } from '../../composables/useFormField'\nimport type { SwitchEmits, SwitchProps } from './types'\nimport { useControlAttrs } from '../../composables/useControlAttrs'\n\ndefineOptions({ name: 'WxSwitch', inheritAttrs: false })\n\n/* `class` and `style` belong to the control; the rest belongs to its input. */\nconst { rootAttrs, controlAttrs } = useControlAttrs()\n\nconst props = withDefaults(defineProps<SwitchProps>(), {\n activeValue: true,\n inactiveValue: false,\n label: undefined,\n disabled: undefined,\n size: undefined,\n id: undefined,\n name: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<SwitchEmits>()\n\nconst model = defineModel<ChoiceValue>({ default: false })\n\nconst field = useFormField(props)\n\nconst checked = computed(() => model.value === props.activeValue)\nconst size = computed(() => props.size ?? field.size.value)\n\nconst classes = computed(() => [\n 'wx-switch',\n `wx-switch--${size.value}`,\n { 'is-checked': checked.value, 'is-disabled': field.disabled.value },\n])\n\nfunction onChange(event: Event) {\n const next = (event.target as HTMLInputElement).checked ? props.activeValue : props.inactiveValue\n model.value = next\n emit('change', next)\n}\n</script>\n\n<template>\n <label :class=\"classes\" v-bind=\"rootAttrs\">\n <input\n :id=\"field.id.value\"\n v-bind=\"controlAttrs\"\n class=\"wx-switch__native\"\n type=\"checkbox\"\n role=\"switch\"\n :name=\"name\"\n :checked=\"checked\"\n :disabled=\"field.disabled.value\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"field.describedBy.value\"\n @change=\"onChange\"\n />\n\n <span class=\"wx-switch__track\" aria-hidden=\"true\">\n <span class=\"wx-switch__thumb\" />\n </span>\n\n <span v-if=\"label || $slots.default\" class=\"wx-switch__label\">\n <slot>{{ label }}</slot>\n </span>\n </label>\n</template>\n\n<style scoped>\n.wx-switch {\n display: inline-flex;\n align-items: center;\n gap: var(--wx-space-8);\n cursor: pointer;\n user-select: none;\n color: var(--wx-text-default);\n}\n\n.wx-switch.is-disabled {\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n.wx-switch__native {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n border: 0;\n}\n\n.wx-switch__track {\n display: inline-flex;\n align-items: center;\n flex: 0 0 auto;\n box-sizing: border-box;\n width: calc(var(--wx-switch-height) * 1.8);\n height: var(--wx-switch-height);\n padding: 2px;\n background: var(--wx-border-strong);\n border-radius: var(--wx-radius-full);\n transition:\n background-color var(--wx-duration-normal) var(--wx-easing-standard),\n box-shadow var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-switch--sm {\n --wx-switch-height: 18px;\n font-size: var(--wx-font-size-control-sm);\n}\n\n.wx-switch--md {\n --wx-switch-height: 22px;\n font-size: var(--wx-font-size-control-md);\n}\n\n.wx-switch--lg {\n --wx-switch-height: 26px;\n font-size: var(--wx-font-size-control-lg);\n}\n\n.wx-switch__thumb {\n width: calc(var(--wx-switch-height) - 4px);\n height: calc(var(--wx-switch-height) - 4px);\n background: var(--wx-bg-surface);\n border-radius: var(--wx-radius-full);\n box-shadow: var(--wx-shadow-card);\n transition: transform var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-switch.is-checked .wx-switch__track {\n background: var(--wx-color-primary);\n}\n\n.wx-switch.is-checked .wx-switch__thumb {\n transform: translateX(calc(var(--wx-switch-height) * 0.8));\n}\n\n.wx-switch.is-disabled .wx-switch__track {\n background: var(--wx-border-default);\n}\n\n.wx-switch.is-disabled.is-checked .wx-switch__track {\n background: var(--wx-color-primary-disabled);\n}\n\n.wx-switch__native:focus-visible + .wx-switch__track {\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-switch__label {\n line-height: var(--wx-font-line-height-normal);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-switch__track,\n .wx-switch__thumb {\n transition: none;\n }\n}\n</style>\n","import type { ImageEditorCrop } from './types'\n\n/** The eight grips, named after the compass the way every editor names them. */\nexport type CropHandle = 'nw' | 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w'\n\nexport interface CropBounds {\n width: number\n height: number\n}\n\n/*\n * All of this works in the pixels of the picture *after* its quarter turns — the space\n * the crop is stored in. The screen only ever comes in as a scale factor, so the maths\n * here is the same whether the editor is 300 pixels wide or 3000.\n */\n\nexport function clamp(value: number, min: number, max: number) {\n return Math.min(Math.max(value, min), max)\n}\n\n/** `1.7778` → `16:9`. Falls back to a decimal for a ratio that is nobody's convention. */\nexport function ratioLabelFor(value: number) {\n for (let denominator = 1; denominator <= 16; denominator += 1) {\n const numerator = value * denominator\n if (Math.abs(numerator - Math.round(numerator)) < 0.001) {\n return `${Math.round(numerator)}:${denominator}`\n }\n }\n return value.toFixed(2)\n}\n\n/** The whole picture, or the largest rectangle of `ratio` in the middle of it. */\nexport function fullCrop(bounds: CropBounds, ratio?: number): ImageEditorCrop {\n const crop = { x: 0, y: 0, width: bounds.width, height: bounds.height }\n return ratio ? fitRatio(crop, ratio, bounds) : crop\n}\n\n/**\n * The largest rectangle of `ratio` that fits inside `crop`, kept where `crop` was — used\n * when the ratio changes and when a turn leaves the old crop the wrong shape.\n */\nexport function fitRatio(\n crop: ImageEditorCrop,\n ratio: number,\n bounds: CropBounds,\n): ImageEditorCrop {\n const centreX = crop.x + crop.width / 2\n const centreY = crop.y + crop.height / 2\n\n let width = crop.width\n let height = width / ratio\n if (height > crop.height) {\n height = crop.height\n width = height * ratio\n }\n\n /* It can still be wider than the picture — a 16:9 asked of a tall crop, say. */\n const shrink = Math.min(1, bounds.width / width, bounds.height / height)\n width *= shrink\n height *= shrink\n\n return {\n x: clamp(centreX - width / 2, 0, bounds.width - width),\n y: clamp(centreY - height / 2, 0, bounds.height - height),\n width,\n height,\n }\n}\n\n/** Dragged from inside: the crop slides, and stops at the edges of the picture. */\nexport function moveCrop(\n start: ImageEditorCrop,\n dx: number,\n dy: number,\n bounds: CropBounds,\n): ImageEditorCrop {\n return {\n ...start,\n x: clamp(start.x + dx, 0, bounds.width - start.width),\n y: clamp(start.y + dy, 0, bounds.height - start.height),\n }\n}\n\n/**\n * Dragged by a grip.\n *\n * The opposite corner — or the opposite edge, for the four in the middle — is the anchor\n * and does not move; everything else follows the pointer. With a ratio the rectangle is\n * brought back to that ratio before it is fitted inside the picture, so a locked crop\n * cannot be nudged out of shape by dragging it into a corner.\n */\nexport function resizeCrop(\n handle: CropHandle,\n point: { x: number; y: number },\n start: ImageEditorCrop,\n bounds: CropBounds,\n { ratio, min = 1 }: { ratio?: number; min?: number } = {},\n): ImageEditorCrop {\n const dirX = handle.includes('w') ? -1 : handle.includes('e') ? 1 : 0\n const dirY = handle.includes('n') ? -1 : handle.includes('s') ? 1 : 0\n\n /* The point that stays put while the grip is dragged. */\n const anchorX = dirX > 0 ? start.x : dirX < 0 ? start.x + start.width : start.x + start.width / 2\n const anchorY =\n dirY > 0 ? start.y : dirY < 0 ? start.y + start.height : start.y + start.height / 2\n\n let width = dirX ? Math.abs(point.x - anchorX) : start.width\n let height = dirY ? Math.abs(point.y - anchorY) : start.height\n\n if (ratio) {\n /* An edge grip drives one side and the ratio decides the other; a corner is led by\n * whichever way it was dragged furthest. */\n if (!dirX) width = height * ratio\n else if (!dirY) height = width / ratio\n else if (width / height > ratio) height = width / ratio\n else width = height * ratio\n }\n\n /* How far the rectangle may grow before it leaves the picture. A grip in the middle of\n * an edge grows both ways around its anchor, so it runs out at the nearer side. */\n const roomX =\n dirX > 0\n ? bounds.width - anchorX\n : dirX < 0\n ? anchorX\n : 2 * Math.min(anchorX, bounds.width - anchorX)\n const roomY =\n dirY > 0\n ? bounds.height - anchorY\n : dirY < 0\n ? anchorY\n : 2 * Math.min(anchorY, bounds.height - anchorY)\n\n if (ratio) {\n const shrink = Math.min(1, roomX / width, roomY / height)\n width *= shrink\n height *= shrink\n\n const grow = Math.max(1, min / width, min / height)\n width = Math.min(width * grow, roomX)\n height = Math.min(height * grow, roomY)\n } else {\n width = clamp(width, Math.min(min, roomX), roomX)\n height = clamp(height, Math.min(min, roomY), roomY)\n }\n\n const x = dirX > 0 ? anchorX : dirX < 0 ? anchorX - width : anchorX - width / 2\n const y = dirY > 0 ? anchorY : dirY < 0 ? anchorY - height : anchorY - height / 2\n\n return {\n x: clamp(x, 0, bounds.width - width),\n y: clamp(y, 0, bounds.height - height),\n width,\n height,\n }\n}\n\n/**\n * The crop follows the picture through a quarter turn, so what was framed stays framed.\n * `bounds` is the space *before* the turn; the space after it has its sides swapped.\n */\nexport function turnCrop(\n crop: ImageEditorCrop,\n bounds: CropBounds,\n direction: 1 | -1,\n): ImageEditorCrop {\n return direction === 1\n ? {\n x: bounds.height - (crop.y + crop.height),\n y: crop.x,\n width: crop.height,\n height: crop.width,\n }\n : {\n x: crop.y,\n y: bounds.width - (crop.x + crop.width),\n width: crop.height,\n height: crop.width,\n }\n}\n\n/** The same, for a mirroring. */\nexport function mirrorCrop(\n crop: ImageEditorCrop,\n bounds: CropBounds,\n axis: 'x' | 'y',\n): ImageEditorCrop {\n return axis === 'x'\n ? { ...crop, x: bounds.width - (crop.x + crop.width) }\n : { ...crop, y: bounds.height - (crop.y + crop.height) }\n}\n\n/** The largest whole-pixel size of the same shape that fits within the caps. */\nexport function fitInside(width: number, height: number, maxWidth?: number, maxHeight?: number) {\n const shrink = Math.min(1, maxWidth ? maxWidth / width : 1, maxHeight ? maxHeight / height : 1)\n return {\n width: Math.max(1, Math.round(width * shrink)),\n height: Math.max(1, Math.round(height * shrink)),\n }\n}\n","import type { ImageEditorAdjustments } from './types'\n\n/** Nothing done to the picture: the reading every slider starts at. */\nexport const NEUTRAL: ImageEditorAdjustments = {\n brightness: 100,\n contrast: 100,\n saturation: 100,\n mono: false,\n}\n\nexport function isNeutral(adjust: ImageEditorAdjustments) {\n return (\n adjust.brightness === NEUTRAL.brightness &&\n adjust.contrast === NEUTRAL.contrast &&\n adjust.saturation === NEUTRAL.saturation &&\n adjust.mono === NEUTRAL.mono\n )\n}\n\n/**\n * The adjustments as a CSS `filter` — the same string the `<img>` is shown through and\n * the canvas is drawn under, which is what keeps the preview honest.\n *\n * Order matters and is the order a reader expects: lighten, then stretch the contrast,\n * then the colour, and black-and-white last so that it wins over whatever the saturation\n * slider was left at.\n */\nexport function filterString(adjust: ImageEditorAdjustments) {\n const parts: string[] = []\n if (adjust.brightness !== 100) parts.push(`brightness(${adjust.brightness}%)`)\n if (adjust.contrast !== 100) parts.push(`contrast(${adjust.contrast}%)`)\n if (adjust.saturation !== 100 && !adjust.mono) parts.push(`saturate(${adjust.saturation}%)`)\n if (adjust.mono) parts.push('grayscale(1)')\n return parts.join(' ')\n}\n\n/** What the eye reads as brightness — the weights CSS itself uses for `saturate`. */\nfunction luminance(r: number, g: number, b: number) {\n return 0.2126 * r + 0.7152 * g + 0.0722 * b\n}\n\nfunction clampByte(value: number) {\n return value < 0 ? 0 : value > 255 ? 255 : value\n}\n\n/**\n * The same arithmetic by hand, for a browser whose canvas has no `filter`.\n *\n * Safari only learned `ctx.filter` in 16.4, and where it is missing it is missing\n * silently: the picture on screen is adjusted, the file that comes out is not. Doing the\n * pass ourselves is the difference between a wrong file and a slow one.\n *\n * Written over the pixels in place, in the order `filterString` composes them.\n */\nexport function applyAdjustments(pixels: Uint8ClampedArray, adjust: ImageEditorAdjustments) {\n const brightness = adjust.brightness / 100\n const contrast = adjust.contrast / 100\n const saturation = adjust.mono ? 0 : adjust.saturation / 100\n\n for (let index = 0; index < pixels.length; index += 4) {\n let r = pixels[index]!\n let g = pixels[index + 1]!\n let b = pixels[index + 2]!\n\n if (brightness !== 1) {\n r *= brightness\n g *= brightness\n b *= brightness\n }\n\n /* Contrast pivots on mid-grey, which is what makes it contrast and not brightness. */\n if (contrast !== 1) {\n r = (r - 127.5) * contrast + 127.5\n g = (g - 127.5) * contrast + 127.5\n b = (b - 127.5) * contrast + 127.5\n }\n\n if (saturation !== 1) {\n const grey = luminance(r, g, b)\n r = grey + (r - grey) * saturation\n g = grey + (g - grey) * saturation\n b = grey + (b - grey) * saturation\n }\n\n pixels[index] = clampByte(r)\n pixels[index + 1] = clampByte(g)\n pixels[index + 2] = clampByte(b)\n }\n}\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, ref, shallowRef, useTemplateRef, watch } from 'vue'\nimport WxAction from '../Action/Action.vue'\nimport WxButton from '../Button/Button.vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport WxInputNumber from '../InputNumber/InputNumber.vue'\nimport WxPopover from '../Popover/Popover.vue'\nimport WxSegmented from '../Segmented/Segmented.vue'\nimport WxSlider from '../Slider/Slider.vue'\nimport WxSwitch from '../Switch/Switch.vue'\nimport WxTooltip from '../Tooltip/Tooltip.vue'\nimport {\n clamp,\n fitInside,\n fitRatio,\n fullCrop,\n mirrorCrop,\n moveCrop,\n ratioLabelFor,\n resizeCrop,\n turnCrop,\n type CropHandle,\n} from './crop'\nimport { NEUTRAL, applyAdjustments, filterString, isNeutral } from './filters'\nimport type {\n ImageEditorAdjustments,\n ImageEditorCrop,\n ImageEditorEmits,\n ImageEditorProps,\n ImageEditorRatio,\n ImageEditorRatioOption,\n ImageEditorResult,\n} from './types'\n\ndefineOptions({ name: 'WxImageEditor' })\n\n/*\n * A picture, a rectangle over it, and a blob at the end.\n *\n * The editing is all geometry — a crop, quarter turns, mirrorings, an output size — and\n * none of it touches the picture until Save is pressed. Then the whole of it is one\n * `drawImage` onto a canvas the size of the result: one resampling rather than a chain of\n * them, which is what keeps a photograph from going soft on the way through.\n *\n * The component uploads nothing. It answers with a blob, and whatever opened it decides\n * where that goes.\n */\nconst props = withDefaults(defineProps<ImageEditorProps>(), {\n fileName: undefined,\n aspect: undefined,\n ratios: undefined,\n ratio: undefined,\n rotatable: true,\n flippable: true,\n resizable: true,\n filters: false,\n maxWidth: undefined,\n maxHeight: undefined,\n minSize: 16,\n format: 'auto',\n quality: 0.92,\n background: '#ffffff',\n crossOrigin: 'anonymous',\n footer: true,\n disabled: false,\n saveLabel: 'Save',\n cancelLabel: 'Cancel',\n resetLabel: 'Reset',\n rotateLeftLabel: 'Turn left',\n rotateRightLabel: 'Turn right',\n flipHorizontalLabel: 'Mirror across',\n flipVerticalLabel: 'Mirror down',\n ratioLabel: 'Ratio',\n cropLabel: 'Crop',\n outputLabel: 'Output',\n outputHint: 'The size of the picture you will get',\n widthLabel: 'Width',\n heightLabel: 'Height',\n adjustLabel: 'Adjust',\n brightnessLabel: 'Brightness',\n contrastLabel: 'Contrast',\n saturationLabel: 'Saturation',\n monoLabel: 'Black and white',\n freeLabel: 'Free',\n originalLabel: 'Original',\n errorText: 'This picture could not be loaded',\n})\n\nconst emit = defineEmits<ImageEditorEmits>()\n\n/* ------------------------------------------------------------------- source --- */\n\n/*\n * A `File` from an upload field is read through an object URL, which has to be given\n * back — and only ours: a URL that came in as a string belongs to the caller.\n */\nconst objectUrl = ref('')\n\nconst source = computed(() => (typeof props.src === 'string' ? props.src : objectUrl.value))\n\nonBeforeUnmount(() => {\n if (objectUrl.value) URL.revokeObjectURL(objectUrl.value)\n})\n\n/* -------------------------------------------------------------------- state --- */\n\nconst image = useTemplateRef<HTMLImageElement>('image')\nconst stage = useTemplateRef<HTMLElement>('stage')\n\nconst natural = ref({ width: 0, height: 0 })\nconst ready = ref(false)\nconst failed = ref(false)\nconst busy = ref(false)\n\nconst rotation = ref(0)\nconst flipX = ref(false)\nconst flipY = ref(false)\n\n/** The crop, in the pixels of the turned picture. */\nconst crop = ref<ImageEditorCrop>({ x: 0, y: 0, width: 0, height: 0 })\n\n/** Set by hand in the width field; until then the output is the crop's own size. */\nconst widthOverride = ref<number | null>(null)\n\n/*\n * Brightness, contrast, saturation and black-and-white — the four a photograph for a\n * website actually wants. They are shown as a CSS `filter` on the `<img>` and written as\n * the same string onto the canvas, so what is looked at and what comes out are the one\n * calculation rather than two that have to be kept in step.\n */\nconst adjust = ref<ImageEditorAdjustments>({ ...NEUTRAL })\n\nconst filter = computed(() => filterString(adjust.value))\n\n/** Whether the button should show that there is something behind it. */\nconst touchedFilters = computed(() => !isNeutral(adjust.value))\n\ntype SliderKey = 'brightness' | 'contrast' | 'saturation'\n\nconst sliders = computed(() => [\n { key: 'brightness' as SliderKey, label: props.brightnessLabel },\n { key: 'contrast' as SliderKey, label: props.contrastLabel },\n { key: 'saturation' as SliderKey, label: props.saturationLabel },\n])\n\nfunction setAdjustment(key: SliderKey, value: number | number[] | null) {\n if (typeof value !== 'number') return\n adjust.value = { ...adjust.value, [key]: value }\n touched.value = true\n}\n\nfunction adjusted() {\n touched.value = true\n}\n\n/** The picture as it is being looked at: sides swapped by an odd number of turns. */\nconst work = computed(() =>\n rotation.value % 180 === 0\n ? { width: natural.value.width, height: natural.value.height }\n : { width: natural.value.height, height: natural.value.width },\n)\n\n/* -------------------------------------------------------------------- ratio --- */\n\nconst options = computed<ImageEditorRatioOption[]>(() => {\n const given =\n props.ratios ??\n (props.aspect === undefined\n ? (['free', 'original', 1, 4 / 3, 3 / 2, 16 / 9] as ImageEditorRatio[])\n : [])\n\n return given.map((entry) => {\n const option = typeof entry === 'object' ? entry : { value: entry }\n if (option.label) return option\n if (option.value === 'free') return { ...option, label: props.freeLabel }\n if (option.value === 'original') return { ...option, label: props.originalLabel }\n return { ...option, label: ratioLabelFor(option.value as number) }\n })\n})\n\nconst chosen = ref<ImageEditorRatio>('free')\n\n/** Whether anything has been done to the picture — all Reset has to know. */\nconst touched = ref(false)\n\n/** The number the crop is actually held to, if any. `aspect` overrules the picker. */\nconst ratio = computed(() => {\n if (props.aspect) return props.aspect\n if (chosen.value === 'free') return undefined\n if (chosen.value === 'original') {\n return work.value.height ? work.value.width / work.value.height : undefined\n }\n return chosen.value\n})\n\n/* Takes what the picker hands back — a string or a number — which is every ratio there is. */\nfunction chooseRatio(value: string | number | undefined) {\n if (value === undefined) return\n chosen.value = value as ImageEditorRatio\n touched.value = true\n if (ratio.value) setCrop(fitRatio(crop.value, ratio.value, work.value))\n}\n\n/* ------------------------------------------------------------------ loading --- */\n\nfunction reset({ loaded = true } = {}) {\n rotation.value = 0\n flipX.value = false\n flipY.value = false\n widthOverride.value = null\n adjust.value = { ...NEUTRAL }\n chosen.value = props.ratio ?? options.value[0]?.value ?? 'free'\n failed.value = false\n touched.value = false\n\n if (!loaded) {\n ready.value = false\n natural.value = { width: 0, height: 0 }\n crop.value = { x: 0, y: 0, width: 0, height: 0 }\n return\n }\n\n crop.value = fullCrop(work.value, ratio.value)\n}\n\n/* Below the state it clears, and immediate: a new picture is a new everything. */\nwatch(\n () => props.src,\n (src) => {\n if (objectUrl.value) URL.revokeObjectURL(objectUrl.value)\n objectUrl.value = typeof src === 'string' ? '' : URL.createObjectURL(src)\n reset({ loaded: false })\n },\n { immediate: true },\n)\n\nfunction onLoad() {\n const el = image.value\n if (!el) return\n\n natural.value = { width: el.naturalWidth, height: el.naturalHeight }\n ready.value = true\n failed.value = false\n reset()\n emit('load', { ...natural.value })\n}\n\nfunction onError() {\n ready.value = false\n failed.value = true\n emit('error', new Error(`The picture at ${source.value} could not be loaded`))\n}\n\n/* ------------------------------------------------------------------ the view --- */\n\n/*\n * The picture is fitted into the stage and everything on screen is that one number away\n * from the pixels underneath. Nothing is resampled to show it: the `<img>` is the browser's\n * own, turned by a CSS transform, and the crop is a box over it.\n */\nconst box = ref({ width: 0, height: 0 })\n\nlet observer: ResizeObserver | undefined\n\nwatch(stage, (el) => {\n observer?.disconnect()\n if (!el || typeof ResizeObserver === 'undefined') return\n\n observer = new ResizeObserver(() => {\n box.value = { width: el.clientWidth, height: el.clientHeight }\n })\n observer.observe(el)\n box.value = { width: el.clientWidth, height: el.clientHeight }\n})\n\nonBeforeUnmount(() => observer?.disconnect())\n\nconst scale = computed(() => {\n const { width, height } = work.value\n if (!width || !height || !box.value.width || !box.value.height) return 0\n return Math.min(box.value.width / width, box.value.height / height)\n})\n\nconst frameStyle = computed(() => ({\n width: `${work.value.width * scale.value}px`,\n height: `${work.value.height * scale.value}px`,\n}))\n\n/*\n * Read right to left, the way CSS applies them: the picture is turned, then mirrored,\n * then put in the middle. The mirroring comes after the turn so that \"mirror across\"\n * means across the screen, whichever way up the picture currently is — and the canvas\n * composes the transform in exactly this order when it comes to writing the result.\n */\nconst imageStyle = computed(() => ({\n width: `${natural.value.width * scale.value}px`,\n height: `${natural.value.height * scale.value}px`,\n transform: `translate(-50%, -50%) scale(${flipX.value ? -1 : 1}, ${flipY.value ? -1 : 1}) rotate(${rotation.value}deg)`,\n /* On the picture and nowhere else: the crop, the grips and the shade are its siblings. */\n filter: filter.value || undefined,\n}))\n\nconst cropStyle = computed(() => ({\n left: `${crop.value.x * scale.value}px`,\n top: `${crop.value.y * scale.value}px`,\n width: `${crop.value.width * scale.value}px`,\n height: `${crop.value.height * scale.value}px`,\n}))\n\n/* --------------------------------------------------------------- the gesture --- */\n\nconst handles: CropHandle[] = ['nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w']\n\nconst frame = useTemplateRef<HTMLElement>('frame')\nconst cropBox = useTemplateRef<HTMLElement>('cropBox')\n\ninterface Gesture {\n handle: CropHandle | 'move'\n start: ImageEditorCrop\n from: { x: number; y: number }\n}\n\nconst gesture = shallowRef<Gesture | null>(null)\n\n/** Where in the picture's own pixels the pointer is. */\nfunction pointAt(event: PointerEvent) {\n const el = frame.value\n if (!el || !scale.value) return { x: 0, y: 0 }\n const rect = el.getBoundingClientRect()\n return {\n x: (event.clientX - rect.left) / scale.value,\n y: (event.clientY - rect.top) / scale.value,\n }\n}\n\nfunction setCrop(next: ImageEditorCrop) {\n crop.value = next\n touched.value = true\n /* A crop that shrank below the width asked for takes the field down with it. */\n if (widthOverride.value !== null) {\n widthOverride.value = Math.min(widthOverride.value, Math.round(next.width))\n }\n emit('crop', rounded(next))\n}\n\nfunction begin(handle: CropHandle | 'move', event: PointerEvent) {\n if (props.disabled || !ready.value || event.button !== 0) return\n\n event.preventDefault()\n gesture.value = { handle, start: { ...crop.value }, from: pointAt(event) }\n ;(event.currentTarget as HTMLElement).setPointerCapture(event.pointerId)\n\n /*\n * By hand, because the `preventDefault` above is what would otherwise have done it —\n * and a crop the reader has just taken hold of but which never took focus leaves the\n * arrow keys with whatever was focused before. That is usually the ratio picker, where\n * an arrow quietly changes the ratio instead of nudging the crop.\n */\n cropBox.value?.focus()\n}\n\n/** A drag on the picture itself draws a new crop, rather than doing nothing. */\nfunction beginDraw(event: PointerEvent) {\n if (props.disabled || !ready.value || event.button !== 0) return\n\n const from = pointAt(event)\n crop.value = { x: from.x, y: from.y, width: 0, height: 0 }\n begin('se', event)\n}\n\nfunction onMove(event: PointerEvent) {\n const current = gesture.value\n if (!current) return\n\n const point = pointAt(event)\n\n if (current.handle === 'move') {\n setCrop(moveCrop(current.start, point.x - current.from.x, point.y - current.from.y, work.value))\n return\n }\n\n setCrop(\n resizeCrop(current.handle, point, current.start, work.value, {\n ratio: ratio.value,\n min: props.minSize,\n }),\n )\n}\n\nfunction endGesture(event: PointerEvent) {\n if (!gesture.value) return\n gesture.value = null\n const el = event.currentTarget as HTMLElement\n if (el.hasPointerCapture?.(event.pointerId)) el.releasePointerCapture(event.pointerId)\n}\n\n/** Arrows move the crop, shift and the arrows resize it — the drag, for a keyboard. */\nfunction onKeydown(event: KeyboardEvent) {\n if (props.disabled || !ready.value) return\n\n const step = event.altKey ? 1 : 10\n const dx = event.key === 'ArrowLeft' ? -step : event.key === 'ArrowRight' ? step : 0\n const dy = event.key === 'ArrowUp' ? -step : event.key === 'ArrowDown' ? step : 0\n if (!dx && !dy) return\n\n event.preventDefault()\n\n if (!event.shiftKey) {\n setCrop(moveCrop(crop.value, dx, dy, work.value))\n return\n }\n\n const corner = {\n x: crop.value.x + crop.value.width + dx,\n y: crop.value.y + crop.value.height + dy,\n }\n setCrop(\n resizeCrop('se', corner, crop.value, work.value, { ratio: ratio.value, min: props.minSize }),\n )\n}\n\n/* ------------------------------------------------------------------- turning --- */\n\nfunction turn(direction: 1 | -1) {\n if (props.disabled || !ready.value) return\n\n const before = work.value\n crop.value = turnCrop(crop.value, before, direction)\n rotation.value = (rotation.value + direction * 90 + 360) % 360\n touched.value = true\n\n /* The output keeps its shape, so a locked crop has to be laid out afresh. */\n if (ratio.value) crop.value = fitRatio(crop.value, ratio.value, work.value)\n emit('crop', rounded(crop.value))\n}\n\nfunction mirror(axis: 'x' | 'y') {\n if (props.disabled || !ready.value) return\n\n const flag = axis === 'x' ? flipX : flipY\n flag.value = !flag.value\n setCrop(mirrorCrop(crop.value, work.value, axis))\n}\n\n/* -------------------------------------------------------------------- output --- */\n\n/** What the result would be at its own size, once the caps have had their say. */\nconst fullSize = computed(() =>\n fitInside(crop.value.width, crop.value.height, props.maxWidth, props.maxHeight),\n)\n\n/**\n * The size the result will actually be written at: the crop's own pixels, unless the\n * reader has asked for fewer.\n *\n * The width is kept as a fraction rather than a whole number of pixels so that a height\n * typed into the other field comes back as exactly that height — rounded first, it would\n * read back a pixel out and look as though the field had refused what was typed.\n */\nconst output = computed(() => {\n const full = fullSize.value\n const width = clamp(widthOverride.value ?? full.width, 1, full.width)\n return {\n width: Math.max(1, Math.round(width)),\n height: Math.max(1, Math.round((width * full.height) / (full.width || 1))),\n }\n})\n\nfunction setOutputWidth(value: number | null | undefined) {\n widthOverride.value = value == null ? null : clamp(value, 1, fullSize.value.width)\n}\n\n/** The same size, asked for from the other side. */\nfunction setOutputHeight(value: number | null | undefined) {\n if (value == null) {\n widthOverride.value = null\n return\n }\n const full = fullSize.value\n widthOverride.value = clamp((value * full.width) / (full.height || 1), 1, full.width)\n}\n\n/**\n * The last part of the URL, which is where a name and an extension would be — taken\n * before the extension is looked for, or a host with a dot in it answers instead.\n */\nconst basename = computed(() =>\n decodeURIComponent(source.value.split(/[?#]/)[0]?.split('/').pop() ?? ''),\n)\n\n/** JPEG cannot be asked to remember transparency, so `auto` keeps a PNG a PNG. */\nconst type = computed(() => {\n if (props.format !== 'auto') return props.format\n\n /* What the file says it is, and failing that what it is called. */\n const given = typeof props.src === 'string' ? '' : props.src.type\n const guess = given || `image/${(basename.value.split('.').pop() ?? '').toLowerCase()}`\n if (guess === 'image/png' || guess === 'image/webp') return guess\n return 'image/jpeg'\n})\n\nconst extensions: Record<string, string> = {\n 'image/jpeg': 'jpg',\n 'image/png': 'png',\n 'image/webp': 'webp',\n}\n\n/** The name, with its extension put right: a PNG written as a JPEG is not a `.png`. */\nconst name = computed(() => {\n const given =\n props.fileName ??\n (typeof props.src !== 'string' && 'name' in props.src ? (props.src as File).name : '')\n const base = (given || basename.value || 'image').replace(/\\.[^./\\\\]+$/, '')\n return `${base || 'image'}.${extensions[type.value] ?? 'jpg'}`\n})\n\nfunction rounded(value: ImageEditorCrop): ImageEditorCrop {\n return {\n x: Math.round(value.x),\n y: Math.round(value.y),\n width: Math.round(value.width),\n height: Math.round(value.height),\n }\n}\n\n/*\n * Asked of the object rather than with `in` on the typed one: TypeScript knows every\n * context has a `filter` and narrows the negative branch away to `never`, which is true\n * of the type and not of Safari before 16.4.\n */\nfunction supportsFilter(context: CanvasRenderingContext2D) {\n return 'filter' in (context as unknown as Record<string, unknown>)\n}\n\nfunction encode(canvas: HTMLCanvasElement): Promise<Blob> {\n return new Promise((resolve, reject) => {\n if (typeof canvas.toBlob !== 'function') {\n reject(new Error('This browser cannot write a canvas out'))\n return\n }\n\n canvas.toBlob(\n (blob) => (blob ? resolve(blob) : reject(new Error('The picture could not be encoded'))),\n type.value,\n props.quality,\n )\n })\n}\n\n/**\n * Draws the result and hands it over. Exposed, so a page with a footer of its own can\n * ask for it without the editor carrying one.\n */\nasync function apply(): Promise<ImageEditorResult | undefined> {\n const el = image.value\n if (!ready.value || !el || busy.value) return undefined\n\n busy.value = true\n try {\n const canvas = document.createElement('canvas')\n canvas.width = output.value.width\n canvas.height = output.value.height\n\n const context = canvas.getContext('2d')\n if (!context) throw new Error('This browser gave no 2D context')\n\n context.imageSmoothingQuality = 'high'\n\n /*\n * The adjustments ride along with the drawing, so the picture is still sampled once.\n * Where the canvas has never heard of `filter` — Safari before 16.4 — it is not an\n * error and not a refusal: the same arithmetic is done over the pixels afterwards,\n * which is slower and gives the same answer. Silently writing an unadjusted file is\n * the one outcome worth any amount of code to avoid.\n */\n const byHand = Boolean(filter.value) && !supportsFilter(context)\n if (filter.value && !byHand) context.filter = filter.value\n\n /* Transparency turns black in a format that has none, which reads as a bug. */\n if (type.value === 'image/jpeg') {\n context.fillStyle = props.background\n context.fillRect(0, 0, canvas.width, canvas.height)\n }\n\n /*\n * Two transforms, composed: the picture's own pixels onto the turned picture, and the\n * crop out of that onto the canvas. Written as one so the source is sampled once.\n */\n const zoom = output.value.width / (crop.value.width || 1)\n context.setTransform(zoom, 0, 0, zoom, -crop.value.x * zoom, -crop.value.y * zoom)\n context.translate(work.value.width / 2, work.value.height / 2)\n context.scale(flipX.value ? -1 : 1, flipY.value ? -1 : 1)\n context.rotate((rotation.value * Math.PI) / 180)\n context.drawImage(\n el,\n -natural.value.width / 2,\n -natural.value.height / 2,\n natural.value.width,\n natural.value.height,\n )\n\n if (byHand) {\n /* Reading the pixels back needs the same untainted canvas that writing one does. */\n context.setTransform(1, 0, 0, 1, 0, 0)\n const pixels = context.getImageData(0, 0, canvas.width, canvas.height)\n applyAdjustments(pixels.data, adjust.value)\n context.putImageData(pixels, 0, 0)\n }\n\n const blob = await encode(canvas)\n const result: ImageEditorResult = {\n blob,\n file: new File([blob], name.value, { type: blob.type || type.value }),\n type: blob.type || type.value,\n width: canvas.width,\n height: canvas.height,\n crop: rounded(crop.value),\n rotation: rotation.value,\n flipX: flipX.value,\n flipY: flipY.value,\n adjustments: { ...adjust.value },\n filter: filter.value,\n }\n\n emit('save', result)\n return result\n } catch (error) {\n emit('error', error)\n return undefined\n } finally {\n busy.value = false\n }\n}\n\nconst dirty = computed(() => touched.value || widthOverride.value !== null)\n\ndefineExpose({\n /** Draws the result, emits `save` and answers with it. */\n apply,\n /** Back to the whole picture, the right way up. */\n reset: () => reset(),\n crop: computed(() => rounded(crop.value)),\n})\n</script>\n\n<template>\n <div class=\"wx-image-editor\" :class=\"{ 'is-disabled': disabled, 'is-busy': busy }\">\n <div class=\"wx-image-editor__stage\">\n <!--\n The room the picture is fitted into, held a little inside the stage: the grips\n stand half outside the picture, and with the picture against the edge of a box\n that clips, that half is cut off — and, with it, half of every corner's target.\n -->\n <div ref=\"stage\" class=\"wx-image-editor__room\">\n <div\n v-show=\"ready\"\n ref=\"frame\"\n class=\"wx-image-editor__frame\"\n :style=\"frameStyle\"\n @pointerdown=\"beginDraw\"\n @pointermove=\"onMove\"\n @pointerup=\"endGesture\"\n @pointercancel=\"endGesture\"\n >\n <!--\n What is clipped: the turned picture, which is wider than its frame whenever it\n is on its side, and the shadow that darkens everything outside the crop — one\n shadow big enough to reach every corner, rather than four boxes around the crop\n that would have to be kept in step with it.\n\n The crop box itself is deliberately not in here. Clipping takes the pointer with\n it, and the grips straddle the edge on purpose: inside a clipped box the outer\n half of every corner grip is dead, which is half the target at the four places\n where aim matters most — and a drag that misses lands on the crop underneath and\n silently does nothing.\n -->\n <div class=\"wx-image-editor__view\">\n <img\n ref=\"image\"\n class=\"wx-image-editor__picture\"\n :src=\"source\"\n :crossorigin=\"crossOrigin || undefined\"\n :style=\"imageStyle\"\n alt=\"\"\n draggable=\"false\"\n @load=\"onLoad\"\n @error=\"onError\"\n />\n\n <span class=\"wx-image-editor__shade\" :style=\"cropStyle\" aria-hidden=\"true\" />\n </div>\n\n <div\n ref=\"cropBox\"\n class=\"wx-image-editor__crop\"\n :class=\"{ 'is-dragging': gesture !== null }\"\n :style=\"cropStyle\"\n role=\"group\"\n :aria-label=\"cropLabel\"\n :tabindex=\"disabled ? -1 : 0\"\n @pointerdown.stop=\"begin('move', $event)\"\n @pointermove=\"onMove\"\n @pointerup=\"endGesture\"\n @pointercancel=\"endGesture\"\n @keydown=\"onKeydown\"\n >\n <span class=\"wx-image-editor__thirds\" aria-hidden=\"true\" />\n <span\n v-for=\"handle in handles\"\n :key=\"handle\"\n class=\"wx-image-editor__handle\"\n :class=\"`is-${handle}`\"\n aria-hidden=\"true\"\n @pointerdown.stop=\"begin(handle, $event)\"\n @pointermove=\"onMove\"\n @pointerup=\"endGesture\"\n @pointercancel=\"endGesture\"\n />\n </div>\n </div>\n </div>\n\n <p v-if=\"failed\" class=\"wx-image-editor__failed\">\n <wx-icon name=\"warning\" size=\"lg\" />\n {{ errorText }}\n </p>\n </div>\n\n <div class=\"wx-image-editor__toolbar\">\n <wx-segmented\n v-if=\"options.length > 1\"\n :model-value=\"chosen\"\n class=\"wx-image-editor__ratios\"\n size=\"sm\"\n :aria-label=\"ratioLabel\"\n :disabled=\"disabled || !ready\"\n :options=\"options.map((option) => ({ label: option.label, value: option.value }))\"\n @update:model-value=\"chooseRatio($event)\"\n />\n\n <span v-if=\"rotatable || flippable\" class=\"wx-image-editor__tools\">\n <wx-action\n v-if=\"rotatable\"\n icon=\"rotate-left\"\n size=\"sm\"\n :title=\"rotateLeftLabel\"\n :disabled=\"disabled || !ready\"\n @click=\"turn(-1)\"\n />\n <wx-action\n v-if=\"rotatable\"\n icon=\"rotate-right\"\n size=\"sm\"\n :title=\"rotateRightLabel\"\n :disabled=\"disabled || !ready\"\n @click=\"turn(1)\"\n />\n <wx-action\n v-if=\"flippable\"\n icon=\"flip-horizontal\"\n size=\"sm\"\n :title=\"flipHorizontalLabel\"\n :disabled=\"disabled || !ready\"\n @click=\"mirror('x')\"\n />\n <wx-action\n v-if=\"flippable\"\n icon=\"flip-vertical\"\n size=\"sm\"\n :title=\"flipVerticalLabel\"\n :disabled=\"disabled || !ready\"\n @click=\"mirror('y')\"\n />\n </span>\n\n <!--\n The adjustments live behind one button rather than in the toolbar: three sliders\n and a switch are wider than everything else put together, and they are reached on\n purpose — nobody arrives at a cropper meaning to change the contrast.\n -->\n <wx-popover v-if=\"filters\" side=\"bottom\" align=\"start\" :width=\"260\" :title=\"adjustLabel\">\n <template #trigger>\n <wx-action\n class=\"wx-image-editor__adjust\"\n icon=\"sliders\"\n size=\"sm\"\n :title=\"adjustLabel\"\n :tone=\"touchedFilters ? 'primary' : undefined\"\n :disabled=\"disabled || !ready\"\n />\n </template>\n\n <div class=\"wx-image-editor__sliders\">\n <label v-for=\"slider in sliders\" :key=\"slider.key\" class=\"wx-image-editor__slider\">\n <span class=\"wx-image-editor__slider-name\">\n {{ slider.label }}\n <span class=\"wx-image-editor__slider-value\">{{ adjust[slider.key] }}%</span>\n </span>\n <wx-slider\n :model-value=\"adjust[slider.key]\"\n :min=\"0\"\n :max=\"200\"\n :step=\"1\"\n size=\"sm\"\n :disabled=\"slider.key === 'saturation' && adjust.mono\"\n :aria-label=\"slider.label\"\n @update:model-value=\"setAdjustment(slider.key, $event)\"\n />\n </label>\n\n <wx-switch v-model=\"adjust.mono\" :label=\"monoLabel\" size=\"sm\" @change=\"adjusted\" />\n </div>\n </wx-popover>\n\n <!--\n Named, and both sides of it: two numbers with nothing to say what they measure\n read as the crop, the picture or the panel with equal ease, and a lone width\n leaves the reader to work out what happened to the height.\n -->\n <span class=\"wx-image-editor__size\">\n <wx-tooltip :content=\"outputHint\">\n <span class=\"wx-image-editor__caption\">{{ outputLabel }}</span>\n </wx-tooltip>\n\n <wx-input-number\n v-if=\"resizable\"\n :model-value=\"output.width\"\n class=\"wx-image-editor__field\"\n size=\"sm\"\n :min=\"1\"\n :max=\"fullSize.width\"\n :controls=\"false\"\n :aria-label=\"widthLabel\"\n :disabled=\"disabled || !ready\"\n @update:model-value=\"setOutputWidth\"\n />\n <span v-else class=\"wx-image-editor__number\">{{ output.width }}</span>\n\n <span class=\"wx-image-editor__times\" aria-hidden=\"true\">×</span>\n\n <wx-input-number\n v-if=\"resizable\"\n :model-value=\"output.height\"\n class=\"wx-image-editor__field\"\n size=\"sm\"\n :min=\"1\"\n :max=\"fullSize.height\"\n :controls=\"false\"\n :aria-label=\"heightLabel\"\n :disabled=\"disabled || !ready\"\n @update:model-value=\"setOutputHeight\"\n />\n <span v-else class=\"wx-image-editor__number\">{{ output.height }}</span>\n\n <span class=\"wx-image-editor__unit\">px</span>\n </span>\n\n <wx-button\n class=\"wx-image-editor__reset\"\n size=\"sm\"\n variant=\"text\"\n :disabled=\"disabled || !ready || !dirty\"\n @click=\"reset()\"\n >\n {{ resetLabel }}\n </wx-button>\n </div>\n\n <div v-if=\"footer\" class=\"wx-image-editor__footer\">\n <wx-button variant=\"outline\" :disabled=\"busy\" @click=\"emit('cancel')\">\n {{ cancelLabel }}\n </wx-button>\n <wx-button type=\"primary\" :loading=\"busy\" :disabled=\"disabled || !ready\" @click=\"apply()\">\n {{ saveLabel }}\n </wx-button>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-image-editor {\n /* The box a grip is caught by. Half of it hangs outside the picture, so it sets the\n * margin the picture is held inside the stage by as well. */\n --wx-image-editor-grip: 16px;\n /* The chequer behind a transparent picture: a hint that something is see-through,\n * not a pattern to be read. Loud in a dark theme otherwise. */\n --wx-image-editor-check: color-mix(in srgb, var(--wx-border-muted) 45%, transparent);\n\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-10);\n min-width: 0;\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n font-size: var(--wx-font-size-sm);\n}\n\n/* A finger is not a mouse pointer: the same drawing, a target twice the size. */\n@media (pointer: coarse) {\n .wx-image-editor {\n --wx-image-editor-grip: 30px;\n }\n}\n\n.wx-image-editor.is-disabled {\n opacity: 0.6;\n}\n\n/*\n * The stage is the room the picture is fitted into, and it is a checkerboard because a\n * transparent PNG over a flat colour is a picture you cannot see the edges of.\n */\n.wx-image-editor__stage {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n min-height: 240px;\n height: var(--wx-image-editor-height, 42vh);\n background-color: var(--wx-bg-body);\n background-image:\n linear-gradient(45deg, var(--wx-image-editor-check) 25%, transparent 25%),\n linear-gradient(-45deg, var(--wx-image-editor-check) 25%, transparent 25%),\n linear-gradient(45deg, transparent 75%, var(--wx-image-editor-check) 75%),\n linear-gradient(-45deg, transparent 75%, var(--wx-image-editor-check) 75%);\n background-position:\n 0 0,\n 0 8px,\n 8px -8px,\n -8px 0;\n background-size: 16px 16px;\n border: 1px solid var(--wx-border-muted);\n border-radius: var(--wx-radius-md);\n user-select: none;\n touch-action: none;\n}\n\n/*\n * Held inside the stage by the half a grip that stands outside the picture. `overflow`\n * clips at the padding box, so what hangs into this margin is drawn and can be clicked;\n * what leaves the stage altogether still goes.\n */\n.wx-image-editor__room {\n position: absolute;\n inset: calc(var(--wx-image-editor-grip) / 2);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* Never shrunk: its size is the fitted picture, and a shrunk frame is a stretched one. */\n.wx-image-editor__frame {\n position: relative;\n flex: none;\n cursor: crosshair;\n}\n\n/* Everything that has to be cut off at the edge of the picture, and nothing else. */\n.wx-image-editor__view {\n position: absolute;\n inset: 0;\n overflow: hidden;\n pointer-events: none;\n}\n\n.wx-image-editor__picture {\n position: absolute;\n top: 50%;\n left: 50%;\n transform-origin: center;\n pointer-events: none;\n}\n\n/* Big enough to reach the corner of any stage, and cut off at the picture's edge. */\n.wx-image-editor__shade {\n position: absolute;\n box-shadow: 0 0 0 9999px rgb(0 0 0 / 45%);\n}\n\n.wx-image-editor__crop {\n position: absolute;\n box-sizing: border-box;\n border: 1px solid var(--wx-color-primary);\n cursor: move;\n outline-offset: 2px;\n}\n\n.wx-image-editor__crop:focus-visible {\n outline: 2px solid var(--wx-color-primary);\n}\n\n/* The thirds, which is what a crop is judged against. */\n.wx-image-editor__thirds {\n position: absolute;\n inset: 0;\n background-image:\n linear-gradient(\n to right,\n transparent 33.33%,\n rgb(255 255 255 / 35%) 33.33% 33.5%,\n transparent 33.5%\n ),\n linear-gradient(\n to right,\n transparent 66.5%,\n rgb(255 255 255 / 35%) 66.5% 66.67%,\n transparent 66.67%\n ),\n linear-gradient(\n to bottom,\n transparent 33.33%,\n rgb(255 255 255 / 35%) 33.33% 33.5%,\n transparent 33.5%\n ),\n linear-gradient(\n to bottom,\n transparent 66.5%,\n rgb(255 255 255 / 35%) 66.5% 66.67%,\n transparent 66.67%\n );\n opacity: 0;\n transition: opacity var(--wx-duration-fast) var(--wx-easing-standard);\n pointer-events: none;\n}\n\n.wx-image-editor__crop:hover .wx-image-editor__thirds,\n.wx-image-editor__crop.is-dragging .wx-image-editor__thirds {\n opacity: 1;\n}\n\n/*\n * The grips are drawn small and hit large: the box around each one is twice the square\n * that is visible, so a corner can be caught without taking aim at four pixels.\n */\n.wx-image-editor__handle {\n position: absolute;\n width: var(--wx-image-editor-grip);\n height: var(--wx-image-editor-grip);\n background: transparent;\n}\n\n.wx-image-editor__handle::after {\n position: absolute;\n inset: calc(var(--wx-image-editor-grip) / 2 - 3px);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-color-primary);\n border-radius: 1px;\n content: '';\n}\n\n.wx-image-editor__handle.is-n,\n.wx-image-editor__handle.is-s {\n left: 50%;\n margin-left: calc(var(--wx-image-editor-grip) / -2);\n cursor: ns-resize;\n}\n\n.wx-image-editor__handle.is-e,\n.wx-image-editor__handle.is-w {\n top: 50%;\n margin-top: calc(var(--wx-image-editor-grip) / -2);\n cursor: ew-resize;\n}\n\n.wx-image-editor__handle.is-n,\n.wx-image-editor__handle.is-ne,\n.wx-image-editor__handle.is-nw {\n top: calc(var(--wx-image-editor-grip) / -2);\n}\n\n.wx-image-editor__handle.is-s,\n.wx-image-editor__handle.is-se,\n.wx-image-editor__handle.is-sw {\n bottom: calc(var(--wx-image-editor-grip) / -2);\n}\n\n.wx-image-editor__handle.is-w,\n.wx-image-editor__handle.is-nw,\n.wx-image-editor__handle.is-sw {\n left: calc(var(--wx-image-editor-grip) / -2);\n}\n\n.wx-image-editor__handle.is-e,\n.wx-image-editor__handle.is-ne,\n.wx-image-editor__handle.is-se {\n right: calc(var(--wx-image-editor-grip) / -2);\n}\n\n.wx-image-editor__handle.is-nw,\n.wx-image-editor__handle.is-se {\n cursor: nwse-resize;\n}\n\n.wx-image-editor__handle.is-ne,\n.wx-image-editor__handle.is-sw {\n cursor: nesw-resize;\n}\n\n.wx-image-editor__failed {\n display: flex;\n gap: var(--wx-space-8);\n align-items: center;\n margin: 0;\n color: var(--wx-text-muted);\n}\n\n.wx-image-editor__toolbar {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-8);\n align-items: center;\n}\n\n.wx-image-editor__ratios {\n min-width: 0;\n}\n\n.wx-image-editor__tools {\n display: flex;\n gap: 2px;\n align-items: center;\n}\n\n.wx-image-editor__sliders {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n}\n\n.wx-image-editor__slider {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n}\n\n.wx-image-editor__slider-name {\n display: flex;\n justify-content: space-between;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n}\n\n.wx-image-editor__slider-value {\n color: var(--wx-text-default);\n font-variant-numeric: tabular-nums;\n}\n\n/* Pushed to the end, with the reset after it — the two things that are not the picture. */\n.wx-image-editor__size {\n display: flex;\n gap: var(--wx-space-4);\n align-items: center;\n margin-inline-start: auto;\n color: var(--wx-text-muted);\n font-variant-numeric: tabular-nums;\n}\n\n/* Wide enough for five digits — a camera's four, and a scan's five. */\n.wx-image-editor__field {\n width: 74px;\n}\n\n.wx-image-editor__caption {\n /* Dotted, the way a word with something behind it is written everywhere else. */\n border-bottom: 1px dotted var(--wx-border-default);\n cursor: help;\n}\n\n.wx-image-editor__number {\n color: var(--wx-text-default);\n}\n\n.wx-image-editor__times,\n.wx-image-editor__unit {\n color: var(--wx-text-placeholder);\n}\n\n.wx-image-editor__footer {\n display: flex;\n gap: var(--wx-space-8);\n justify-content: flex-end;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-image-editor__thirds {\n transition: none;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { provide, ref, shallowRef, useAttrs } from 'vue'\nimport WxLightbox from '../Lightbox/Lightbox.vue'\nimport { imageGroupKey, type ImageGroupEntry } from '../../composables/useImageGroup'\nimport type { LightboxItem } from '../Lightbox/types'\nimport type { ImageGroupProps } from './types'\n\ndefineOptions({ name: 'WxImageGroup', inheritAttrs: false })\n\n/*\n * Every `<wx-image preview>` inside opens one gallery of all of them.\n *\n * The group is a component rather than a shared name on each picture: two cards on one\n * screen that both call their pictures \"photos\" would otherwise become one gallery.\n *\n * The lightbox's props are not declared here. They ride through on `$attrs`: a wrapper that\n * re-declares a child's booleans turns every one the caller left alone into `false`, and\n * the strip's \"on when there is more than one\" would be lost on the way.\n */\nwithDefaults(defineProps<ImageGroupProps>(), { tag: 'div' })\n\n/* Functions, not `computed`: `attrs` is not reactive, and a cached split would go stale. */\nconst attrs = useAttrs()\nconst rootAttrs = () => ({ class: attrs.class, style: attrs.style })\nconst lightboxAttrs = () =>\n Object.fromEntries(Object.entries(attrs).filter(([name]) => name !== 'class' && name !== 'style'))\n\nconst entries = new Set<ImageGroupEntry>()\n\nconst open = ref(false)\nconst index = ref(0)\nconst items = shallowRef<LightboxItem[]>([])\n\n/*\n * Order is the page's, read when the gallery opens: pictures are added, removed and\n * reordered by whatever renders them, and the page is the one place that is never stale.\n */\nfunction ordered() {\n return [...entries].sort((a, b) => {\n const first = a.el()\n const second = b.el()\n if (!first || !second) return 0\n return first.compareDocumentPosition(second) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1\n })\n}\n\nprovide(imageGroupKey, {\n register(entry) {\n entries.add(entry)\n return () => entries.delete(entry)\n },\n open(entry) {\n const list = ordered()\n items.value = list.map((one) => one.item())\n index.value = Math.max(0, list.indexOf(entry))\n open.value = true\n },\n})\n</script>\n\n<template>\n <component :is=\"tag\" class=\"wx-image-group\" v-bind=\"rootAttrs()\">\n <slot />\n <wx-lightbox\n v-bind=\"lightboxAttrs()\"\n v-model:open=\"open\"\n v-model:index=\"index\"\n :items=\"items\"\n />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useSlots } from 'vue'\nimport type { IndicatorProps } from './types'\n\ndefineOptions({ name: 'WxIndicator' })\n\nconst props = withDefaults(defineProps<IndicatorProps>(), {\n value: undefined,\n max: 99,\n dot: false,\n showZero: false,\n placement: 'top-right',\n offset: undefined,\n type: 'danger',\n hidden: false,\n label: undefined,\n})\n\nconst slots = useSlots()\n\n/** Without a wrapped element the mark is the whole component — a count in a menu row. */\nconst isAttached = computed(() => Boolean(slots.default))\n\nconst text = computed(() => {\n if (props.dot) return ''\n if (typeof props.value === 'number') {\n return props.value > props.max ? `${props.max}+` : String(props.value)\n }\n return props.value ?? ''\n})\n\nconst visible = computed(() => {\n if (props.hidden) return false\n if (props.dot) return true\n if (props.value === 0) return props.showZero\n return text.value !== ''\n})\n\nconst markClasses = computed(() => [\n 'wx-indicator__mark',\n `wx-indicator__mark--${props.type}`,\n {\n 'wx-indicator__mark--dot': props.dot,\n 'wx-indicator__mark--attached': isAttached.value,\n [`wx-indicator__mark--${props.placement}`]: isAttached.value,\n },\n])\n\nconst markStyle = computed(() => {\n if (!props.offset) return undefined\n const [x, y] = props.offset\n return { '--wx-indicator-offset-x': `${x}px`, '--wx-indicator-offset-y': `${y}px` }\n})\n</script>\n\n<template>\n <span class=\"wx-indicator\" :class=\"{ 'wx-indicator--attached': isAttached }\">\n <slot />\n <span v-if=\"visible\" :class=\"markClasses\" :style=\"markStyle\" :aria-label=\"label\">\n <slot name=\"mark\">{{ text }}</slot>\n </span>\n </span>\n</template>\n\n<style scoped>\n.wx-indicator {\n display: inline-flex;\n vertical-align: middle;\n}\n\n.wx-indicator--attached {\n position: relative;\n}\n\n.wx-indicator__mark {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n border-radius: var(--wx-radius-full);\n color: var(--wx-indicator-fg);\n font-family: var(--wx-font-family-sans);\n font-size: var(--wx-font-size-xs);\n font-weight: var(--wx-font-weight-semibold);\n line-height: 1;\n white-space: nowrap;\n background: var(--wx-indicator-bg);\n}\n\n/*\n * The ring is the surface behind the mark, not a fixed white — a counter pinned to a\n * dark sidebar icon needs the sidebar's colour, which callers set on the wrapper.\n */\n.wx-indicator__mark--attached {\n position: absolute;\n z-index: 1;\n border: 2px solid var(--wx-indicator-ring, var(--wx-bg-surface));\n height: 20px;\n min-width: 20px;\n pointer-events: none;\n}\n\n.wx-indicator__mark--top-right {\n top: 0;\n right: 0;\n transform: translate(\n calc(50% + var(--wx-indicator-offset-x, 0px)),\n calc(-50% + var(--wx-indicator-offset-y, 0px))\n );\n}\n\n.wx-indicator__mark--top-left {\n top: 0;\n left: 0;\n transform: translate(\n calc(-50% + var(--wx-indicator-offset-x, 0px)),\n calc(-50% + var(--wx-indicator-offset-y, 0px))\n );\n}\n\n.wx-indicator__mark--bottom-right {\n bottom: 0;\n right: 0;\n transform: translate(\n calc(50% + var(--wx-indicator-offset-x, 0px)),\n calc(50% + var(--wx-indicator-offset-y, 0px))\n );\n}\n\n.wx-indicator__mark--bottom-left {\n bottom: 0;\n left: 0;\n transform: translate(\n calc(-50% + var(--wx-indicator-offset-x, 0px)),\n calc(50% + var(--wx-indicator-offset-y, 0px))\n );\n}\n\n.wx-indicator__mark--dot {\n min-width: 10px;\n width: 10px;\n height: 10px;\n padding: 0;\n}\n\n.wx-indicator__mark--dot.wx-indicator__mark--attached {\n min-width: 12px;\n width: 12px;\n height: 12px;\n}\n\n/* colours */\n.wx-indicator__mark--danger {\n --wx-indicator-bg: var(--wx-color-danger);\n --wx-indicator-fg: var(--wx-color-danger-contrast);\n}\n\n.wx-indicator__mark--primary {\n --wx-indicator-bg: var(--wx-color-primary);\n --wx-indicator-fg: var(--wx-color-primary-contrast);\n}\n\n.wx-indicator__mark--success {\n --wx-indicator-bg: var(--wx-color-success);\n --wx-indicator-fg: var(--wx-color-success-contrast);\n}\n\n.wx-indicator__mark--warning {\n --wx-indicator-bg: var(--wx-color-warning);\n --wx-indicator-fg: var(--wx-color-warning-contrast);\n}\n\n.wx-indicator__mark--info {\n --wx-indicator-bg: var(--wx-color-info);\n --wx-indicator-fg: var(--wx-color-info-contrast);\n}\n\n.wx-indicator__mark--neutral {\n --wx-indicator-bg: var(--wx-bg-fill-hover);\n --wx-indicator-fg: var(--wx-text-default);\n}\n</style>\n","var an = Object.defineProperty;\nvar Pe = Object.getOwnPropertySymbols;\nvar yt = Object.prototype.hasOwnProperty, wt = Object.prototype.propertyIsEnumerable;\nvar bt = (t, e, n) => e in t ? an(t, e, { enumerable: !0, configurable: !0, writable: !0, value: n }) : t[e] = n, fe = (t, e) => {\n for (var n in e || (e = {}))\n yt.call(e, n) && bt(t, n, e[n]);\n if (Pe)\n for (var n of Pe(e))\n wt.call(e, n) && bt(t, n, e[n]);\n return t;\n};\nvar $e = (t, e) => {\n var n = {};\n for (var o in t)\n yt.call(t, o) && e.indexOf(o) < 0 && (n[o] = t[o]);\n if (t != null && Pe)\n for (var o of Pe(t))\n e.indexOf(o) < 0 && wt.call(t, o) && (n[o] = t[o]);\n return n;\n};\nimport { getCurrentInstance as dt, unref as U, watch as ln, onUnmounted as sn, onMounted as un, nextTick as kt, isRef as qe, defineComponent as cn, computed as Et, toRefs as fn, ref as dn, reactive as hn, h as pn, isProxy as gn } from \"vue\";\nconst Ht = \"[vue-draggable-plus]: \";\nfunction mn(t) {\n console.warn(Ht + t);\n}\nfunction vn(t) {\n console.error(Ht + t);\n}\nfunction St(t, e, n) {\n return n >= 0 && n < t.length && t.splice(n, 0, t.splice(e, 1)[0]), t;\n}\nfunction bn(t) {\n return t.replace(/-(\\w)/g, (e, n) => n ? n.toUpperCase() : \"\");\n}\nfunction yn(t) {\n return Object.keys(t).reduce((e, n) => (typeof t[n] != \"undefined\" && (e[bn(n)] = t[n]), e), {});\n}\nfunction Dt(t, e) {\n return Array.isArray(t) && t.splice(e, 1), t;\n}\nfunction _t(t, e, n) {\n return Array.isArray(t) && t.splice(e, 0, n), t;\n}\nfunction wn(t) {\n return typeof t == \"undefined\";\n}\nfunction En(t) {\n return typeof t == \"string\";\n}\nfunction Tt(t, e, n) {\n const o = t.children[n];\n t.insertBefore(e, o);\n}\nfunction Ke(t) {\n t.parentNode && t.parentNode.removeChild(t);\n}\nfunction Sn(t, e = document) {\n var o;\n let n = null;\n return typeof (e == null ? void 0 : e.querySelector) == \"function\" ? n = (o = e == null ? void 0 : e.querySelector) == null ? void 0 : o.call(e, t) : n = document.querySelector(t), n || mn(`Element not found: ${t}`), n;\n}\nfunction Dn(t, e, n = null) {\n return function(...o) {\n return t.apply(n, o), e.apply(n, o);\n };\n}\nfunction _n(t, e) {\n const n = fe({}, t);\n return Object.keys(e).forEach((o) => {\n n[o] ? n[o] = Dn(t[o], e[o]) : n[o] = e[o];\n }), n;\n}\nfunction Tn(t) {\n return t instanceof HTMLElement;\n}\nfunction Ct(t, e) {\n Object.keys(t).forEach((n) => {\n e(n, t[n]);\n });\n}\nfunction Cn(t) {\n return t.charCodeAt(0) === 111 && t.charCodeAt(1) === 110 && (t.charCodeAt(2) > 122 || t.charCodeAt(2) < 97);\n}\nconst On = Object.assign;\n/**!\n * Sortable 1.15.2\n * @author\tRubaXa <trash@rubaxa.org>\n * @author\towenm <owen23355@gmail.com>\n * @license MIT\n */\nfunction Ot(t, e) {\n var n = Object.keys(t);\n if (Object.getOwnPropertySymbols) {\n var o = Object.getOwnPropertySymbols(t);\n e && (o = o.filter(function(r) {\n return Object.getOwnPropertyDescriptor(t, r).enumerable;\n })), n.push.apply(n, o);\n }\n return n;\n}\nfunction ne(t) {\n for (var e = 1; e < arguments.length; e++) {\n var n = arguments[e] != null ? arguments[e] : {};\n e % 2 ? Ot(Object(n), !0).forEach(function(o) {\n In(t, o, n[o]);\n }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(t, Object.getOwnPropertyDescriptors(n)) : Ot(Object(n)).forEach(function(o) {\n Object.defineProperty(t, o, Object.getOwnPropertyDescriptor(n, o));\n });\n }\n return t;\n}\nfunction Ye(t) {\n \"@babel/helpers - typeof\";\n return typeof Symbol == \"function\" && typeof Symbol.iterator == \"symbol\" ? Ye = function(e) {\n return typeof e;\n } : Ye = function(e) {\n return e && typeof Symbol == \"function\" && e.constructor === Symbol && e !== Symbol.prototype ? \"symbol\" : typeof e;\n }, Ye(t);\n}\nfunction In(t, e, n) {\n return e in t ? Object.defineProperty(t, e, {\n value: n,\n enumerable: !0,\n configurable: !0,\n writable: !0\n }) : t[e] = n, t;\n}\nfunction ie() {\n return ie = Object.assign || function(t) {\n for (var e = 1; e < arguments.length; e++) {\n var n = arguments[e];\n for (var o in n)\n Object.prototype.hasOwnProperty.call(n, o) && (t[o] = n[o]);\n }\n return t;\n }, ie.apply(this, arguments);\n}\nfunction An(t, e) {\n if (t == null)\n return {};\n var n = {}, o = Object.keys(t), r, i;\n for (i = 0; i < o.length; i++)\n r = o[i], !(e.indexOf(r) >= 0) && (n[r] = t[r]);\n return n;\n}\nfunction xn(t, e) {\n if (t == null)\n return {};\n var n = An(t, e), o, r;\n if (Object.getOwnPropertySymbols) {\n var i = Object.getOwnPropertySymbols(t);\n for (r = 0; r < i.length; r++)\n o = i[r], !(e.indexOf(o) >= 0) && Object.prototype.propertyIsEnumerable.call(t, o) && (n[o] = t[o]);\n }\n return n;\n}\nvar Nn = \"1.15.2\";\nfunction re(t) {\n if (typeof window != \"undefined\" && window.navigator)\n return !!/* @__PURE__ */ navigator.userAgent.match(t);\n}\nvar ae = re(/(?:Trident.*rv[ :]?11\\.|msie|iemobile|Windows Phone)/i), xe = re(/Edge/i), It = re(/firefox/i), Te = re(/safari/i) && !re(/chrome/i) && !re(/android/i), Lt = re(/iP(ad|od|hone)/i), Wt = re(/chrome/i) && re(/android/i), Gt = {\n capture: !1,\n passive: !1\n};\nfunction S(t, e, n) {\n t.addEventListener(e, n, !ae && Gt);\n}\nfunction E(t, e, n) {\n t.removeEventListener(e, n, !ae && Gt);\n}\nfunction We(t, e) {\n if (e) {\n if (e[0] === \">\" && (e = e.substring(1)), t)\n try {\n if (t.matches)\n return t.matches(e);\n if (t.msMatchesSelector)\n return t.msMatchesSelector(e);\n if (t.webkitMatchesSelector)\n return t.webkitMatchesSelector(e);\n } catch (n) {\n return !1;\n }\n return !1;\n }\n}\nfunction Pn(t) {\n return t.host && t !== document && t.host.nodeType ? t.host : t.parentNode;\n}\nfunction Q(t, e, n, o) {\n if (t) {\n n = n || document;\n do {\n if (e != null && (e[0] === \">\" ? t.parentNode === n && We(t, e) : We(t, e)) || o && t === n)\n return t;\n if (t === n)\n break;\n } while (t = Pn(t));\n }\n return null;\n}\nvar At = /\\s+/g;\nfunction V(t, e, n) {\n if (t && e)\n if (t.classList)\n t.classList[n ? \"add\" : \"remove\"](e);\n else {\n var o = (\" \" + t.className + \" \").replace(At, \" \").replace(\" \" + e + \" \", \" \");\n t.className = (o + (n ? \" \" + e : \"\")).replace(At, \" \");\n }\n}\nfunction h(t, e, n) {\n var o = t && t.style;\n if (o) {\n if (n === void 0)\n return document.defaultView && document.defaultView.getComputedStyle ? n = document.defaultView.getComputedStyle(t, \"\") : t.currentStyle && (n = t.currentStyle), e === void 0 ? n : n[e];\n !(e in o) && e.indexOf(\"webkit\") === -1 && (e = \"-webkit-\" + e), o[e] = n + (typeof n == \"string\" ? \"\" : \"px\");\n }\n}\nfunction ye(t, e) {\n var n = \"\";\n if (typeof t == \"string\")\n n = t;\n else\n do {\n var o = h(t, \"transform\");\n o && o !== \"none\" && (n = o + \" \" + n);\n } while (!e && (t = t.parentNode));\n var r = window.DOMMatrix || window.WebKitCSSMatrix || window.CSSMatrix || window.MSCSSMatrix;\n return r && new r(n);\n}\nfunction jt(t, e, n) {\n if (t) {\n var o = t.getElementsByTagName(e), r = 0, i = o.length;\n if (n)\n for (; r < i; r++)\n n(o[r], r);\n return o;\n }\n return [];\n}\nfunction te() {\n var t = document.scrollingElement;\n return t || document.documentElement;\n}\nfunction P(t, e, n, o, r) {\n if (!(!t.getBoundingClientRect && t !== window)) {\n var i, a, l, s, u, d, f;\n if (t !== window && t.parentNode && t !== te() ? (i = t.getBoundingClientRect(), a = i.top, l = i.left, s = i.bottom, u = i.right, d = i.height, f = i.width) : (a = 0, l = 0, s = window.innerHeight, u = window.innerWidth, d = window.innerHeight, f = window.innerWidth), (e || n) && t !== window && (r = r || t.parentNode, !ae))\n do\n if (r && r.getBoundingClientRect && (h(r, \"transform\") !== \"none\" || n && h(r, \"position\") !== \"static\")) {\n var m = r.getBoundingClientRect();\n a -= m.top + parseInt(h(r, \"border-top-width\")), l -= m.left + parseInt(h(r, \"border-left-width\")), s = a + i.height, u = l + i.width;\n break;\n }\n while (r = r.parentNode);\n if (o && t !== window) {\n var y = ye(r || t), b = y && y.a, w = y && y.d;\n y && (a /= w, l /= b, f /= b, d /= w, s = a + d, u = l + f);\n }\n return {\n top: a,\n left: l,\n bottom: s,\n right: u,\n width: f,\n height: d\n };\n }\n}\nfunction xt(t, e, n) {\n for (var o = ce(t, !0), r = P(t)[e]; o; ) {\n var i = P(o)[n], a = void 0;\n if (a = r >= i, !a)\n return o;\n if (o === te())\n break;\n o = ce(o, !1);\n }\n return !1;\n}\nfunction we(t, e, n, o) {\n for (var r = 0, i = 0, a = t.children; i < a.length; ) {\n if (a[i].style.display !== \"none\" && a[i] !== p.ghost && (o || a[i] !== p.dragged) && Q(a[i], n.draggable, t, !1)) {\n if (r === e)\n return a[i];\n r++;\n }\n i++;\n }\n return null;\n}\nfunction ht(t, e) {\n for (var n = t.lastElementChild; n && (n === p.ghost || h(n, \"display\") === \"none\" || e && !We(n, e)); )\n n = n.previousElementSibling;\n return n || null;\n}\nfunction J(t, e) {\n var n = 0;\n if (!t || !t.parentNode)\n return -1;\n for (; t = t.previousElementSibling; )\n t.nodeName.toUpperCase() !== \"TEMPLATE\" && t !== p.clone && (!e || We(t, e)) && n++;\n return n;\n}\nfunction Nt(t) {\n var e = 0, n = 0, o = te();\n if (t)\n do {\n var r = ye(t), i = r.a, a = r.d;\n e += t.scrollLeft * i, n += t.scrollTop * a;\n } while (t !== o && (t = t.parentNode));\n return [e, n];\n}\nfunction Mn(t, e) {\n for (var n in t)\n if (t.hasOwnProperty(n)) {\n for (var o in e)\n if (e.hasOwnProperty(o) && e[o] === t[n][o])\n return Number(n);\n }\n return -1;\n}\nfunction ce(t, e) {\n if (!t || !t.getBoundingClientRect)\n return te();\n var n = t, o = !1;\n do\n if (n.clientWidth < n.scrollWidth || n.clientHeight < n.scrollHeight) {\n var r = h(n);\n if (n.clientWidth < n.scrollWidth && (r.overflowX == \"auto\" || r.overflowX == \"scroll\") || n.clientHeight < n.scrollHeight && (r.overflowY == \"auto\" || r.overflowY == \"scroll\")) {\n if (!n.getBoundingClientRect || n === document.body)\n return te();\n if (o || e)\n return n;\n o = !0;\n }\n }\n while (n = n.parentNode);\n return te();\n}\nfunction Fn(t, e) {\n if (t && e)\n for (var n in e)\n e.hasOwnProperty(n) && (t[n] = e[n]);\n return t;\n}\nfunction Je(t, e) {\n return Math.round(t.top) === Math.round(e.top) && Math.round(t.left) === Math.round(e.left) && Math.round(t.height) === Math.round(e.height) && Math.round(t.width) === Math.round(e.width);\n}\nvar Ce;\nfunction zt(t, e) {\n return function() {\n if (!Ce) {\n var n = arguments, o = this;\n n.length === 1 ? t.call(o, n[0]) : t.apply(o, n), Ce = setTimeout(function() {\n Ce = void 0;\n }, e);\n }\n };\n}\nfunction Rn() {\n clearTimeout(Ce), Ce = void 0;\n}\nfunction Ut(t, e, n) {\n t.scrollLeft += e, t.scrollTop += n;\n}\nfunction Vt(t) {\n var e = window.Polymer, n = window.jQuery || window.Zepto;\n return e && e.dom ? e.dom(t).cloneNode(!0) : n ? n(t).clone(!0)[0] : t.cloneNode(!0);\n}\nfunction $t(t, e, n) {\n var o = {};\n return Array.from(t.children).forEach(function(r) {\n var i, a, l, s;\n if (!(!Q(r, e.draggable, t, !1) || r.animated || r === n)) {\n var u = P(r);\n o.left = Math.min((i = o.left) !== null && i !== void 0 ? i : 1 / 0, u.left), o.top = Math.min((a = o.top) !== null && a !== void 0 ? a : 1 / 0, u.top), o.right = Math.max((l = o.right) !== null && l !== void 0 ? l : -1 / 0, u.right), o.bottom = Math.max((s = o.bottom) !== null && s !== void 0 ? s : -1 / 0, u.bottom);\n }\n }), o.width = o.right - o.left, o.height = o.bottom - o.top, o.x = o.left, o.y = o.top, o;\n}\nvar q = \"Sortable\" + (/* @__PURE__ */ new Date()).getTime();\nfunction Xn() {\n var t = [], e;\n return {\n captureAnimationState: function() {\n if (t = [], !!this.options.animation) {\n var o = [].slice.call(this.el.children);\n o.forEach(function(r) {\n if (!(h(r, \"display\") === \"none\" || r === p.ghost)) {\n t.push({\n target: r,\n rect: P(r)\n });\n var i = ne({}, t[t.length - 1].rect);\n if (r.thisAnimationDuration) {\n var a = ye(r, !0);\n a && (i.top -= a.f, i.left -= a.e);\n }\n r.fromRect = i;\n }\n });\n }\n },\n addAnimationState: function(o) {\n t.push(o);\n },\n removeAnimationState: function(o) {\n t.splice(Mn(t, {\n target: o\n }), 1);\n },\n animateAll: function(o) {\n var r = this;\n if (!this.options.animation) {\n clearTimeout(e), typeof o == \"function\" && o();\n return;\n }\n var i = !1, a = 0;\n t.forEach(function(l) {\n var s = 0, u = l.target, d = u.fromRect, f = P(u), m = u.prevFromRect, y = u.prevToRect, b = l.rect, w = ye(u, !0);\n w && (f.top -= w.f, f.left -= w.e), u.toRect = f, u.thisAnimationDuration && Je(m, f) && !Je(d, f) && // Make sure animatingRect is on line between toRect & fromRect\n (b.top - f.top) / (b.left - f.left) === (d.top - f.top) / (d.left - f.left) && (s = Bn(b, m, y, r.options)), Je(f, d) || (u.prevFromRect = d, u.prevToRect = f, s || (s = r.options.animation), r.animate(u, b, f, s)), s && (i = !0, a = Math.max(a, s), clearTimeout(u.animationResetTimer), u.animationResetTimer = setTimeout(function() {\n u.animationTime = 0, u.prevFromRect = null, u.fromRect = null, u.prevToRect = null, u.thisAnimationDuration = null;\n }, s), u.thisAnimationDuration = s);\n }), clearTimeout(e), i ? e = setTimeout(function() {\n typeof o == \"function\" && o();\n }, a) : typeof o == \"function\" && o(), t = [];\n },\n animate: function(o, r, i, a) {\n if (a) {\n h(o, \"transition\", \"\"), h(o, \"transform\", \"\");\n var l = ye(this.el), s = l && l.a, u = l && l.d, d = (r.left - i.left) / (s || 1), f = (r.top - i.top) / (u || 1);\n o.animatingX = !!d, o.animatingY = !!f, h(o, \"transform\", \"translate3d(\" + d + \"px,\" + f + \"px,0)\"), this.forRepaintDummy = Yn(o), h(o, \"transition\", \"transform \" + a + \"ms\" + (this.options.easing ? \" \" + this.options.easing : \"\")), h(o, \"transform\", \"translate3d(0,0,0)\"), typeof o.animated == \"number\" && clearTimeout(o.animated), o.animated = setTimeout(function() {\n h(o, \"transition\", \"\"), h(o, \"transform\", \"\"), o.animated = !1, o.animatingX = !1, o.animatingY = !1;\n }, a);\n }\n }\n };\n}\nfunction Yn(t) {\n return t.offsetWidth;\n}\nfunction Bn(t, e, n, o) {\n return Math.sqrt(Math.pow(e.top - t.top, 2) + Math.pow(e.left - t.left, 2)) / Math.sqrt(Math.pow(e.top - n.top, 2) + Math.pow(e.left - n.left, 2)) * o.animation;\n}\nvar ge = [], Ze = {\n initializeByDefault: !0\n}, Ne = {\n mount: function(e) {\n for (var n in Ze)\n Ze.hasOwnProperty(n) && !(n in e) && (e[n] = Ze[n]);\n ge.forEach(function(o) {\n if (o.pluginName === e.pluginName)\n throw \"Sortable: Cannot mount plugin \".concat(e.pluginName, \" more than once\");\n }), ge.push(e);\n },\n pluginEvent: function(e, n, o) {\n var r = this;\n this.eventCanceled = !1, o.cancel = function() {\n r.eventCanceled = !0;\n };\n var i = e + \"Global\";\n ge.forEach(function(a) {\n n[a.pluginName] && (n[a.pluginName][i] && n[a.pluginName][i](ne({\n sortable: n\n }, o)), n.options[a.pluginName] && n[a.pluginName][e] && n[a.pluginName][e](ne({\n sortable: n\n }, o)));\n });\n },\n initializePlugins: function(e, n, o, r) {\n ge.forEach(function(l) {\n var s = l.pluginName;\n if (!(!e.options[s] && !l.initializeByDefault)) {\n var u = new l(e, n, e.options);\n u.sortable = e, u.options = e.options, e[s] = u, ie(o, u.defaults);\n }\n });\n for (var i in e.options)\n if (e.options.hasOwnProperty(i)) {\n var a = this.modifyOption(e, i, e.options[i]);\n typeof a != \"undefined\" && (e.options[i] = a);\n }\n },\n getEventProperties: function(e, n) {\n var o = {};\n return ge.forEach(function(r) {\n typeof r.eventProperties == \"function\" && ie(o, r.eventProperties.call(n[r.pluginName], e));\n }), o;\n },\n modifyOption: function(e, n, o) {\n var r;\n return ge.forEach(function(i) {\n e[i.pluginName] && i.optionListeners && typeof i.optionListeners[n] == \"function\" && (r = i.optionListeners[n].call(e[i.pluginName], o));\n }), r;\n }\n};\nfunction kn(t) {\n var e = t.sortable, n = t.rootEl, o = t.name, r = t.targetEl, i = t.cloneEl, a = t.toEl, l = t.fromEl, s = t.oldIndex, u = t.newIndex, d = t.oldDraggableIndex, f = t.newDraggableIndex, m = t.originalEvent, y = t.putSortable, b = t.extraEventProperties;\n if (e = e || n && n[q], !!e) {\n var w, L = e.options, G = \"on\" + o.charAt(0).toUpperCase() + o.substr(1);\n window.CustomEvent && !ae && !xe ? w = new CustomEvent(o, {\n bubbles: !0,\n cancelable: !0\n }) : (w = document.createEvent(\"Event\"), w.initEvent(o, !0, !0)), w.to = a || n, w.from = l || n, w.item = r || n, w.clone = i, w.oldIndex = s, w.newIndex = u, w.oldDraggableIndex = d, w.newDraggableIndex = f, w.originalEvent = m, w.pullMode = y ? y.lastPutMode : void 0;\n var R = ne(ne({}, b), Ne.getEventProperties(o, e));\n for (var j in R)\n w[j] = R[j];\n n && n.dispatchEvent(w), L[G] && L[G].call(e, w);\n }\n}\nvar Hn = [\"evt\"], z = function(e, n) {\n var o = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {}, r = o.evt, i = xn(o, Hn);\n Ne.pluginEvent.bind(p)(e, n, ne({\n dragEl: c,\n parentEl: O,\n ghostEl: g,\n rootEl: T,\n nextEl: pe,\n lastDownEl: Be,\n cloneEl: C,\n cloneHidden: ue,\n dragStarted: Se,\n putSortable: Y,\n activeSortable: p.active,\n originalEvent: r,\n oldIndex: be,\n oldDraggableIndex: Oe,\n newIndex: $,\n newDraggableIndex: se,\n hideGhostForTarget: Zt,\n unhideGhostForTarget: Qt,\n cloneNowHidden: function() {\n ue = !0;\n },\n cloneNowShown: function() {\n ue = !1;\n },\n dispatchSortableEvent: function(l) {\n W({\n sortable: n,\n name: l,\n originalEvent: r\n });\n }\n }, i));\n};\nfunction W(t) {\n kn(ne({\n putSortable: Y,\n cloneEl: C,\n targetEl: c,\n rootEl: T,\n oldIndex: be,\n oldDraggableIndex: Oe,\n newIndex: $,\n newDraggableIndex: se\n }, t));\n}\nvar c, O, g, T, pe, Be, C, ue, be, $, Oe, se, Me, Y, ve = !1, Ge = !1, je = [], de, Z, Qe, et, Pt, Mt, Se, me, Ie, Ae = !1, Fe = !1, ke, H, tt = [], lt = !1, ze = [], Ve = typeof document != \"undefined\", Re = Lt, Ft = xe || ae ? \"cssFloat\" : \"float\", Ln = Ve && !Wt && !Lt && \"draggable\" in document.createElement(\"div\"), qt = function() {\n if (Ve) {\n if (ae)\n return !1;\n var t = document.createElement(\"x\");\n return t.style.cssText = \"pointer-events:auto\", t.style.pointerEvents === \"auto\";\n }\n}(), Kt = function(e, n) {\n var o = h(e), r = parseInt(o.width) - parseInt(o.paddingLeft) - parseInt(o.paddingRight) - parseInt(o.borderLeftWidth) - parseInt(o.borderRightWidth), i = we(e, 0, n), a = we(e, 1, n), l = i && h(i), s = a && h(a), u = l && parseInt(l.marginLeft) + parseInt(l.marginRight) + P(i).width, d = s && parseInt(s.marginLeft) + parseInt(s.marginRight) + P(a).width;\n if (o.display === \"flex\")\n return o.flexDirection === \"column\" || o.flexDirection === \"column-reverse\" ? \"vertical\" : \"horizontal\";\n if (o.display === \"grid\")\n return o.gridTemplateColumns.split(\" \").length <= 1 ? \"vertical\" : \"horizontal\";\n if (i && l.float && l.float !== \"none\") {\n var f = l.float === \"left\" ? \"left\" : \"right\";\n return a && (s.clear === \"both\" || s.clear === f) ? \"vertical\" : \"horizontal\";\n }\n return i && (l.display === \"block\" || l.display === \"flex\" || l.display === \"table\" || l.display === \"grid\" || u >= r && o[Ft] === \"none\" || a && o[Ft] === \"none\" && u + d > r) ? \"vertical\" : \"horizontal\";\n}, Wn = function(e, n, o) {\n var r = o ? e.left : e.top, i = o ? e.right : e.bottom, a = o ? e.width : e.height, l = o ? n.left : n.top, s = o ? n.right : n.bottom, u = o ? n.width : n.height;\n return r === l || i === s || r + a / 2 === l + u / 2;\n}, Gn = function(e, n) {\n var o;\n return je.some(function(r) {\n var i = r[q].options.emptyInsertThreshold;\n if (!(!i || ht(r))) {\n var a = P(r), l = e >= a.left - i && e <= a.right + i, s = n >= a.top - i && n <= a.bottom + i;\n if (l && s)\n return o = r;\n }\n }), o;\n}, Jt = function(e) {\n function n(i, a) {\n return function(l, s, u, d) {\n var f = l.options.group.name && s.options.group.name && l.options.group.name === s.options.group.name;\n if (i == null && (a || f))\n return !0;\n if (i == null || i === !1)\n return !1;\n if (a && i === \"clone\")\n return i;\n if (typeof i == \"function\")\n return n(i(l, s, u, d), a)(l, s, u, d);\n var m = (a ? l : s).options.group.name;\n return i === !0 || typeof i == \"string\" && i === m || i.join && i.indexOf(m) > -1;\n };\n }\n var o = {}, r = e.group;\n (!r || Ye(r) != \"object\") && (r = {\n name: r\n }), o.name = r.name, o.checkPull = n(r.pull, !0), o.checkPut = n(r.put), o.revertClone = r.revertClone, e.group = o;\n}, Zt = function() {\n !qt && g && h(g, \"display\", \"none\");\n}, Qt = function() {\n !qt && g && h(g, \"display\", \"\");\n};\nVe && !Wt && document.addEventListener(\"click\", function(t) {\n if (Ge)\n return t.preventDefault(), t.stopPropagation && t.stopPropagation(), t.stopImmediatePropagation && t.stopImmediatePropagation(), Ge = !1, !1;\n}, !0);\nvar he = function(e) {\n if (c) {\n e = e.touches ? e.touches[0] : e;\n var n = Gn(e.clientX, e.clientY);\n if (n) {\n var o = {};\n for (var r in e)\n e.hasOwnProperty(r) && (o[r] = e[r]);\n o.target = o.rootEl = n, o.preventDefault = void 0, o.stopPropagation = void 0, n[q]._onDragOver(o);\n }\n }\n}, jn = function(e) {\n c && c.parentNode[q]._isOutsideThisEl(e.target);\n};\nfunction p(t, e) {\n if (!(t && t.nodeType && t.nodeType === 1))\n throw \"Sortable: `el` must be an HTMLElement, not \".concat({}.toString.call(t));\n this.el = t, this.options = e = ie({}, e), t[q] = this;\n var n = {\n group: null,\n sort: !0,\n disabled: !1,\n store: null,\n handle: null,\n draggable: /^[uo]l$/i.test(t.nodeName) ? \">li\" : \">*\",\n swapThreshold: 1,\n // percentage; 0 <= x <= 1\n invertSwap: !1,\n // invert always\n invertedSwapThreshold: null,\n // will be set to same as swapThreshold if default\n removeCloneOnHide: !0,\n direction: function() {\n return Kt(t, this.options);\n },\n ghostClass: \"sortable-ghost\",\n chosenClass: \"sortable-chosen\",\n dragClass: \"sortable-drag\",\n ignore: \"a, img\",\n filter: null,\n preventOnFilter: !0,\n animation: 0,\n easing: null,\n setData: function(a, l) {\n a.setData(\"Text\", l.textContent);\n },\n dropBubble: !1,\n dragoverBubble: !1,\n dataIdAttr: \"data-id\",\n delay: 0,\n delayOnTouchOnly: !1,\n touchStartThreshold: (Number.parseInt ? Number : window).parseInt(window.devicePixelRatio, 10) || 1,\n forceFallback: !1,\n fallbackClass: \"sortable-fallback\",\n fallbackOnBody: !1,\n fallbackTolerance: 0,\n fallbackOffset: {\n x: 0,\n y: 0\n },\n supportPointer: p.supportPointer !== !1 && \"PointerEvent\" in window && !Te,\n emptyInsertThreshold: 5\n };\n Ne.initializePlugins(this, t, n);\n for (var o in n)\n !(o in e) && (e[o] = n[o]);\n Jt(e);\n for (var r in this)\n r.charAt(0) === \"_\" && typeof this[r] == \"function\" && (this[r] = this[r].bind(this));\n this.nativeDraggable = e.forceFallback ? !1 : Ln, this.nativeDraggable && (this.options.touchStartThreshold = 1), e.supportPointer ? S(t, \"pointerdown\", this._onTapStart) : (S(t, \"mousedown\", this._onTapStart), S(t, \"touchstart\", this._onTapStart)), this.nativeDraggable && (S(t, \"dragover\", this), S(t, \"dragenter\", this)), je.push(this.el), e.store && e.store.get && this.sort(e.store.get(this) || []), ie(this, Xn());\n}\np.prototype = /** @lends Sortable.prototype */\n{\n constructor: p,\n _isOutsideThisEl: function(e) {\n !this.el.contains(e) && e !== this.el && (me = null);\n },\n _getDirection: function(e, n) {\n return typeof this.options.direction == \"function\" ? this.options.direction.call(this, e, n, c) : this.options.direction;\n },\n _onTapStart: function(e) {\n if (e.cancelable) {\n var n = this, o = this.el, r = this.options, i = r.preventOnFilter, a = e.type, l = e.touches && e.touches[0] || e.pointerType && e.pointerType === \"touch\" && e, s = (l || e).target, u = e.target.shadowRoot && (e.path && e.path[0] || e.composedPath && e.composedPath()[0]) || s, d = r.filter;\n if (Zn(o), !c && !(/mousedown|pointerdown/.test(a) && e.button !== 0 || r.disabled) && !u.isContentEditable && !(!this.nativeDraggable && Te && s && s.tagName.toUpperCase() === \"SELECT\") && (s = Q(s, r.draggable, o, !1), !(s && s.animated) && Be !== s)) {\n if (be = J(s), Oe = J(s, r.draggable), typeof d == \"function\") {\n if (d.call(this, e, s, this)) {\n W({\n sortable: n,\n rootEl: u,\n name: \"filter\",\n targetEl: s,\n toEl: o,\n fromEl: o\n }), z(\"filter\", n, {\n evt: e\n }), i && e.cancelable && e.preventDefault();\n return;\n }\n } else if (d && (d = d.split(\",\").some(function(f) {\n if (f = Q(u, f.trim(), o, !1), f)\n return W({\n sortable: n,\n rootEl: f,\n name: \"filter\",\n targetEl: s,\n fromEl: o,\n toEl: o\n }), z(\"filter\", n, {\n evt: e\n }), !0;\n }), d)) {\n i && e.cancelable && e.preventDefault();\n return;\n }\n r.handle && !Q(u, r.handle, o, !1) || this._prepareDragStart(e, l, s);\n }\n }\n },\n _prepareDragStart: function(e, n, o) {\n var r = this, i = r.el, a = r.options, l = i.ownerDocument, s;\n if (o && !c && o.parentNode === i) {\n var u = P(o);\n if (T = i, c = o, O = c.parentNode, pe = c.nextSibling, Be = o, Me = a.group, p.dragged = c, de = {\n target: c,\n clientX: (n || e).clientX,\n clientY: (n || e).clientY\n }, Pt = de.clientX - u.left, Mt = de.clientY - u.top, this._lastX = (n || e).clientX, this._lastY = (n || e).clientY, c.style[\"will-change\"] = \"all\", s = function() {\n if (z(\"delayEnded\", r, {\n evt: e\n }), p.eventCanceled) {\n r._onDrop();\n return;\n }\n r._disableDelayedDragEvents(), !It && r.nativeDraggable && (c.draggable = !0), r._triggerDragStart(e, n), W({\n sortable: r,\n name: \"choose\",\n originalEvent: e\n }), V(c, a.chosenClass, !0);\n }, a.ignore.split(\",\").forEach(function(d) {\n jt(c, d.trim(), nt);\n }), S(l, \"dragover\", he), S(l, \"mousemove\", he), S(l, \"touchmove\", he), S(l, \"mouseup\", r._onDrop), S(l, \"touchend\", r._onDrop), S(l, \"touchcancel\", r._onDrop), It && this.nativeDraggable && (this.options.touchStartThreshold = 4, c.draggable = !0), z(\"delayStart\", this, {\n evt: e\n }), a.delay && (!a.delayOnTouchOnly || n) && (!this.nativeDraggable || !(xe || ae))) {\n if (p.eventCanceled) {\n this._onDrop();\n return;\n }\n S(l, \"mouseup\", r._disableDelayedDrag), S(l, \"touchend\", r._disableDelayedDrag), S(l, \"touchcancel\", r._disableDelayedDrag), S(l, \"mousemove\", r._delayedDragTouchMoveHandler), S(l, \"touchmove\", r._delayedDragTouchMoveHandler), a.supportPointer && S(l, \"pointermove\", r._delayedDragTouchMoveHandler), r._dragStartTimer = setTimeout(s, a.delay);\n } else\n s();\n }\n },\n _delayedDragTouchMoveHandler: function(e) {\n var n = e.touches ? e.touches[0] : e;\n Math.max(Math.abs(n.clientX - this._lastX), Math.abs(n.clientY - this._lastY)) >= Math.floor(this.options.touchStartThreshold / (this.nativeDraggable && window.devicePixelRatio || 1)) && this._disableDelayedDrag();\n },\n _disableDelayedDrag: function() {\n c && nt(c), clearTimeout(this._dragStartTimer), this._disableDelayedDragEvents();\n },\n _disableDelayedDragEvents: function() {\n var e = this.el.ownerDocument;\n E(e, \"mouseup\", this._disableDelayedDrag), E(e, \"touchend\", this._disableDelayedDrag), E(e, \"touchcancel\", this._disableDelayedDrag), E(e, \"mousemove\", this._delayedDragTouchMoveHandler), E(e, \"touchmove\", this._delayedDragTouchMoveHandler), E(e, \"pointermove\", this._delayedDragTouchMoveHandler);\n },\n _triggerDragStart: function(e, n) {\n n = n || e.pointerType == \"touch\" && e, !this.nativeDraggable || n ? this.options.supportPointer ? S(document, \"pointermove\", this._onTouchMove) : n ? S(document, \"touchmove\", this._onTouchMove) : S(document, \"mousemove\", this._onTouchMove) : (S(c, \"dragend\", this), S(T, \"dragstart\", this._onDragStart));\n try {\n document.selection ? He(function() {\n document.selection.empty();\n }) : window.getSelection().removeAllRanges();\n } catch (o) {\n }\n },\n _dragStarted: function(e, n) {\n if (ve = !1, T && c) {\n z(\"dragStarted\", this, {\n evt: n\n }), this.nativeDraggable && S(document, \"dragover\", jn);\n var o = this.options;\n !e && V(c, o.dragClass, !1), V(c, o.ghostClass, !0), p.active = this, e && this._appendGhost(), W({\n sortable: this,\n name: \"start\",\n originalEvent: n\n });\n } else\n this._nulling();\n },\n _emulateDragOver: function() {\n if (Z) {\n this._lastX = Z.clientX, this._lastY = Z.clientY, Zt();\n for (var e = document.elementFromPoint(Z.clientX, Z.clientY), n = e; e && e.shadowRoot && (e = e.shadowRoot.elementFromPoint(Z.clientX, Z.clientY), e !== n); )\n n = e;\n if (c.parentNode[q]._isOutsideThisEl(e), n)\n do {\n if (n[q]) {\n var o = void 0;\n if (o = n[q]._onDragOver({\n clientX: Z.clientX,\n clientY: Z.clientY,\n target: e,\n rootEl: n\n }), o && !this.options.dragoverBubble)\n break;\n }\n e = n;\n } while (n = n.parentNode);\n Qt();\n }\n },\n _onTouchMove: function(e) {\n if (de) {\n var n = this.options, o = n.fallbackTolerance, r = n.fallbackOffset, i = e.touches ? e.touches[0] : e, a = g && ye(g, !0), l = g && a && a.a, s = g && a && a.d, u = Re && H && Nt(H), d = (i.clientX - de.clientX + r.x) / (l || 1) + (u ? u[0] - tt[0] : 0) / (l || 1), f = (i.clientY - de.clientY + r.y) / (s || 1) + (u ? u[1] - tt[1] : 0) / (s || 1);\n if (!p.active && !ve) {\n if (o && Math.max(Math.abs(i.clientX - this._lastX), Math.abs(i.clientY - this._lastY)) < o)\n return;\n this._onDragStart(e, !0);\n }\n if (g) {\n a ? (a.e += d - (Qe || 0), a.f += f - (et || 0)) : a = {\n a: 1,\n b: 0,\n c: 0,\n d: 1,\n e: d,\n f\n };\n var m = \"matrix(\".concat(a.a, \",\").concat(a.b, \",\").concat(a.c, \",\").concat(a.d, \",\").concat(a.e, \",\").concat(a.f, \")\");\n h(g, \"webkitTransform\", m), h(g, \"mozTransform\", m), h(g, \"msTransform\", m), h(g, \"transform\", m), Qe = d, et = f, Z = i;\n }\n e.cancelable && e.preventDefault();\n }\n },\n _appendGhost: function() {\n if (!g) {\n var e = this.options.fallbackOnBody ? document.body : T, n = P(c, !0, Re, !0, e), o = this.options;\n if (Re) {\n for (H = e; h(H, \"position\") === \"static\" && h(H, \"transform\") === \"none\" && H !== document; )\n H = H.parentNode;\n H !== document.body && H !== document.documentElement ? (H === document && (H = te()), n.top += H.scrollTop, n.left += H.scrollLeft) : H = te(), tt = Nt(H);\n }\n g = c.cloneNode(!0), V(g, o.ghostClass, !1), V(g, o.fallbackClass, !0), V(g, o.dragClass, !0), h(g, \"transition\", \"\"), h(g, \"transform\", \"\"), h(g, \"box-sizing\", \"border-box\"), h(g, \"margin\", 0), h(g, \"top\", n.top), h(g, \"left\", n.left), h(g, \"width\", n.width), h(g, \"height\", n.height), h(g, \"opacity\", \"0.8\"), h(g, \"position\", Re ? \"absolute\" : \"fixed\"), h(g, \"zIndex\", \"100000\"), h(g, \"pointerEvents\", \"none\"), p.ghost = g, e.appendChild(g), h(g, \"transform-origin\", Pt / parseInt(g.style.width) * 100 + \"% \" + Mt / parseInt(g.style.height) * 100 + \"%\");\n }\n },\n _onDragStart: function(e, n) {\n var o = this, r = e.dataTransfer, i = o.options;\n if (z(\"dragStart\", this, {\n evt: e\n }), p.eventCanceled) {\n this._onDrop();\n return;\n }\n z(\"setupClone\", this), p.eventCanceled || (C = Vt(c), C.removeAttribute(\"id\"), C.draggable = !1, C.style[\"will-change\"] = \"\", this._hideClone(), V(C, this.options.chosenClass, !1), p.clone = C), o.cloneId = He(function() {\n z(\"clone\", o), !p.eventCanceled && (o.options.removeCloneOnHide || T.insertBefore(C, c), o._hideClone(), W({\n sortable: o,\n name: \"clone\"\n }));\n }), !n && V(c, i.dragClass, !0), n ? (Ge = !0, o._loopId = setInterval(o._emulateDragOver, 50)) : (E(document, \"mouseup\", o._onDrop), E(document, \"touchend\", o._onDrop), E(document, \"touchcancel\", o._onDrop), r && (r.effectAllowed = \"move\", i.setData && i.setData.call(o, r, c)), S(document, \"drop\", o), h(c, \"transform\", \"translateZ(0)\")), ve = !0, o._dragStartId = He(o._dragStarted.bind(o, n, e)), S(document, \"selectstart\", o), Se = !0, Te && h(document.body, \"user-select\", \"none\");\n },\n // Returns true - if no further action is needed (either inserted or another condition)\n _onDragOver: function(e) {\n var n = this.el, o = e.target, r, i, a, l = this.options, s = l.group, u = p.active, d = Me === s, f = l.sort, m = Y || u, y, b = this, w = !1;\n if (lt)\n return;\n function L(ee, Ee) {\n z(ee, b, ne({\n evt: e,\n isOwner: d,\n axis: y ? \"vertical\" : \"horizontal\",\n revert: a,\n dragRect: r,\n targetRect: i,\n canSort: f,\n fromSortable: m,\n target: o,\n completed: R,\n onMove: function(vt, rn) {\n return Xe(T, n, c, r, vt, P(vt), e, rn);\n },\n changed: j\n }, Ee));\n }\n function G() {\n L(\"dragOverAnimationCapture\"), b.captureAnimationState(), b !== m && m.captureAnimationState();\n }\n function R(ee) {\n return L(\"dragOverCompleted\", {\n insertion: ee\n }), ee && (d ? u._hideClone() : u._showClone(b), b !== m && (V(c, Y ? Y.options.ghostClass : u.options.ghostClass, !1), V(c, l.ghostClass, !0)), Y !== b && b !== p.active ? Y = b : b === p.active && Y && (Y = null), m === b && (b._ignoreWhileAnimating = o), b.animateAll(function() {\n L(\"dragOverAnimationComplete\"), b._ignoreWhileAnimating = null;\n }), b !== m && (m.animateAll(), m._ignoreWhileAnimating = null)), (o === c && !c.animated || o === n && !o.animated) && (me = null), !l.dragoverBubble && !e.rootEl && o !== document && (c.parentNode[q]._isOutsideThisEl(e.target), !ee && he(e)), !l.dragoverBubble && e.stopPropagation && e.stopPropagation(), w = !0;\n }\n function j() {\n $ = J(c), se = J(c, l.draggable), W({\n sortable: b,\n name: \"change\",\n toEl: n,\n newIndex: $,\n newDraggableIndex: se,\n originalEvent: e\n });\n }\n if (e.preventDefault !== void 0 && e.cancelable && e.preventDefault(), o = Q(o, l.draggable, n, !0), L(\"dragOver\"), p.eventCanceled)\n return w;\n if (c.contains(e.target) || o.animated && o.animatingX && o.animatingY || b._ignoreWhileAnimating === o)\n return R(!1);\n if (Ge = !1, u && !l.disabled && (d ? f || (a = O !== T) : Y === this || (this.lastPutMode = Me.checkPull(this, u, c, e)) && s.checkPut(this, u, c, e))) {\n if (y = this._getDirection(e, o) === \"vertical\", r = P(c), L(\"dragOverValid\"), p.eventCanceled)\n return w;\n if (a)\n return O = T, G(), this._hideClone(), L(\"revert\"), p.eventCanceled || (pe ? T.insertBefore(c, pe) : T.appendChild(c)), R(!0);\n var B = ht(n, l.draggable);\n if (!B || $n(e, y, this) && !B.animated) {\n if (B === c)\n return R(!1);\n if (B && n === e.target && (o = B), o && (i = P(o)), Xe(T, n, c, r, o, i, e, !!o) !== !1)\n return G(), B && B.nextSibling ? n.insertBefore(c, B.nextSibling) : n.appendChild(c), O = n, j(), R(!0);\n } else if (B && Vn(e, y, this)) {\n var X = we(n, 0, l, !0);\n if (X === c)\n return R(!1);\n if (o = X, i = P(o), Xe(T, n, c, r, o, i, e, !1) !== !1)\n return G(), n.insertBefore(c, X), O = n, j(), R(!0);\n } else if (o.parentNode === n) {\n i = P(o);\n var K = 0, oe, le = c.parentNode !== n, k = !Wn(c.animated && c.toRect || r, o.animated && o.toRect || i, y), v = y ? \"top\" : \"left\", D = xt(o, \"top\", \"top\") || xt(c, \"top\", \"top\"), A = D ? D.scrollTop : void 0;\n me !== o && (oe = i[v], Ae = !1, Fe = !k && l.invertSwap || le), K = qn(e, o, i, y, k ? 1 : l.swapThreshold, l.invertedSwapThreshold == null ? l.swapThreshold : l.invertedSwapThreshold, Fe, me === o);\n var I;\n if (K !== 0) {\n var _ = J(c);\n do\n _ -= K, I = O.children[_];\n while (I && (h(I, \"display\") === \"none\" || I === g));\n }\n if (K === 0 || I === o)\n return R(!1);\n me = o, Ie = K;\n var x = o.nextElementSibling, M = !1;\n M = K === 1;\n var F = Xe(T, n, c, r, o, i, e, M);\n if (F !== !1)\n return (F === 1 || F === -1) && (M = F === 1), lt = !0, setTimeout(Un, 30), G(), M && !x ? n.appendChild(c) : o.parentNode.insertBefore(c, M ? x : o), D && Ut(D, 0, A - D.scrollTop), O = c.parentNode, oe !== void 0 && !Fe && (ke = Math.abs(oe - P(o)[v])), j(), R(!0);\n }\n if (n.contains(c))\n return R(!1);\n }\n return !1;\n },\n _ignoreWhileAnimating: null,\n _offMoveEvents: function() {\n E(document, \"mousemove\", this._onTouchMove), E(document, \"touchmove\", this._onTouchMove), E(document, \"pointermove\", this._onTouchMove), E(document, \"dragover\", he), E(document, \"mousemove\", he), E(document, \"touchmove\", he);\n },\n _offUpEvents: function() {\n var e = this.el.ownerDocument;\n E(e, \"mouseup\", this._onDrop), E(e, \"touchend\", this._onDrop), E(e, \"pointerup\", this._onDrop), E(e, \"touchcancel\", this._onDrop), E(document, \"selectstart\", this);\n },\n _onDrop: function(e) {\n var n = this.el, o = this.options;\n if ($ = J(c), se = J(c, o.draggable), z(\"drop\", this, {\n evt: e\n }), O = c && c.parentNode, $ = J(c), se = J(c, o.draggable), p.eventCanceled) {\n this._nulling();\n return;\n }\n ve = !1, Fe = !1, Ae = !1, clearInterval(this._loopId), clearTimeout(this._dragStartTimer), st(this.cloneId), st(this._dragStartId), this.nativeDraggable && (E(document, \"drop\", this), E(n, \"dragstart\", this._onDragStart)), this._offMoveEvents(), this._offUpEvents(), Te && h(document.body, \"user-select\", \"\"), h(c, \"transform\", \"\"), e && (Se && (e.cancelable && e.preventDefault(), !o.dropBubble && e.stopPropagation()), g && g.parentNode && g.parentNode.removeChild(g), (T === O || Y && Y.lastPutMode !== \"clone\") && C && C.parentNode && C.parentNode.removeChild(C), c && (this.nativeDraggable && E(c, \"dragend\", this), nt(c), c.style[\"will-change\"] = \"\", Se && !ve && V(c, Y ? Y.options.ghostClass : this.options.ghostClass, !1), V(c, this.options.chosenClass, !1), W({\n sortable: this,\n name: \"unchoose\",\n toEl: O,\n newIndex: null,\n newDraggableIndex: null,\n originalEvent: e\n }), T !== O ? ($ >= 0 && (W({\n rootEl: O,\n name: \"add\",\n toEl: O,\n fromEl: T,\n originalEvent: e\n }), W({\n sortable: this,\n name: \"remove\",\n toEl: O,\n originalEvent: e\n }), W({\n rootEl: O,\n name: \"sort\",\n toEl: O,\n fromEl: T,\n originalEvent: e\n }), W({\n sortable: this,\n name: \"sort\",\n toEl: O,\n originalEvent: e\n })), Y && Y.save()) : $ !== be && $ >= 0 && (W({\n sortable: this,\n name: \"update\",\n toEl: O,\n originalEvent: e\n }), W({\n sortable: this,\n name: \"sort\",\n toEl: O,\n originalEvent: e\n })), p.active && (($ == null || $ === -1) && ($ = be, se = Oe), W({\n sortable: this,\n name: \"end\",\n toEl: O,\n originalEvent: e\n }), this.save()))), this._nulling();\n },\n _nulling: function() {\n z(\"nulling\", this), T = c = O = g = pe = C = Be = ue = de = Z = Se = $ = se = be = Oe = me = Ie = Y = Me = p.dragged = p.ghost = p.clone = p.active = null, ze.forEach(function(e) {\n e.checked = !0;\n }), ze.length = Qe = et = 0;\n },\n handleEvent: function(e) {\n switch (e.type) {\n case \"drop\":\n case \"dragend\":\n this._onDrop(e);\n break;\n case \"dragenter\":\n case \"dragover\":\n c && (this._onDragOver(e), zn(e));\n break;\n case \"selectstart\":\n e.preventDefault();\n break;\n }\n },\n /**\n * Serializes the item into an array of string.\n * @returns {String[]}\n */\n toArray: function() {\n for (var e = [], n, o = this.el.children, r = 0, i = o.length, a = this.options; r < i; r++)\n n = o[r], Q(n, a.draggable, this.el, !1) && e.push(n.getAttribute(a.dataIdAttr) || Jn(n));\n return e;\n },\n /**\n * Sorts the elements according to the array.\n * @param {String[]} order order of the items\n */\n sort: function(e, n) {\n var o = {}, r = this.el;\n this.toArray().forEach(function(i, a) {\n var l = r.children[a];\n Q(l, this.options.draggable, r, !1) && (o[i] = l);\n }, this), n && this.captureAnimationState(), e.forEach(function(i) {\n o[i] && (r.removeChild(o[i]), r.appendChild(o[i]));\n }), n && this.animateAll();\n },\n /**\n * Save the current sorting\n */\n save: function() {\n var e = this.options.store;\n e && e.set && e.set(this);\n },\n /**\n * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.\n * @param {HTMLElement} el\n * @param {String} [selector] default: `options.draggable`\n * @returns {HTMLElement|null}\n */\n closest: function(e, n) {\n return Q(e, n || this.options.draggable, this.el, !1);\n },\n /**\n * Set/get option\n * @param {string} name\n * @param {*} [value]\n * @returns {*}\n */\n option: function(e, n) {\n var o = this.options;\n if (n === void 0)\n return o[e];\n var r = Ne.modifyOption(this, e, n);\n typeof r != \"undefined\" ? o[e] = r : o[e] = n, e === \"group\" && Jt(o);\n },\n /**\n * Destroy\n */\n destroy: function() {\n z(\"destroy\", this);\n var e = this.el;\n e[q] = null, E(e, \"mousedown\", this._onTapStart), E(e, \"touchstart\", this._onTapStart), E(e, \"pointerdown\", this._onTapStart), this.nativeDraggable && (E(e, \"dragover\", this), E(e, \"dragenter\", this)), Array.prototype.forEach.call(e.querySelectorAll(\"[draggable]\"), function(n) {\n n.removeAttribute(\"draggable\");\n }), this._onDrop(), this._disableDelayedDragEvents(), je.splice(je.indexOf(this.el), 1), this.el = e = null;\n },\n _hideClone: function() {\n if (!ue) {\n if (z(\"hideClone\", this), p.eventCanceled)\n return;\n h(C, \"display\", \"none\"), this.options.removeCloneOnHide && C.parentNode && C.parentNode.removeChild(C), ue = !0;\n }\n },\n _showClone: function(e) {\n if (e.lastPutMode !== \"clone\") {\n this._hideClone();\n return;\n }\n if (ue) {\n if (z(\"showClone\", this), p.eventCanceled)\n return;\n c.parentNode == T && !this.options.group.revertClone ? T.insertBefore(C, c) : pe ? T.insertBefore(C, pe) : T.appendChild(C), this.options.group.revertClone && this.animate(c, C), h(C, \"display\", \"\"), ue = !1;\n }\n }\n};\nfunction zn(t) {\n t.dataTransfer && (t.dataTransfer.dropEffect = \"move\"), t.cancelable && t.preventDefault();\n}\nfunction Xe(t, e, n, o, r, i, a, l) {\n var s, u = t[q], d = u.options.onMove, f;\n return window.CustomEvent && !ae && !xe ? s = new CustomEvent(\"move\", {\n bubbles: !0,\n cancelable: !0\n }) : (s = document.createEvent(\"Event\"), s.initEvent(\"move\", !0, !0)), s.to = e, s.from = t, s.dragged = n, s.draggedRect = o, s.related = r || e, s.relatedRect = i || P(e), s.willInsertAfter = l, s.originalEvent = a, t.dispatchEvent(s), d && (f = d.call(u, s, a)), f;\n}\nfunction nt(t) {\n t.draggable = !1;\n}\nfunction Un() {\n lt = !1;\n}\nfunction Vn(t, e, n) {\n var o = P(we(n.el, 0, n.options, !0)), r = $t(n.el, n.options, g), i = 10;\n return e ? t.clientX < r.left - i || t.clientY < o.top && t.clientX < o.right : t.clientY < r.top - i || t.clientY < o.bottom && t.clientX < o.left;\n}\nfunction $n(t, e, n) {\n var o = P(ht(n.el, n.options.draggable)), r = $t(n.el, n.options, g), i = 10;\n return e ? t.clientX > r.right + i || t.clientY > o.bottom && t.clientX > o.left : t.clientY > r.bottom + i || t.clientX > o.right && t.clientY > o.top;\n}\nfunction qn(t, e, n, o, r, i, a, l) {\n var s = o ? t.clientY : t.clientX, u = o ? n.height : n.width, d = o ? n.top : n.left, f = o ? n.bottom : n.right, m = !1;\n if (!a) {\n if (l && ke < u * r) {\n if (!Ae && (Ie === 1 ? s > d + u * i / 2 : s < f - u * i / 2) && (Ae = !0), Ae)\n m = !0;\n else if (Ie === 1 ? s < d + ke : s > f - ke)\n return -Ie;\n } else if (s > d + u * (1 - r) / 2 && s < f - u * (1 - r) / 2)\n return Kn(e);\n }\n return m = m || a, m && (s < d + u * i / 2 || s > f - u * i / 2) ? s > d + u / 2 ? 1 : -1 : 0;\n}\nfunction Kn(t) {\n return J(c) < J(t) ? 1 : -1;\n}\nfunction Jn(t) {\n for (var e = t.tagName + t.className + t.src + t.href + t.textContent, n = e.length, o = 0; n--; )\n o += e.charCodeAt(n);\n return o.toString(36);\n}\nfunction Zn(t) {\n ze.length = 0;\n for (var e = t.getElementsByTagName(\"input\"), n = e.length; n--; ) {\n var o = e[n];\n o.checked && ze.push(o);\n }\n}\nfunction He(t) {\n return setTimeout(t, 0);\n}\nfunction st(t) {\n return clearTimeout(t);\n}\nVe && S(document, \"touchmove\", function(t) {\n (p.active || ve) && t.cancelable && t.preventDefault();\n});\np.utils = {\n on: S,\n off: E,\n css: h,\n find: jt,\n is: function(e, n) {\n return !!Q(e, n, e, !1);\n },\n extend: Fn,\n throttle: zt,\n closest: Q,\n toggleClass: V,\n clone: Vt,\n index: J,\n nextTick: He,\n cancelNextTick: st,\n detectDirection: Kt,\n getChild: we\n};\np.get = function(t) {\n return t[q];\n};\np.mount = function() {\n for (var t = arguments.length, e = new Array(t), n = 0; n < t; n++)\n e[n] = arguments[n];\n e[0].constructor === Array && (e = e[0]), e.forEach(function(o) {\n if (!o.prototype || !o.prototype.constructor)\n throw \"Sortable: Mounted plugin must be a constructor function, not \".concat({}.toString.call(o));\n o.utils && (p.utils = ne(ne({}, p.utils), o.utils)), Ne.mount(o);\n });\n};\np.create = function(t, e) {\n return new p(t, e);\n};\np.version = Nn;\nvar N = [], De, ut, ct = !1, ot, rt, Ue, _e;\nfunction Qn() {\n function t() {\n this.defaults = {\n scroll: !0,\n forceAutoScrollFallback: !1,\n scrollSensitivity: 30,\n scrollSpeed: 10,\n bubbleScroll: !0\n };\n for (var e in this)\n e.charAt(0) === \"_\" && typeof this[e] == \"function\" && (this[e] = this[e].bind(this));\n }\n return t.prototype = {\n dragStarted: function(n) {\n var o = n.originalEvent;\n this.sortable.nativeDraggable ? S(document, \"dragover\", this._handleAutoScroll) : this.options.supportPointer ? S(document, \"pointermove\", this._handleFallbackAutoScroll) : o.touches ? S(document, \"touchmove\", this._handleFallbackAutoScroll) : S(document, \"mousemove\", this._handleFallbackAutoScroll);\n },\n dragOverCompleted: function(n) {\n var o = n.originalEvent;\n !this.options.dragOverBubble && !o.rootEl && this._handleAutoScroll(o);\n },\n drop: function() {\n this.sortable.nativeDraggable ? E(document, \"dragover\", this._handleAutoScroll) : (E(document, \"pointermove\", this._handleFallbackAutoScroll), E(document, \"touchmove\", this._handleFallbackAutoScroll), E(document, \"mousemove\", this._handleFallbackAutoScroll)), Rt(), Le(), Rn();\n },\n nulling: function() {\n Ue = ut = De = ct = _e = ot = rt = null, N.length = 0;\n },\n _handleFallbackAutoScroll: function(n) {\n this._handleAutoScroll(n, !0);\n },\n _handleAutoScroll: function(n, o) {\n var r = this, i = (n.touches ? n.touches[0] : n).clientX, a = (n.touches ? n.touches[0] : n).clientY, l = document.elementFromPoint(i, a);\n if (Ue = n, o || this.options.forceAutoScrollFallback || xe || ae || Te) {\n it(n, this.options, l, o);\n var s = ce(l, !0);\n ct && (!_e || i !== ot || a !== rt) && (_e && Rt(), _e = setInterval(function() {\n var u = ce(document.elementFromPoint(i, a), !0);\n u !== s && (s = u, Le()), it(n, r.options, u, o);\n }, 10), ot = i, rt = a);\n } else {\n if (!this.options.bubbleScroll || ce(l, !0) === te()) {\n Le();\n return;\n }\n it(n, this.options, ce(l, !1), !1);\n }\n }\n }, ie(t, {\n pluginName: \"scroll\",\n initializeByDefault: !0\n });\n}\nfunction Le() {\n N.forEach(function(t) {\n clearInterval(t.pid);\n }), N = [];\n}\nfunction Rt() {\n clearInterval(_e);\n}\nvar it = zt(function(t, e, n, o) {\n if (e.scroll) {\n var r = (t.touches ? t.touches[0] : t).clientX, i = (t.touches ? t.touches[0] : t).clientY, a = e.scrollSensitivity, l = e.scrollSpeed, s = te(), u = !1, d;\n ut !== n && (ut = n, Le(), De = e.scroll, d = e.scrollFn, De === !0 && (De = ce(n, !0)));\n var f = 0, m = De;\n do {\n var y = m, b = P(y), w = b.top, L = b.bottom, G = b.left, R = b.right, j = b.width, B = b.height, X = void 0, K = void 0, oe = y.scrollWidth, le = y.scrollHeight, k = h(y), v = y.scrollLeft, D = y.scrollTop;\n y === s ? (X = j < oe && (k.overflowX === \"auto\" || k.overflowX === \"scroll\" || k.overflowX === \"visible\"), K = B < le && (k.overflowY === \"auto\" || k.overflowY === \"scroll\" || k.overflowY === \"visible\")) : (X = j < oe && (k.overflowX === \"auto\" || k.overflowX === \"scroll\"), K = B < le && (k.overflowY === \"auto\" || k.overflowY === \"scroll\"));\n var A = X && (Math.abs(R - r) <= a && v + j < oe) - (Math.abs(G - r) <= a && !!v), I = K && (Math.abs(L - i) <= a && D + B < le) - (Math.abs(w - i) <= a && !!D);\n if (!N[f])\n for (var _ = 0; _ <= f; _++)\n N[_] || (N[_] = {});\n (N[f].vx != A || N[f].vy != I || N[f].el !== y) && (N[f].el = y, N[f].vx = A, N[f].vy = I, clearInterval(N[f].pid), (A != 0 || I != 0) && (u = !0, N[f].pid = setInterval(function() {\n o && this.layer === 0 && p.active._onTouchMove(Ue);\n var x = N[this.layer].vy ? N[this.layer].vy * l : 0, M = N[this.layer].vx ? N[this.layer].vx * l : 0;\n typeof d == \"function\" && d.call(p.dragged.parentNode[q], M, x, t, Ue, N[this.layer].el) !== \"continue\" || Ut(N[this.layer].el, M, x);\n }.bind({\n layer: f\n }), 24))), f++;\n } while (e.bubbleScroll && m !== s && (m = ce(m, !1)));\n ct = u;\n }\n}, 30), en = function(e) {\n var n = e.originalEvent, o = e.putSortable, r = e.dragEl, i = e.activeSortable, a = e.dispatchSortableEvent, l = e.hideGhostForTarget, s = e.unhideGhostForTarget;\n if (n) {\n var u = o || i;\n l();\n var d = n.changedTouches && n.changedTouches.length ? n.changedTouches[0] : n, f = document.elementFromPoint(d.clientX, d.clientY);\n s(), u && !u.el.contains(f) && (a(\"spill\"), this.onSpill({\n dragEl: r,\n putSortable: o\n }));\n }\n};\nfunction pt() {\n}\npt.prototype = {\n startIndex: null,\n dragStart: function(e) {\n var n = e.oldDraggableIndex;\n this.startIndex = n;\n },\n onSpill: function(e) {\n var n = e.dragEl, o = e.putSortable;\n this.sortable.captureAnimationState(), o && o.captureAnimationState();\n var r = we(this.sortable.el, this.startIndex, this.options);\n r ? this.sortable.el.insertBefore(n, r) : this.sortable.el.appendChild(n), this.sortable.animateAll(), o && o.animateAll();\n },\n drop: en\n};\nie(pt, {\n pluginName: \"revertOnSpill\"\n});\nfunction gt() {\n}\ngt.prototype = {\n onSpill: function(e) {\n var n = e.dragEl, o = e.putSortable, r = o || this.sortable;\n r.captureAnimationState(), n.parentNode && n.parentNode.removeChild(n), r.animateAll();\n },\n drop: en\n};\nie(gt, {\n pluginName: \"removeOnSpill\"\n});\np.mount(new Qn());\np.mount(gt, pt);\nfunction eo(t) {\n return t == null ? t : JSON.parse(JSON.stringify(t));\n}\nfunction to(t) {\n dt() && sn(t);\n}\nfunction no(t) {\n dt() ? un(t) : kt(t);\n}\nlet tn = null, nn = null;\nfunction Xt(t = null, e = null) {\n tn = t, nn = e;\n}\nfunction oo() {\n return {\n data: tn,\n clonedData: nn\n };\n}\nconst Yt = Symbol(\"cloneElement\");\nfunction on(...t) {\n var le, k;\n const e = (le = dt()) == null ? void 0 : le.proxy;\n let n = null;\n const o = t[0];\n let [, r, i] = t;\n Array.isArray(U(r)) || (i = r, r = null);\n let a = null;\n const {\n immediate: l = !0,\n clone: s = eo,\n forceFallback: u,\n fallbackOnBody: d,\n customUpdate: f\n } = (k = U(i)) != null ? k : {};\n function m(v) {\n var F;\n const { from: D, oldIndex: A, item: I } = v, _ = Array.from(D.childNodes);\n n = u && !d ? _.slice(0, -1) : _;\n const x = U((F = U(r)) == null ? void 0 : F[A]), M = s(x);\n Xt(x, M), I[Yt] = M;\n }\n function y(v) {\n const D = v.item[Yt];\n if (!wn(D)) {\n if (Ke(v.item), qe(r)) {\n const A = [...U(r)];\n r.value = _t(A, v.newDraggableIndex, D);\n return;\n }\n _t(U(r), v.newDraggableIndex, D);\n }\n }\n function b(v) {\n const { from: D, item: A, oldIndex: I, oldDraggableIndex: _, pullMode: x, clone: M } = v;\n if (Tt(D, A, I), x === \"clone\") {\n Ke(M);\n return;\n }\n if (qe(r)) {\n const F = [...U(r)];\n r.value = Dt(F, _);\n return;\n }\n Dt(U(r), _);\n }\n function w(v) {\n if (f) {\n f(v);\n return;\n }\n const { from: D, item: A, oldIndex: I, oldDraggableIndex: _, newDraggableIndex: x } = v;\n if (Ke(A), Tt(D, A, I), qe(r)) {\n const M = [...U(r)];\n r.value = St(\n M,\n _,\n x\n );\n return;\n }\n St(U(r), _, x);\n }\n function L(v) {\n const { newIndex: D, oldIndex: A, from: I, to: _ } = v;\n let x = null;\n const M = D === A && I === _;\n try {\n if (M) {\n let F = null;\n n == null || n.some((ee, Ee) => {\n if (F && (n == null ? void 0 : n.length) !== _.childNodes.length)\n return I.insertBefore(F, ee.nextSibling), !0;\n const mt = _.childNodes[Ee];\n F = _ == null ? void 0 : _.replaceChild(ee, mt);\n });\n }\n } catch (F) {\n x = F;\n } finally {\n n = null;\n }\n kt(() => {\n if (Xt(), x)\n throw x;\n });\n }\n const G = {\n onUpdate: w,\n onStart: m,\n onAdd: y,\n onRemove: b,\n onEnd: L\n };\n function R(v) {\n const D = U(o);\n return v || (v = En(D) ? Sn(D, e == null ? void 0 : e.$el) : D), v && !Tn(v) && (v = v.$el), v || vn(\"Root element not found\"), v;\n }\n function j() {\n var I;\n const _ = (I = U(i)) != null ? I : {}, { immediate: v, clone: D } = _, A = $e(_, [\"immediate\", \"clone\"]);\n return Ct(A, (x, M) => {\n Cn(x) && (A[x] = (F, ...ee) => {\n const Ee = oo();\n return On(F, Ee), M(F, ...ee);\n });\n }), _n(\n r === null ? {} : G,\n A\n );\n }\n const B = (v) => {\n v = R(v), a && X.destroy(), a = new p(v, j());\n };\n ln(\n () => i,\n () => {\n a && Ct(j(), (v, D) => {\n a == null || a.option(v, D);\n });\n },\n { deep: !0 }\n );\n const X = {\n option: (v, D) => a == null ? void 0 : a.option(v, D),\n destroy: () => {\n a == null || a.destroy(), a = null;\n },\n save: () => a == null ? void 0 : a.save(),\n toArray: () => a == null ? void 0 : a.toArray(),\n closest: (...v) => a == null ? void 0 : a.closest(...v)\n }, K = () => X == null ? void 0 : X.option(\"disabled\", !0), oe = () => X == null ? void 0 : X.option(\"disabled\", !1);\n return no(() => {\n l && B();\n }), to(X.destroy), fe({ start: B, pause: K, resume: oe }, X);\n}\nconst ft = [\n \"update\",\n \"start\",\n \"add\",\n \"remove\",\n \"choose\",\n \"unchoose\",\n \"end\",\n \"sort\",\n \"filter\",\n \"clone\",\n \"move\",\n \"change\"\n], ro = [\n \"clone\",\n \"animation\",\n \"ghostClass\",\n \"group\",\n \"sort\",\n \"disabled\",\n \"store\",\n \"handle\",\n \"draggable\",\n \"swapThreshold\",\n \"invertSwap\",\n \"invertedSwapThreshold\",\n \"removeCloneOnHide\",\n \"direction\",\n \"chosenClass\",\n \"dragClass\",\n \"ignore\",\n \"filter\",\n \"preventOnFilter\",\n \"easing\",\n \"setData\",\n \"dropBubble\",\n \"dragoverBubble\",\n \"dataIdAttr\",\n \"delay\",\n \"delayOnTouchOnly\",\n \"touchStartThreshold\",\n \"forceFallback\",\n \"fallbackClass\",\n \"fallbackOnBody\",\n \"fallbackTolerance\",\n \"fallbackOffset\",\n \"supportPointer\",\n \"emptyInsertThreshold\",\n \"scroll\",\n \"forceAutoScrollFallback\",\n \"scrollSensitivity\",\n \"scrollSpeed\",\n \"bubbleScroll\",\n \"modelValue\",\n \"tag\",\n \"target\",\n \"customUpdate\",\n ...ft.map((t) => `on${t.replace(/^\\S/, (e) => e.toUpperCase())}`)\n], lo = cn({\n name: \"VueDraggable\",\n model: {\n prop: \"modelValue\",\n event: \"update:modelValue\"\n },\n props: ro,\n emits: [\"update:modelValue\", ...ft],\n setup(t, { slots: e, emit: n, expose: o, attrs: r }) {\n const i = ft.reduce((d, f) => {\n const m = `on${f.replace(/^\\S/, (y) => y.toUpperCase())}`;\n return d[m] = (...y) => n(f, ...y), d;\n }, {}), a = Et(() => {\n const y = fn(t), { modelValue: d } = y, f = $e(y, [\"modelValue\"]), m = Object.entries(f).reduce((b, [w, L]) => {\n const G = U(L);\n return G !== void 0 && (b[w] = G), b;\n }, {});\n return fe(fe({}, i), yn(fe(fe({}, r), m)));\n }), l = Et({\n get: () => t.modelValue,\n set: (d) => n(\"update:modelValue\", d)\n }), s = dn(), u = hn(\n on(t.target || s, l, a)\n );\n return o(u), () => {\n var d;\n return pn(t.tag || \"div\", { ref: s }, (d = e == null ? void 0 : e.default) == null ? void 0 : d.call(e, u));\n };\n }\n}), Bt = {\n mounted: \"mounted\",\n unmounted: \"unmounted\"\n}, at = /* @__PURE__ */ new WeakMap(), so = {\n [Bt.mounted](t, e) {\n const n = gn(e.value) ? [e.value] : e.value, [o, r] = n, i = on(t, o, r);\n at.set(t, i.destroy);\n },\n [Bt.unmounted](t) {\n var e;\n (e = at.get(t)) == null || e(), at.delete(t);\n }\n};\nexport {\n lo as VueDraggable,\n on as useDraggable,\n so as vDraggable\n};\n","<script setup lang=\"ts\" generic=\"T extends KanbanCard = KanbanCard\">\nimport { computed, nextTick, ref, useId, useTemplateRef } from 'vue'\nimport { VueDraggable } from 'vue-draggable-plus'\nimport WxBadge from '../Badge/Badge.vue'\nimport WxButton from '../Button/Button.vue'\nimport WxEntityCard from '../EntityCard/EntityCard.vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport type {\n KanbanCard,\n KanbanColumn,\n KanbanEmits,\n KanbanId,\n KanbanProps,\n KanbanVia,\n} from './types'\n\ndefineOptions({ name: 'WxKanban', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<KanbanProps<T>>(), {\n group: undefined,\n size: 'md',\n columnWidth: 288,\n disabled: false,\n handle: undefined,\n addable: false,\n addLabel: 'Add a card',\n collapsible: false,\n reorderColumns: false,\n columnAddable: false,\n addColumnLabel: 'Add a column',\n emptyText: 'Nothing here yet',\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<KanbanEmits<T>>()\n\ndefineSlots<{\n /** One card. Without it the board falls back to the card's own title. */\n card?: (props: { card: T; column: KanbanColumn<T>; index: number }) => unknown\n /** Replaces the title and the count above a column. */\n 'column-header'?: (props: {\n column: KanbanColumn<T>\n count: number\n overLimit: boolean\n }) => unknown\n /** The end of a column's heading — a plus, a menu, whatever the column can do. */\n 'column-actions'?: (props: { column: KanbanColumn<T>; collapsed: boolean }) => unknown\n /** Under the cards, where the add button would be. */\n 'column-footer'?: (props: { column: KanbanColumn<T> }) => unknown\n /** Shown in a column holding no cards. */\n empty?: (props: { column: KanbanColumn<T> }) => unknown\n /** After the last column, in place of the add-a-column button. */\n default?: () => unknown\n}>()\n\n/** Which columns are folded down. Bind it to remember them between visits. */\nconst collapsed = defineModel<KanbanId[]>('collapsed', { default: () => [] })\n\nconst root = useTemplateRef<HTMLElement>('root')\n\n/** Boards exchange cards only when they are told to share a name. */\nconst ownId = useId()\nconst cardGroup = computed(() => props.group ?? `wx-kanban-cards-${ownId}`)\n\nconst boardStyle = computed(() => ({\n '--wx-kanban-column-width':\n typeof props.columnWidth === 'number' ? `${props.columnWidth}px` : props.columnWidth,\n}))\n\nfunction isFull(column: KanbanColumn<T>) {\n return column.limit !== undefined && column.items.length >= column.limit\n}\n\nfunction isCollapsed(column: KanbanColumn<T>) {\n return collapsed.value.includes(column.id)\n}\n\n/** A folded column has nowhere to put a card, so it is closed to them as well. */\nfunction isLocked(column: KanbanColumn<T>) {\n return props.disabled || Boolean(column.disabled) || isCollapsed(column)\n}\n\nfunction columnById(id: KanbanId | string) {\n return props.columns.find((column) => String(column.id) === String(id))\n}\n\nfunction cardTitle(card: T) {\n const named = card as { title?: unknown; name?: unknown; label?: unknown }\n return String(named.title ?? named.name ?? named.label ?? card.id)\n}\n\nfunction nameOf(column: KanbanColumn<T>) {\n return String(column.title ?? column.id)\n}\n\nfunction toggle(column: KanbanColumn<T>) {\n collapsed.value = isCollapsed(column)\n ? collapsed.value.filter((id) => id !== column.id)\n : [...collapsed.value, column.id]\n}\n\n/**\n * A work-in-progress limit is only worth drawing if it also refuses the card. The\n * column's own group decides what may be dropped into it; reordering inside a full\n * column stays allowed, since that does not make it any fuller.\n */\nfunction groupFor(column: KanbanColumn<T>) {\n return {\n name: cardGroup.value,\n pull: !isLocked(column),\n put: (to: unknown, from: unknown) => {\n if (isLocked(column)) return false\n return to === from || !isFull(column)\n },\n }\n}\n\n/* ---------------------------------------------------------------------------\n * Moving a card\n * ------------------------------------------------------------------------- */\n\nfunction move(\n from: KanbanColumn<T>,\n fromIndex: number,\n to: KanbanColumn<T>,\n toIndex: number,\n via: KanbanVia,\n) {\n const [card] = from.items.splice(fromIndex, 1)\n if (!card) return\n\n to.items.splice(toIndex, 0, card)\n emit('move', {\n card,\n from: { column: from.id, index: fromIndex },\n to: { column: to.id, index: toIndex },\n via,\n })\n}\n\n/**\n * A pointer drag is over by the time this runs — the library moved the card between\n * the arrays itself, and all that is left is to say what happened. Each list carries\n * its column id in the DOM so the event can be read back into our own terms.\n */\nfunction onCardDrop(event: {\n from: HTMLElement\n to: HTMLElement\n oldIndex?: number\n newIndex?: number\n}) {\n const fromId = event.from.dataset.columnId\n const toId = event.to.dataset.columnId\n const fromIndex = event.oldIndex ?? -1\n const toIndex = event.newIndex ?? -1\n if (fromId === undefined || toId === undefined || fromIndex < 0 || toIndex < 0) return\n if (fromId === toId && fromIndex === toIndex) return\n\n const to = columnById(toId)\n const card = to?.items[toIndex]\n if (!to || !card) return\n\n emit('move', {\n card,\n from: { column: columnById(fromId)?.id ?? fromId, index: fromIndex },\n to: { column: to.id, index: toIndex },\n via: 'pointer',\n })\n}\n\n/* ---------------------------------------------------------------------------\n * Moving a column\n * ------------------------------------------------------------------------- */\n\n/*\n * Writing into `columns` is the board's contract rather than an accident: a move has\n * to be visible the moment it happens, and the array the caller passed is the one\n * their own `ref` holds — the cards are moved between `column.items` the same way, a\n * level deeper than the rule can see. Assigning to the prop itself is still off the\n * table; only its contents are rearranged.\n */\n/* eslint-disable vue/no-mutating-props */\n\n/**\n * The new order of the columns, written back into the array it came from.\n */\nconst columnOrder = computed({\n get: () => props.columns,\n set: (next) => {\n props.columns.splice(0, props.columns.length, ...next)\n },\n})\n\nfunction moveColumn(from: number, to: number, via: KanbanVia) {\n if (to < 0 || to >= props.columns.length || from === to) return\n\n const [column] = props.columns.splice(from, 1)\n if (!column) return\n\n props.columns.splice(to, 0, column)\n emit('column-move', { column, from, to, via })\n}\n\n/* eslint-enable vue/no-mutating-props */\n\nfunction onColumnDrop(event: { oldDraggableIndex?: number; newDraggableIndex?: number }) {\n const from = event.oldDraggableIndex ?? -1\n const to = event.newDraggableIndex ?? -1\n if (from < 0 || to < 0 || from === to) return\n\n const column = props.columns[to]\n if (!column) return\n\n emit('column-move', { column, from, to, via: 'pointer' })\n}\n\n/* ---------------------------------------------------------------------------\n * Moving without a mouse\n *\n * SortableJS is a pointer library and has nothing to say to a keyboard, so the board\n * carries its own: space picks a card — or a column — up, the arrows move it, space\n * drops it, escape puts it back. It is the same two array operations a drag performs;\n * what a keyboard needs on top is somewhere to read the result, and that is the live\n * region.\n * ------------------------------------------------------------------------- */\n\nconst grabbed = ref<{\n id: KanbanId\n column: KanbanId\n origin: { column: KanbanId; index: number }\n} | null>(null)\n\nconst grabbedColumn = ref<{ id: KanbanId; origin: number } | null>(null)\n\nconst announcement = ref('')\n\nfunction isGrabbed(card: T) {\n return grabbed.value?.id === card.id\n}\n\nfunction isColumnGrabbed(column: KanbanColumn<T>) {\n return grabbedColumn.value?.id === column.id\n}\n\nfunction positionOf(card: T, column: KanbanColumn<T>) {\n return `${column.items.indexOf(card) + 1} of ${column.items.length}`\n}\n\n/**\n * Whatever moved is in a different element now, so the focus has to follow it there.\n * The id is compared rather than written into a selector: an id belongs to the\n * application, and quoting one into CSS needs an escape not every environment has.\n */\nasync function refocus(attribute: 'data-card-id' | 'data-column-grip', id: KanbanId) {\n await nextTick()\n\n const wanted = String(id)\n const elements = root.value?.querySelectorAll<HTMLElement>(`[${attribute}]`) ?? []\n for (const element of elements) {\n if (element.getAttribute(attribute) === wanted) {\n element.focus()\n return\n }\n }\n}\n\nfunction onCardKeydown(event: KeyboardEvent, card: T, column: KanbanColumn<T>, index: number) {\n /* A button or a link inside a card keeps its own keys. */\n if (event.target !== event.currentTarget) return\n if (isLocked(column)) return\n\n const held = isGrabbed(card)\n\n if (event.key === ' ' || event.key === 'Spacebar' || event.key === 'Enter') {\n event.preventDefault()\n if (held) {\n grabbed.value = null\n announcement.value = `Dropped ${cardTitle(card)} in ${nameOf(column)}, ${positionOf(card, column)}.`\n } else {\n grabbed.value = { id: card.id, column: column.id, origin: { column: column.id, index } }\n announcement.value = `Picked up ${cardTitle(card)}. Use the arrow keys to move it, space to drop it, escape to put it back.`\n }\n return\n }\n\n if (!held) return\n\n if (event.key === 'Escape') {\n event.preventDefault()\n const state = grabbed.value\n grabbed.value = null\n if (!state) return\n\n const current = columnById(state.column)\n const origin = columnById(state.origin.column)\n if (current && origin) {\n const at = current.items.indexOf(card)\n if (at >= 0) move(current, at, origin, state.origin.index, 'keyboard')\n }\n\n announcement.value = 'Move cancelled.'\n void refocus('data-card-id', card.id)\n return\n }\n\n const steps: Record<string, () => void> = {\n ArrowUp: () => stepCard(card, column, -1),\n ArrowDown: () => stepCard(card, column, 1),\n ArrowLeft: () => shiftCard(card, column, -1),\n ArrowRight: () => shiftCard(card, column, 1),\n }\n\n const run = steps[event.key]\n if (!run) return\n\n event.preventDefault()\n run()\n}\n\nfunction stepCard(card: T, column: KanbanColumn<T>, offset: number) {\n const index = column.items.indexOf(card)\n const next = index + offset\n if (next < 0 || next >= column.items.length) return\n\n move(column, index, column, next, 'keyboard')\n announcement.value = `${cardTitle(card)} is now ${positionOf(card, column)} in ${nameOf(column)}.`\n void refocus('data-card-id', card.id)\n}\n\nfunction shiftCard(card: T, column: KanbanColumn<T>, offset: number) {\n const columnIndex = props.columns.indexOf(column)\n\n /* Past a column that refuses the card there may still be one that takes it. */\n for (let i = columnIndex + offset; i >= 0 && i < props.columns.length; i += offset) {\n const target = props.columns[i]\n if (isLocked(target) || isFull(target)) continue\n\n const index = column.items.indexOf(card)\n move(column, index, target, Math.min(index, target.items.length), 'keyboard')\n\n if (grabbed.value) grabbed.value = { ...grabbed.value, column: target.id }\n announcement.value = `${cardTitle(card)} moved to ${nameOf(target)}, ${positionOf(card, target)}.`\n void refocus('data-card-id', card.id)\n return\n }\n\n announcement.value = `${nameOf(column)} is the last column that can take ${cardTitle(card)}.`\n}\n\nfunction onColumnKeydown(event: KeyboardEvent, column: KanbanColumn<T>, index: number) {\n if (event.target !== event.currentTarget) return\n if (!props.reorderColumns || props.disabled) return\n\n const held = isColumnGrabbed(column)\n\n if (event.key === ' ' || event.key === 'Spacebar' || event.key === 'Enter') {\n event.preventDefault()\n if (held) {\n grabbedColumn.value = null\n announcement.value = `Dropped ${nameOf(column)}, ${index + 1} of ${props.columns.length}.`\n } else {\n grabbedColumn.value = { id: column.id, origin: index }\n announcement.value = `Picked up the ${nameOf(column)} column. Use the left and right arrows to move it.`\n }\n return\n }\n\n if (!held) return\n\n if (event.key === 'Escape') {\n event.preventDefault()\n const state = grabbedColumn.value\n grabbedColumn.value = null\n if (state) moveColumn(props.columns.indexOf(column), state.origin, 'keyboard')\n\n announcement.value = 'Move cancelled.'\n void refocus('data-column-grip', column.id)\n return\n }\n\n const offsets: Record<string, number> = { ArrowLeft: -1, ArrowRight: 1 }\n const offset = offsets[event.key]\n if (offset === undefined) return\n\n event.preventDefault()\n const at = props.columns.indexOf(column)\n moveColumn(at, at + offset, 'keyboard')\n announcement.value = `${nameOf(column)} is now ${props.columns.indexOf(column) + 1} of ${props.columns.length}.`\n void refocus('data-column-grip', column.id)\n}\n\nconst classes = computed(() => ['wx-kanban', `wx-kanban--${props.size}`])\n\ndefineExpose({ move, moveColumn, toggle })\n</script>\n\n<template>\n <div\n ref=\"root\"\n v-bind=\"$attrs\"\n :class=\"classes\"\n :style=\"boardStyle\"\n role=\"group\"\n :aria-label=\"ariaLabel\"\n >\n <!--\n Only the columns are items of this list; the tail that adds a column rides along\n inside the same scroller so it stays at the end of the row wherever that is.\n -->\n <vue-draggable\n v-model=\"columnOrder\"\n class=\"wx-kanban__scroller\"\n :group=\"{ name: `wx-kanban-columns-${ownId}`, pull: false, put: false }\"\n :disabled=\"!reorderColumns || disabled\"\n draggable=\".wx-kanban__column\"\n handle=\".wx-kanban__grip\"\n filter=\"button, a, .wx-kanban__actions\"\n :prevent-on-filter=\"false\"\n :animation=\"160\"\n @end=\"onColumnDrop\"\n >\n <section\n v-for=\"(column, columnIndex) in columns\"\n :key=\"column.id\"\n class=\"wx-kanban__column\"\n :class=\"[\n `wx-kanban__column--${column.tone ?? 'default'}`,\n {\n 'is-collapsed': isCollapsed(column),\n 'is-locked': disabled || column.disabled,\n 'is-grabbed': isColumnGrabbed(column),\n },\n ]\"\n >\n <!-- Folded down, a column is a strip with its name read the long way. -->\n <div\n v-if=\"isCollapsed(column)\"\n class=\"wx-kanban__strip wx-kanban__grip\"\n :data-column-grip=\"column.id\"\n :tabindex=\"reorderColumns && !disabled ? 0 : -1\"\n @keydown=\"onColumnKeydown($event, column, columnIndex)\"\n >\n <button\n class=\"wx-kanban__expand\"\n type=\"button\"\n :aria-expanded=\"false\"\n :aria-label=\"`Expand ${nameOf(column)}`\"\n @click=\"toggle(column)\"\n >\n <wx-icon name=\"chevron-right\" />\n </button>\n <span class=\"wx-kanban__title wx-kanban__title--vertical\">{{ nameOf(column) }}</span>\n <wx-badge size=\"sm\" round :type=\"isFull(column) ? 'danger' : 'default'\">\n {{ column.items.length }}\n </wx-badge>\n </div>\n\n <template v-else>\n <header\n class=\"wx-kanban__head wx-kanban__grip\"\n :data-column-grip=\"column.id\"\n :tabindex=\"reorderColumns && !disabled ? 0 : -1\"\n :role=\"reorderColumns && !disabled ? 'button' : undefined\"\n :aria-roledescription=\"reorderColumns && !disabled ? 'Draggable column' : undefined\"\n :aria-pressed=\"reorderColumns && !disabled ? isColumnGrabbed(column) : undefined\"\n @keydown=\"onColumnKeydown($event, column, columnIndex)\"\n >\n <button\n v-if=\"collapsible\"\n class=\"wx-kanban__collapse\"\n type=\"button\"\n :aria-expanded=\"true\"\n :aria-label=\"`Collapse ${nameOf(column)}`\"\n @click=\"toggle(column)\"\n >\n <wx-icon name=\"chevron-left\" />\n </button>\n\n <slot\n name=\"column-header\"\n :column=\"column\"\n :count=\"column.items.length\"\n :over-limit=\"isFull(column)\"\n >\n <span class=\"wx-kanban__title\">{{ nameOf(column) }}</span>\n <wx-badge\n class=\"wx-kanban__count\"\n size=\"sm\"\n round\n :type=\"isFull(column) ? 'danger' : 'default'\"\n >\n {{ column.items.length\n }}<template v-if=\"column.limit\">/{{ column.limit }}</template>\n </wx-badge>\n </slot>\n\n <span v-if=\"$slots['column-actions']\" class=\"wx-kanban__actions\">\n <slot name=\"column-actions\" :column=\"column\" :collapsed=\"false\" />\n </span>\n </header>\n\n <vue-draggable\n v-model=\"column.items\"\n class=\"wx-kanban__list\"\n :data-column-id=\"column.id\"\n :group=\"groupFor(column)\"\n :disabled=\"isLocked(column)\"\n :handle=\"handle\"\n :animation=\"160\"\n :delay=\"150\"\n :delay-on-touch-only=\"true\"\n ghost-class=\"wx-kanban__card--ghost\"\n chosen-class=\"wx-kanban__card--chosen\"\n @end=\"onCardDrop\"\n >\n <div\n v-for=\"(card, index) in column.items\"\n :key=\"card.id\"\n class=\"wx-kanban__card\"\n :class=\"{ 'is-grabbed': isGrabbed(card) }\"\n :data-card-id=\"card.id\"\n :tabindex=\"isLocked(column) ? -1 : 0\"\n role=\"button\"\n aria-roledescription=\"Draggable card\"\n :aria-pressed=\"isGrabbed(card)\"\n @keydown=\"onCardKeydown($event, card, column, index)\"\n >\n <slot name=\"card\" :card=\"card\" :column=\"column\" :index=\"index\">\n <wx-entity-card :title=\"cardTitle(card)\" variant=\"card\" bordered size=\"sm\" />\n </slot>\n </div>\n </vue-draggable>\n\n <p v-if=\"column.items.length === 0\" class=\"wx-kanban__empty\">\n <slot name=\"empty\" :column=\"column\">{{ emptyText }}</slot>\n </p>\n\n <footer v-if=\"addable || $slots['column-footer']\" class=\"wx-kanban__foot\">\n <slot name=\"column-footer\" :column=\"column\">\n <wx-button\n class=\"wx-kanban__add\"\n variant=\"text\"\n size=\"sm\"\n block\n :disabled=\"isLocked(column) || isFull(column)\"\n @click=\"emit('add', column)\"\n >\n <template #icon><wx-icon name=\"plus\" /></template>\n {{ addLabel }}\n </wx-button>\n </slot>\n </footer>\n </template>\n </section>\n\n <div v-if=\"columnAddable || $slots.default\" class=\"wx-kanban__tail\">\n <slot>\n <button class=\"wx-kanban__add-column\" type=\"button\" @click=\"emit('add-column')\">\n <wx-icon name=\"plus\" />\n <span class=\"wx-kanban__title--vertical\">{{ addColumnLabel }}</span>\n </button>\n </slot>\n </div>\n </vue-draggable>\n\n <!-- What a keyboard move says out loud. -->\n <div class=\"wx-kanban__live\" role=\"status\" aria-live=\"polite\">{{ announcement }}</div>\n </div>\n</template>\n\n<style scoped>\n.wx-kanban {\n --wx-kanban-column-width: 288px;\n\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n /* The board is as tall as it is given; the columns scroll inside it, not the page. */\n min-height: 0;\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n container-type: inline-size;\n}\n\n.wx-kanban__scroller {\n display: flex;\n align-items: stretch;\n gap: var(--wx-space-12);\n min-height: 0;\n padding-bottom: var(--wx-space-6);\n overflow-x: auto;\n /* A swipe across the board must not turn into a page swipe or a back gesture. */\n overscroll-behavior-inline: contain;\n scroll-snap-type: inline proximity;\n}\n\n.wx-kanban__column {\n display: flex;\n flex: 0 0 auto;\n flex-direction: column;\n box-sizing: border-box;\n width: var(--wx-kanban-column-width);\n min-height: 0;\n background: var(--wx-bg-muted);\n border-top: 3px solid var(--wx-kanban-tone, var(--wx-border-default));\n border-radius: var(--wx-radius-md);\n scroll-snap-align: start;\n transition: width var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-kanban__column--primary {\n --wx-kanban-tone: var(--wx-color-primary);\n}\n\n.wx-kanban__column--success {\n --wx-kanban-tone: var(--wx-color-success);\n}\n\n.wx-kanban__column--warning {\n --wx-kanban-tone: var(--wx-color-warning);\n}\n\n.wx-kanban__column--danger {\n --wx-kanban-tone: var(--wx-color-danger);\n}\n\n.wx-kanban__column--info {\n --wx-kanban-tone: var(--wx-color-info);\n}\n\n.wx-kanban__column.is-locked {\n opacity: 0.7;\n}\n\n.wx-kanban__column.is-collapsed {\n width: 48px;\n}\n\n.wx-kanban__column.is-grabbed {\n box-shadow: var(--wx-ring-focus), var(--wx-shadow-md);\n}\n\n.wx-kanban__head {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n padding: var(--wx-space-12) var(--wx-space-12) var(--wx-space-8);\n border-radius: var(--wx-radius-md) var(--wx-radius-md) 0 0;\n}\n\n/* The heading is what a column is dragged by, so it says so under the pointer. */\n.wx-kanban__grip {\n cursor: grab;\n}\n\n.wx-kanban__grip:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-kanban__title {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n color: var(--wx-text-strong);\n font-size: var(--wx-font-size-sm);\n font-weight: var(--wx-font-weight-semibold);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Read down the strip of a folded column, the way a spine is. */\n.wx-kanban__title--vertical {\n flex: 0 1 auto;\n max-height: 100%;\n writing-mode: vertical-rl;\n}\n\n.wx-kanban__count,\n.wx-kanban__actions {\n flex: 0 0 auto;\n}\n\n.wx-kanban__actions {\n display: flex;\n align-items: center;\n gap: var(--wx-space-2);\n cursor: default;\n}\n\n.wx-kanban__collapse,\n.wx-kanban__expand {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 22px;\n height: 22px;\n padding: 0;\n background: none;\n border: none;\n border-radius: var(--wx-radius-full);\n color: var(--wx-text-muted);\n cursor: pointer;\n}\n\n.wx-kanban__collapse:hover,\n.wx-kanban__expand:hover {\n background: var(--wx-bg-fill);\n color: var(--wx-text-default);\n}\n\n.wx-kanban__collapse:focus-visible,\n.wx-kanban__expand:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-kanban__strip {\n display: flex;\n flex: 1 1 auto;\n flex-direction: column;\n align-items: center;\n gap: var(--wx-space-8);\n min-height: 0;\n padding: var(--wx-space-10) 0;\n overflow: hidden;\n}\n\n.wx-kanban__list {\n display: flex;\n flex: 1 1 auto;\n flex-direction: column;\n gap: var(--wx-space-8);\n /* Room to drop a card into a column that has none. */\n min-height: 40px;\n padding: 0 var(--wx-space-8);\n overflow-y: auto;\n}\n\n.wx-kanban__card {\n border-radius: var(--wx-radius-sm);\n cursor: grab;\n}\n\n.wx-kanban__card:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n/* Held by the keyboard: the same ring, plus the lift a dragged card has. */\n.wx-kanban__card.is-grabbed {\n box-shadow: var(--wx-ring-focus), var(--wx-shadow-md);\n}\n\n/* What is left behind in the list while the card is being dragged. */\n.wx-kanban__card--ghost {\n opacity: 0.4;\n}\n\n.wx-kanban__card--chosen {\n cursor: grabbing;\n}\n\n.wx-kanban__empty {\n margin: 0;\n padding: var(--wx-space-8) var(--wx-space-12) 0;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n}\n\n.wx-kanban__foot {\n padding: var(--wx-space-8);\n}\n\n.wx-kanban__tail {\n display: flex;\n flex: 0 0 auto;\n align-items: stretch;\n}\n\n/* A column-shaped button, so the end of the row reads as a place for one more. */\n.wx-kanban__add-column {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--wx-space-8);\n box-sizing: border-box;\n width: 48px;\n padding: var(--wx-space-10) 0;\n background: var(--wx-bg-subtle);\n border: 1px dashed var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n color: var(--wx-text-muted);\n font-family: inherit;\n font-size: var(--wx-font-size-sm);\n cursor: pointer;\n transition: color var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-kanban__add-column:hover {\n background: var(--wx-bg-fill);\n color: var(--wx-text-default);\n}\n\n.wx-kanban__add-column:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n/* Read out, never drawn. */\n.wx-kanban__live {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n\n.wx-kanban--sm .wx-kanban__head {\n padding: var(--wx-space-8) var(--wx-space-10) var(--wx-space-6);\n}\n\n.wx-kanban--sm .wx-kanban__list {\n gap: var(--wx-space-6);\n padding: 0 var(--wx-space-6);\n}\n\n/*\n * On a phone a column of a fixed 288px leaves a slice of the next one showing, which\n * reads as clutter rather than as a hint. Below that width a column takes most of the\n * screen and the swipe snaps to it. Asked of the board, not of the window: the same\n * squeeze happens in a narrow panel on a wide monitor.\n */\n@container (max-width: 560px) {\n .wx-kanban__scroller {\n scroll-snap-type: inline mandatory;\n }\n\n .wx-kanban__column:not(.is-collapsed) {\n width: min(88cqw, 320px);\n }\n}\n\n/* A finger needs a bigger target, and a long press to tell a drag from a scroll. */\n@media (pointer: coarse) {\n .wx-kanban__card,\n .wx-kanban__grip {\n cursor: default;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-kanban__column {\n transition: none;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport type { LinkEmits, LinkProps } from './types'\n\ndefineOptions({ name: 'WxLink', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<LinkProps>(), {\n href: undefined,\n target: undefined,\n rel: undefined,\n type: 'default',\n underline: 'hover',\n size: undefined,\n weight: undefined,\n disabled: false,\n external: false,\n as: undefined,\n})\n\nconst emit = defineEmits<LinkEmits>()\n\nconst tag = computed(() => props.as ?? 'a')\n\n/** `noopener` is not optional on a `_blank` link — the opened page can steal the tab. */\nconst linkAttrs = computed(() => {\n const target = props.target ?? (props.external ? '_blank' : undefined)\n const rel = props.rel ?? (target === '_blank' ? 'noopener noreferrer' : undefined)\n const href = props.disabled ? undefined : props.href\n\n /*\n * Only the attributes we actually have: rendering through `RouterLink`, a stray\n * `href: undefined` in the fallthrough would wipe out the href the router writes.\n */\n const attrs: Record<string, unknown> = {}\n if (href !== undefined) attrs.href = href\n if (target !== undefined) attrs.target = target\n if (rel !== undefined) attrs.rel = rel\n if (props.disabled) {\n attrs['aria-disabled'] = 'true'\n attrs.tabindex = -1\n }\n return attrs\n})\n\nconst classes = computed(() => [\n 'wx-link',\n `wx-link--${props.type}`,\n `wx-link--underline-${props.underline}`,\n {\n [`wx-link--${props.size}`]: Boolean(props.size),\n [`wx-link--weight-${props.weight}`]: Boolean(props.weight),\n 'is-disabled': props.disabled,\n },\n])\n\nfunction onClick(event: MouseEvent) {\n if (props.disabled) {\n event.preventDefault()\n event.stopPropagation()\n return\n }\n emit('click', event)\n}\n</script>\n\n<template>\n <component :is=\"tag\" v-bind=\"{ ...linkAttrs, ...$attrs }\" :class=\"classes\" @click=\"onClick\">\n <span v-if=\"$slots.icon\" class=\"wx-link__icon\">\n <slot name=\"icon\" />\n </span>\n <slot />\n <wx-icon v-if=\"external\" class=\"wx-link__external\" name=\"external-link\" size=\"0.85em\" />\n </component>\n</template>\n\n<style scoped>\n.wx-link {\n display: inline-flex;\n align-items: center;\n gap: var(--wx-space-4);\n color: var(--wx-link-color, var(--wx-text-link));\n font-family: inherit;\n font-size: inherit;\n text-decoration: none;\n cursor: pointer;\n transition: color var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n/* `as=\"button\"` — an action that reads as a link: none of the browser's button chrome. */\nbutton.wx-link {\n padding: 0;\n border: 0;\n background: none;\n font-weight: inherit;\n line-height: inherit;\n}\n\n.wx-link:hover {\n color: var(--wx-link-hover, var(--wx-link-color));\n}\n\n.wx-link:focus-visible {\n outline: none;\n border-radius: var(--wx-radius-xs);\n box-shadow: var(--wx-ring-focus);\n}\n\n/* types */\n.wx-link--default {\n --wx-link-color: var(--wx-text-link);\n --wx-link-hover: var(--wx-color-primary-hover);\n}\n\n.wx-link--primary {\n --wx-link-color: var(--wx-color-primary);\n --wx-link-hover: var(--wx-color-primary-hover);\n}\n\n.wx-link--success {\n --wx-link-color: var(--wx-color-success-active);\n --wx-link-hover: var(--wx-color-success);\n}\n\n.wx-link--warning {\n --wx-link-color: var(--wx-color-warning-active);\n --wx-link-hover: var(--wx-color-warning);\n}\n\n.wx-link--danger {\n --wx-link-color: var(--wx-color-danger);\n --wx-link-hover: var(--wx-color-danger-hover);\n}\n\n.wx-link--info {\n --wx-link-color: var(--wx-color-info-active);\n --wx-link-hover: var(--wx-color-info);\n}\n\n.wx-link--muted {\n --wx-link-color: var(--wx-text-muted);\n --wx-link-hover: var(--wx-text-default);\n}\n\n/* underline */\n.wx-link--underline-always {\n text-decoration: underline;\n text-underline-offset: 0.2em;\n}\n\n.wx-link--underline-hover:hover {\n text-decoration: underline;\n text-underline-offset: 0.2em;\n}\n\n.wx-link--underline-never,\n.wx-link--underline-never:hover {\n text-decoration: none;\n}\n\n/* sizes */\n.wx-link--xs {\n font-size: var(--wx-font-size-xs);\n}\n\n.wx-link--sm {\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-link--md {\n font-size: var(--wx-font-size-md);\n}\n\n.wx-link--lg {\n font-size: var(--wx-font-size-lg);\n}\n\n.wx-link--xl {\n font-size: var(--wx-font-size-xl);\n}\n\n.wx-link--weight-regular {\n font-weight: var(--wx-font-weight-regular);\n}\n\n.wx-link--weight-medium {\n font-weight: var(--wx-font-weight-medium);\n}\n\n.wx-link--weight-semibold {\n font-weight: var(--wx-font-weight-semibold);\n}\n\n.wx-link--weight-bold {\n font-weight: var(--wx-font-weight-bold);\n}\n\n.wx-link.is-disabled {\n color: var(--wx-text-disabled);\n text-decoration: none;\n cursor: not-allowed;\n}\n\n.wx-link__icon {\n display: inline-flex;\n align-items: center;\n}\n\n.wx-link__external {\n opacity: 0.75;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { localeLabel, useLocales, type LocaleOption } from '../../composables/useLocalized'\nimport LocalePicker from './LocalePicker.vue'\nimport type { LocalesEmits, LocalesProps } from './types'\n\n/**\n * Several fields that belong to one language, switched together.\n *\n * A single field does not need this — it takes `localized` and grows a picker of its own. This\n * is for a section: a heading, a lead and a body that are all the Ukrainian version of a page.\n */\ndefineOptions({ name: 'WxLocales' })\n\nconst props = withDefaults(defineProps<LocalesProps>(), {\n locales: undefined,\n variant: 'inline',\n})\n\nconst emit = defineEmits<LocalesEmits>()\n\nconst context = useLocales()\n\nconst list = computed<LocaleOption[]>(() => props.locales ?? context.list.value)\n\n/**\n * The language being edited is shared, so switching it here switches it everywhere on the\n * screen — a page half in one language and half in another is how a record gets saved\n * untranslated. A caller that wants this section on its own passes `v-model:locale`.\n */\nconst model = defineModel<string | undefined>('locale', { default: undefined })\n\nconst active = computed<string>(() => {\n const chosen = model.value ?? context.active.value\n const known = list.value.some((locale) => locale.code === chosen)\n\n return known ? chosen : (list.value[0]?.code ?? '')\n})\n\nfunction choose(code: string): void {\n if (code === active.value) return\n\n if (model.value === undefined) {\n context.active.value = code\n } else {\n model.value = code\n }\n\n emit('change', code)\n}\n</script>\n\n<template>\n <div :class=\"['wx-locales', `wx-locales--${variant}`]\">\n <div v-if=\"variant === 'tabs'\" class=\"wx-locales__tabs\" role=\"tablist\">\n <button\n v-for=\"locale in list\"\n :key=\"locale.code\"\n type=\"button\"\n role=\"tab\"\n :aria-selected=\"locale.code === active\"\n :class=\"['wx-locales__tab', { 'is-active': locale.code === active }]\"\n @click=\"choose(locale.code)\"\n >\n {{ localeLabel(locale) }}\n </button>\n </div>\n\n <!--\n Every language stays in the DOM, only one is shown: a control that is not rendered is a\n control a classic form post leaves out, and the other languages would be wiped on save.\n -->\n <!--\n With no languages configured the section is still a section: the slot is rendered once\n with none, rather than the whole thing disappearing because a setting is missing.\n -->\n <div v-if=\"list.length === 0\" class=\"wx-locales__pane\">\n <slot :locale=\"undefined\" :active=\"true\" />\n </div>\n\n <div\n v-for=\"locale in list\"\n v-show=\"locale.code === active\"\n :key=\"locale.code\"\n class=\"wx-locales__pane\"\n >\n <slot :locale=\"locale\" :active=\"locale.code === active\" />\n </div>\n\n <locale-picker\n v-if=\"variant === 'inline' && list.length > 1\"\n :locales=\"list\"\n :active=\"active\"\n @choose=\"choose\"\n />\n </div>\n</template>\n\n<style scoped>\n.wx-locales--inline {\n position: relative;\n}\n\n.wx-locales__pane {\n min-width: 0;\n}\n\n.wx-locales__tabs {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-4);\n margin-bottom: var(--wx-space-8);\n}\n\n.wx-locales__tab {\n height: var(--wx-size-control-sm);\n padding: 0 var(--wx-space-12);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-control);\n background: var(--wx-bg-surface);\n color: var(--wx-text-muted);\n font-family: inherit;\n font-size: var(--wx-font-size-control-sm);\n font-weight: 600;\n text-transform: uppercase;\n cursor: pointer;\n transition:\n background-color var(--wx-duration-fast) var(--wx-easing-standard),\n color var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-locales__tab:hover {\n color: var(--wx-text-default);\n}\n\n.wx-locales__tab.is-active {\n border-color: var(--wx-color-primary);\n background: var(--wx-color-primary);\n color: var(--wx-color-primary-contrast);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref, useSlots, watch } from 'vue'\nimport WxDrawer from '../Drawer/Drawer.vue'\nimport { useElementWidth } from '../../composables/useElementWidth'\nimport type { ListDetailProps } from './types'\n\ndefineOptions({ name: 'WxListDetail' })\n\nconst props = withDefaults(defineProps<ListDetailProps>(), {\n filtersWidth: 240,\n listWidth: 380,\n detailMin: 420,\n filtersTitle: 'Filters',\n detailLabel: 'Details',\n})\n\nconst emit = defineEmits<{\n /**\n * Whether the chooser still has a column of its own, said whenever it changes and once at\n * the start. The `list` slot is handed the same thing; this is for a head that stands\n * outside the pane and has to offer the way in when the column is gone.\n */\n 'filters-inline': [inline: boolean]\n /**\n * Whether an open record still stands beside the list, said the same way.\n *\n * What it is for is the first record: beside the list, a screen that opens on nothing wastes\n * its whole width on the words \"choose one\", so the caller opens the first by itself — and\n * on a phone that same line would raise a panel over a list nobody has touched yet. Only the\n * pane knows which of the two it is.\n */\n 'detail-inline': [inline: boolean]\n}>()\n\ndefineSlots<{\n /** What narrows the list: views, folders, filters. The column is optional. */\n filters?: (props: { inline: boolean; close: () => void }) => unknown\n /** The records. Left alone by a screen with no `detail`, it is the screen. */\n list?: (props: { filtersInline: boolean; openFilters: () => void }) => unknown\n /** The record that is open. Optional: a list whose records open elsewhere has none. */\n detail?: (props: { inline: boolean; back: () => void }) => unknown\n /** Shown in the pane's place while nothing is selected. */\n empty?: () => unknown\n}>()\n\n/**\n * Whether a record is open. One idea, two jobs: beside the list it picks the detail\n * over the empty state, and on a narrow screen it is what raises the panel.\n */\nconst open = defineModel<boolean>('open', { default: false })\nconst filtersOpen = defineModel<boolean>('filtersOpen', { default: false })\n\nconst slots = useSlots()\n\n/**\n * Whether one record is opened beside the list at all.\n *\n * Without it this is a list with a chooser in front of it — which form's submissions, which\n * folder's files — and the list is the screen rather than a column of one. The difference is\n * the whole of what the narrow screen does: a pane that exists goes into the panel and the\n * chooser keeps its column for longer; a pane that does not means the chooser is what folds\n * away, and what the reader is left looking at is the records.\n */\nconst hasDetail = computed(() => Boolean(slots.detail))\n\nconst root = ref<HTMLElement | null>(null)\n\n/*\n * The screen measures itself, not the window: this is a pane inside a page inside a\n * shell, and a viewport media query would count the sidebar it does not have.\n */\nconst width = useElementWidth(root)\n\nfunction toPx(value: number | string) {\n return typeof value === 'number' ? value : Number.parseFloat(value) || 0\n}\n\n/**\n * How far under its threshold a layout that already stands keeps standing.\n *\n * The widest thing that comes and goes with the layout itself is the page's scrollbar: a record\n * opened beside the list makes the page taller, the scrollbar takes its 15-17 px, and a pane\n * measured just over the line fell under it — the record went into the drawer, the page was short\n * again, the bar left, and the record came back. For ever, with the drawer closing the record on\n * each way out. A band wider than any scrollbar is what stops it; crossing into the wider layout\n * still needs the full width, so nothing is ever drawn into room it does not have.\n */\nconst SETTLE = 24\n\n/** Whether a layout that needs `need()` pixels stands, with {@link SETTLE} of give once it does. */\nfunction settled(need: () => number) {\n const inline = ref(true)\n\n watch(\n [width, need],\n ([now, threshold], previous) => {\n // Unmeasured is columns (see below); the first measurement is taken at its word.\n if (now === 0) inline.value = true\n else if (!previous?.[0] || !inline.value) inline.value = now >= threshold\n else inline.value = now >= threshold - SETTLE\n },\n { immediate: true, flush: 'sync' },\n )\n\n return inline\n}\n\n/*\n * Both thresholds are the widths the caller gave, added up — not numbers of their\n * own. A wider list or a roomier detail moves them by itself, which is the only way\n * they stay right for a screen we have never seen.\n *\n * `detailMin` is the main pane's floor, and which pane that is depends on whether there\n * is a detail: with one, the column of records stands between the two and is counted;\n * without, the records are the main pane and the chooser folds when they would go under\n * that same floor.\n */\nconst filtersInline = settled(\n () => toPx(props.filtersWidth) + (hasDetail.value ? toPx(props.listWidth) : 0) + props.detailMin,\n)\n\nconst detailInline = settled(() => toPx(props.listWidth) + props.detailMin)\n\n/** The list is the screen: nothing stands beside it, so it takes what is left. */\nconst listAlone = computed(() => !hasDetail.value || !detailInline.value)\n\nconst style = computed(() => ({\n '--wx-list-detail-filters': toLength(props.filtersWidth),\n '--wx-list-detail-list': toLength(props.listWidth),\n}))\n\nfunction toLength(value: number | string) {\n return typeof value === 'number' ? `${value}px` : value\n}\n\nfunction openFilters() {\n filtersOpen.value = true\n}\n\nfunction closeFilters() {\n filtersOpen.value = false\n}\n\nfunction back() {\n open.value = false\n}\n\n/*\n * A record stays open when the screen grows — it just stops being a panel and\n * becomes the column it always wanted to be. The filters have no such continuity:\n * their column is back, so the panel has nothing left to show.\n */\nwatch(\n filtersInline,\n (inline) => {\n if (inline) filtersOpen.value = false\n\n emit('filters-inline', inline)\n },\n { immediate: true },\n)\n\n/*\n * Only once the pane has been measured. Before that the width is zero and every threshold\n * answers \"inline\" — which is right for the layout, since a pane that has not been measured\n * renders as columns — and wrong for a caller that would open the first record on the strength\n * of it, on a phone, over a list nobody has touched.\n */\nwatch(\n [width, detailInline],\n () => {\n if (width.value > 0) emit('detail-inline', detailInline.value)\n },\n { immediate: true },\n)\n</script>\n\n<template>\n <div ref=\"root\" class=\"wx-list-detail\" :style=\"style\">\n <div v-if=\"$slots.filters && filtersInline\" class=\"wx-list-detail__filters\">\n <slot name=\"filters\" :inline=\"true\" :close=\"closeFilters\" />\n </div>\n\n <div class=\"wx-list-detail__list\" :class=\"{ 'wx-list-detail__list--alone': listAlone }\">\n <slot name=\"list\" :filters-inline=\"filtersInline\" :open-filters=\"openFilters\" />\n </div>\n\n <section v-if=\"hasDetail && detailInline\" class=\"wx-list-detail__detail\">\n <slot v-if=\"open\" name=\"detail\" :inline=\"true\" :back=\"back\" />\n <div v-else class=\"wx-list-detail__empty\">\n <slot name=\"empty\" />\n </div>\n </section>\n\n <!--\n Narrow: the detail is not a column but a screen of its own, and the filters are\n a panel. Both are the same slots — the caller writes them once.\n -->\n <wx-drawer\n v-if=\"hasDetail && !detailInline\"\n v-model:open=\"open\"\n side=\"right\"\n size=\"100%\"\n :closable=\"false\"\n :aria-label=\"detailLabel\"\n class=\"wx-list-detail__drawer\"\n >\n <slot name=\"detail\" :inline=\"false\" :back=\"back\" />\n </wx-drawer>\n\n <wx-drawer\n v-if=\"$slots.filters && !filtersInline\"\n v-model:open=\"filtersOpen\"\n side=\"left\"\n :size=\"filtersWidth\"\n :title=\"filtersTitle\"\n closable\n >\n <slot name=\"filters\" :inline=\"false\" :close=\"closeFilters\" />\n </wx-drawer>\n </div>\n</template>\n\n<style scoped>\n.wx-list-detail {\n display: flex;\n /* It fills what it is given: a route inside a padding-less `WxMain`, usually. */\n height: 100%;\n min-height: 0;\n min-width: 0;\n background: var(--wx-bg-body);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n}\n\n.wx-list-detail__filters,\n.wx-list-detail__list,\n.wx-list-detail__detail {\n display: flex;\n flex-direction: column;\n /* Columns clip; what scrolls inside them is the caller's to say. */\n min-height: 0;\n box-sizing: border-box;\n}\n\n.wx-list-detail__filters {\n width: var(--wx-list-detail-filters, 240px);\n flex: 0 0 var(--wx-list-detail-filters, 240px);\n background: var(--wx-bg-surface);\n border-right: 1px solid var(--wx-border-default);\n}\n\n.wx-list-detail__list {\n width: var(--wx-list-detail-list, 380px);\n flex: 0 0 var(--wx-list-detail-list, 380px);\n /* A row whose contents refuse to wrap must not widen the column. */\n min-width: 0;\n background: var(--wx-bg-surface);\n border-right: 1px solid var(--wx-border-default);\n}\n\n/* Alone, the list is the screen. */\n.wx-list-detail__list--alone {\n width: auto;\n flex: 1 1 auto;\n border-right: none;\n}\n\n.wx-list-detail__detail {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.wx-list-detail__empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--wx-space-10);\n height: 100%;\n color: var(--wx-text-muted);\n text-align: center;\n}\n</style>\n\n<style>\n/*\n * The panel is teleported, so its padding cannot be set from a scoped rule.\n *\n * Neither the body nor the sheet inside it insets anything. A drawer pads what it holds\n * because what it holds is usually a form or a note; this one holds a screen, and a screen\n * brings its own margins — two insets stacked put the same content further from the edge here\n * than the same content is on every other screen of the application.\n */\n.wx-list-detail__drawer .wx-drawer__body,\n.wx-list-detail__drawer .wx-drawer__content {\n padding: 0;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, ref, watch } from 'vue'\nimport type { LoadingProps } from './types'\n\ndefineOptions({ name: 'WxLoading' })\n\n/*\n * A veil over what is already there, rather than a spinner in place of it. The rows\n * of a table being refreshed are still the rows you were reading, and taking them\n * away to say so loses your place — twice, since they come back.\n */\nconst props = withDefaults(defineProps<LoadingProps>(), {\n loading: false,\n text: undefined,\n size: 'md',\n fullscreen: false,\n delay: 0,\n blur: false,\n ariaLabel: 'Loading',\n})\n\ndefineSlots<{\n /** What is being covered. Left out for a spinner on its own. */\n default?: () => unknown\n /** Replaces the spinner. */\n spinner?: () => unknown\n}>()\n\nconst showing = ref(props.delay === 0 && props.loading)\n\nlet timer: ReturnType<typeof setTimeout> | undefined\n\nwatch(\n [() => props.loading, () => props.delay],\n ([loading, delay]) => {\n clearTimeout(timer)\n\n if (!loading) {\n showing.value = false\n return\n }\n\n if (delay === 0) {\n showing.value = true\n return\n }\n\n timer = setTimeout(() => {\n showing.value = true\n }, delay)\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => clearTimeout(timer))\n\nconst classes = computed(() => [\n 'wx-loading',\n `wx-loading--${props.size}`,\n {\n 'wx-loading--fullscreen': props.fullscreen,\n 'wx-loading--blur': props.blur,\n 'is-loading': showing.value,\n },\n])\n</script>\n\n<template>\n <div :class=\"classes\">\n <div class=\"wx-loading__content\" :inert=\"showing || undefined\">\n <slot />\n </div>\n\n <div v-if=\"showing\" class=\"wx-loading__veil\" role=\"status\" :aria-label=\"ariaLabel\">\n <slot name=\"spinner\">\n <span class=\"wx-loading__spinner\" aria-hidden=\"true\" />\n </slot>\n <span v-if=\"text\" class=\"wx-loading__text\">{{ text }}</span>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-loading {\n position: relative;\n box-sizing: border-box;\n font-family: var(--wx-font-family-sans);\n}\n\n.wx-loading__content {\n /*\n * `inert` while the veil is up, so nothing underneath can be tabbed into or\n * clicked. A veil that only looks like it blocks is worse than none: it invites\n * the second click that sends the request twice.\n */\n transition: filter var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-loading--blur.is-loading .wx-loading__content {\n filter: blur(2px);\n}\n\n.wx-loading__veil {\n position: absolute;\n inset: 0;\n z-index: var(--wx-z-index-overlay);\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--wx-space-10);\n /*\n * The surface at three quarters, not the dialog scrim: this covers a panel while\n * it refreshes, and a scrim that dark says the page has been taken away.\n */\n background: color-mix(in srgb, var(--wx-bg-surface) 76%, transparent);\n color: var(--wx-text-muted);\n}\n\n.wx-loading--fullscreen .wx-loading__veil {\n position: fixed;\n}\n\n.wx-loading__text {\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-loading__spinner {\n display: block;\n width: var(--wx-loading-size);\n height: var(--wx-loading-size);\n border: var(--wx-loading-stroke) solid var(--wx-border-default);\n /* One quarter in the accent colour is what makes the rotation visible. */\n border-top-color: var(--wx-color-primary);\n border-radius: var(--wx-radius-full);\n animation: wx-loading-spin 0.7s linear infinite;\n}\n\n.wx-loading--sm {\n --wx-loading-size: 18px;\n --wx-loading-stroke: 2px;\n}\n\n.wx-loading--md {\n --wx-loading-size: 28px;\n --wx-loading-stroke: 3px;\n}\n\n.wx-loading--lg {\n --wx-loading-size: 40px;\n --wx-loading-stroke: 4px;\n}\n\n@keyframes wx-loading-spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n/*\n * Reduced motion stops the spin but keeps the ring: it is the only thing on screen\n * saying that anything is happening at all.\n */\n@media (prefers-reduced-motion: reduce) {\n .wx-loading__spinner {\n animation-duration: 2.4s;\n }\n\n .wx-loading__content {\n transition: none;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { MainProps } from './types'\n\ndefineOptions({ name: 'WxMain' })\n\nconst props = withDefaults(defineProps<MainProps>(), {\n padding: 'md',\n scroll: false,\n maxWidth: undefined,\n})\n\nconst maxWidth = computed(() => {\n if (props.maxWidth === undefined) return undefined\n return typeof props.maxWidth === 'number' ? `${props.maxWidth}px` : props.maxWidth\n})\n\nconst classes = computed(() => [\n 'wx-main',\n `wx-main--padding-${props.padding}`,\n { 'wx-main--scroll': props.scroll },\n])\n</script>\n\n<template>\n <main :class=\"classes\" :style=\"maxWidth ? { '--wx-main-max-width': maxWidth } : undefined\">\n <!--\n The inner element is what the cap applies to, so the padding and the background\n still run the full width of the column.\n -->\n <div class=\"wx-main__inner\">\n <slot />\n </div>\n </main>\n</template>\n\n<style scoped>\n.wx-main {\n /*\n * A column rather than a block, so that a screen asked to fill the page — a\n * `WxListDetail` under a `<router-view />`, say — actually can. As a block, the\n * inner element was content-tall and a `height: 100%` child measured itself\n * against that instead of against the column.\n */\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n flex: 1 1 auto;\n min-width: 0;\n min-height: 0;\n padding: var(--wx-main-padding, var(--wx-space-24));\n background: var(--wx-bg-body);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n}\n\n.wx-main--padding-none {\n --wx-main-padding: 0px;\n}\n\n.wx-main--padding-sm {\n --wx-main-padding: var(--wx-space-12);\n}\n\n.wx-main--padding-md {\n --wx-main-padding: var(--wx-space-24);\n}\n\n.wx-main--padding-lg {\n --wx-main-padding: var(--wx-space-40);\n}\n\n.wx-main--scroll {\n overflow-y: auto;\n}\n\n/*\n * The inner element fills the column, so a screen that asks for `height: 100%` —\n * a `WxListDetail` under a `<router-view />` — gets the column's height rather than\n * its own content's.\n */\n.wx-main__inner {\n flex: 1 1 auto;\n min-height: 0;\n width: 100%;\n max-width: var(--wx-main-max-width, none);\n /* The cap is centred, but only once there is a cap to centre. */\n margin-inline: auto;\n}\n\n/*\n * A scrolling column is the exception: there the inner element has to be as tall as\n * its content, or the padding at the bottom never makes it into the scrollable area\n * and the last card ends flush against the edge. Measured: 1288px of content in a\n * 216px column scrolls 1312px with this rule and 1300px without it.\n */\n.wx-main--scroll .wx-main__inner {\n flex: 0 0 auto;\n min-height: 100%;\n}\n\n/*\n * A screen that scrolls its own panes — an editor with a tree beside a preview — says so\n * with `data-wx-fill`, and the column stops growing with it.\n *\n * It has to be said from the inside, and it has to be said to the column: `height: 100%`\n * on the screen resolves against nothing while the inner element is as tall as its own\n * content, and the screen cannot reach its own ancestors any other way. With the inner\n * element stretched instead, its height is the column's, the screen's `height: 100%`\n * finally means something, and whatever the screen holds scrolls where it belongs rather\n * than taking the page with it.\n */\n.wx-main--scroll:has(> .wx-main__inner > [data-wx-fill]) > .wx-main__inner {\n flex: 1 1 auto;\n min-height: 0;\n}\n\n/*\n * The other shape: the page scrolls, not the column. A screen that has to be exactly as tall\n * as the window says so with the same attribute, and here there is no column to measure\n * against — the window is the answer, less whatever the shell keeps around the column.\n * `--wx-fill-height` is how the shell says how much that is.\n */\n.wx-main:not(.wx-main--scroll) > .wx-main__inner > :deep([data-wx-fill]) {\n height: var(--wx-fill-height, 100dvh);\n min-height: 0;\n}\n\n/*\n * A screen with a bar along its bottom is at least as tall as the column, whatever it holds.\n * The bar is pushed down by an auto margin, and an auto margin needs room to eat: without this\n * a form of one field puts its bar halfway up the page, where it reads as a stray card rather\n * than as the foot of the form. A screen that fills the window on purpose says so with\n * `data-wx-fill` and is already taller than this floor.\n */\n.wx-main:not(.wx-main--scroll) > .wx-main__inner:has(.wx-action-bar) > :deep(*) {\n min-height: var(--wx-fill-height, 100dvh);\n}\n\n/*\n * Padding is the first thing to give way on a small screen: 24px of margin around a\n * form is air on a desktop and a third of the line on a phone.\n */\n@media (max-width: 640px) {\n .wx-main--padding-lg {\n --wx-main-padding: var(--wx-space-16);\n }\n\n .wx-main--padding-md {\n --wx-main-padding: var(--wx-space-16);\n }\n\n .wx-main--padding-sm {\n --wx-main-padding: var(--wx-space-8);\n }\n}\n\n@media (max-width: 420px) {\n .wx-main--padding-lg,\n .wx-main--padding-md {\n --wx-main-padding: var(--wx-space-12);\n }\n}\n</style>\n","import { inject, type ComputedRef, type InjectionKey } from 'vue'\n\nexport type MenuMode = 'vertical' | 'horizontal'\nexport type MenuSize = 'sm' | 'md'\n\n/** What identifies an entry: whatever you would put in a route table. */\nexport type MenuValue = string | number\n\n/** What `WxMenu` hands down to everything inside it. */\nexport interface MenuContext {\n mode: ComputedRef<MenuMode>\n size: ComputedRef<MenuSize>\n /** The icon rail: labels hidden, submenus opening as flyouts. */\n collapsed: ComputedRef<boolean>\n /** The entry that is currently selected. */\n active: ComputedRef<MenuValue | undefined>\n /** The submenus the active entry sits in, outermost first. */\n trail: ComputedRef<MenuValue[]>\n select: (value: MenuValue, event: MouseEvent) => void\n isOpen: (value: MenuValue) => boolean\n setOpen: (value: MenuValue, open: boolean, ancestors: MenuValue[]) => void\n /**\n * Bumped when every open flyout should close — an entry inside one was chosen.\n * A panel cannot close on any click of its own: the branches inside it are opened\n * by clicking too, and that would shut the panel before they could unfold.\n */\n closeSignal: ComputedRef<number>\n closeFlyouts: () => void\n /**\n * An entry says where it sits so a submenu can tell it holds the active one —\n * the highlight on a collapsed branch, and what `autoExpand` follows.\n */\n register: (value: MenuValue, ancestors: MenuValue[]) => void\n unregister: (value: MenuValue) => void\n}\n\n/** What a `WxSubmenu` hands down to the entries it holds. */\nexport interface SubmenuContext {\n /** The submenus above this one, outermost first, including itself. */\n ancestors: MenuValue[]\n /** How deep the entries below sit — what the indent is counted from. */\n depth: number\n /**\n * Whether these entries are already inside a flyout panel. A panel is a fresh\n * surface: the depth restarts at its edge, and the branches in it open inline\n * rather than throwing a second panel beside the first.\n */\n inFlyout: boolean\n}\n\nexport const menuKey: InjectionKey<MenuContext> = Symbol('wx-menu')\nexport const submenuKey: InjectionKey<SubmenuContext> = Symbol('wx-submenu')\n\nexport function useMenu(): MenuContext | null {\n return inject(menuKey, null)\n}\n\nexport function useSubmenu(): SubmenuContext {\n return inject(submenuKey, { ancestors: [], depth: 0, inFlyout: false })\n}\n","<script setup lang=\"ts\">\nimport { computed, provide, ref, useId, watch } from 'vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport WxDropdown from '../Dropdown/Dropdown.vue'\nimport { submenuKey, useMenu, useSubmenu } from '../../composables/useMenu'\nimport '../../styles/menu.css'\nimport type { SubmenuEmits, SubmenuProps } from './types'\n\ndefineOptions({ name: 'WxSubmenu' })\n\nconst props = withDefaults(defineProps<SubmenuProps>(), {\n icon: undefined,\n title: undefined,\n disabled: false,\n})\n\nconst emit = defineEmits<SubmenuEmits>()\n\nconst menu = useMenu()\nconst parent = useSubmenu()\n\nconst panelId = useId()\n\nconst ancestors = computed(() => [...parent.ancestors, props.value])\n\nconst collapsed = computed(() => menu?.collapsed.value ?? false)\nconst isTrail = computed(() => menu?.trail.value.includes(props.value) ?? false)\n\n/**\n * Inline the branch drops open under its title; there is no room for that in a bar\n * or on an icon rail, so those open it as a panel beside the trigger instead.\n *\n * Only the first branch does, though. Inside a panel there is room again, and the\n * branches below open inline in it — a second panel hanging off the first is both\n * harder to keep under the pointer and harder to place near the edge of a screen.\n */\nconst asFlyout = computed(\n () => !parent.inFlyout && (collapsed.value || menu?.mode.value === 'horizontal'),\n)\n\nprovide(submenuKey, {\n /*\n * A submenu is an ancestor of everything below it, so it puts itself on the list\n * it hands down. The entries indent by one and report the branch they sit in.\n */\n get ancestors() {\n return ancestors.value\n },\n /* A panel is a fresh surface: what it holds is indented from its own edge. */\n get depth() {\n return asFlyout.value ? 0 : parent.depth + 1\n },\n get inFlyout() {\n return parent.inFlyout || asFlyout.value\n },\n})\n\n/*\n * A flyout is transient — it belongs to the pointer, not to the menu — so it keeps\n * its own state rather than joining `v-model:open`. Otherwise collapsing a sidebar\n * would throw open a panel for every branch that happened to be expanded.\n */\nconst flyoutOpen = ref(false)\n\nconst isOpen = computed(() =>\n asFlyout.value ? flyoutOpen.value : (menu?.isOpen(props.value) ?? false),\n)\n\nwatch(asFlyout, () => {\n flyoutOpen.value = false\n})\n\n/* An entry was chosen somewhere in the menu — every panel standing open has served. */\nwatch(\n () => menu?.closeSignal.value,\n () => {\n flyoutOpen.value = false\n },\n)\n\nconst flyoutSide = computed(() =>\n menu?.mode.value === 'horizontal' && parent.depth === 0 ? 'bottom' : 'right',\n)\n\nconst chevron = computed(() => {\n if (!asFlyout.value) return 'chevron-down'\n return flyoutSide.value === 'bottom' ? 'chevron-down' : 'chevron-right'\n})\n\nconst triggerClasses = computed(() => [\n 'wx-menu-row',\n {\n 'is-open': isOpen.value,\n 'is-trail': isTrail.value && !isOpen.value,\n 'is-disabled': props.disabled,\n },\n])\n\nfunction setOpen(open: boolean) {\n if (props.disabled) return\n if (asFlyout.value) flyoutOpen.value = open\n else menu?.setOpen(props.value, open, parent.ancestors)\n emit('toggle', open)\n}\n\nfunction onTriggerClick() {\n setOpen(!isOpen.value)\n}\n</script>\n\n<template>\n <li class=\"wx-submenu\" :class=\"{ 'is-open': isOpen }\">\n <wx-dropdown\n v-if=\"asFlyout\"\n class=\"wx-menu-flyout\"\n :open=\"isOpen\"\n :side=\"flyoutSide\"\n align=\"start\"\n :disabled=\"disabled\"\n :close-on-click=\"false\"\n @update:open=\"setOpen\"\n >\n <template #trigger>\n <button\n type=\"button\"\n :class=\"triggerClasses\"\n :disabled=\"disabled\"\n :style=\"{ '--wx-menu-depth': parent.depth }\"\n :title=\"collapsed ? title : undefined\"\n :aria-label=\"collapsed ? title : undefined\"\n >\n <span v-if=\"icon || $slots.icon\" class=\"wx-menu-row__icon\">\n <slot name=\"icon\">\n <wx-icon v-if=\"icon\" :name=\"icon\" />\n </slot>\n </span>\n <span class=\"wx-menu-row__label\">\n <slot name=\"title\">{{ title }}</slot>\n </span>\n <wx-icon class=\"wx-menu-row__chevron\" :name=\"chevron\" size=\"0.9em\" />\n </button>\n </template>\n\n <ul class=\"wx-menu-flyout__list\">\n <slot />\n </ul>\n </wx-dropdown>\n\n <template v-else>\n <button\n type=\"button\"\n :class=\"triggerClasses\"\n :disabled=\"disabled\"\n :style=\"{ '--wx-menu-depth': parent.depth }\"\n :aria-expanded=\"isOpen\"\n :aria-controls=\"panelId\"\n @click=\"onTriggerClick\"\n >\n <span v-if=\"icon || $slots.icon\" class=\"wx-menu-row__icon\">\n <slot name=\"icon\">\n <wx-icon v-if=\"icon\" :name=\"icon\" />\n </slot>\n </span>\n <span class=\"wx-menu-row__label\">\n <slot name=\"title\">{{ title }}</slot>\n </span>\n <wx-icon class=\"wx-menu-row__chevron\" :name=\"chevron\" size=\"0.9em\" />\n </button>\n\n <!--\n The panel animates between `0fr` and `1fr` rather than a measured height, so\n a branch of any length opens without JavaScript measuring it. `inert` keeps\n the links inside a closed branch out of the tab order while it is shut.\n -->\n <div :id=\"panelId\" class=\"wx-submenu__panel\" :class=\"{ 'is-open': isOpen }\" :inert=\"!isOpen\">\n <ul class=\"wx-submenu__list\">\n <slot />\n </ul>\n </div>\n </template>\n </li>\n</template>\n\n<style scoped>\n.wx-submenu {\n min-width: 0;\n /* Scoped, so a host stylesheet spacing `li + li` cannot step the branch down. */\n margin: 0;\n}\n\n.wx-submenu__panel {\n display: grid;\n grid-template-rows: 0fr;\n transition: grid-template-rows var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-submenu__panel.is-open {\n grid-template-rows: 1fr;\n}\n\n.wx-submenu__list {\n display: flex;\n flex-direction: column;\n gap: var(--wx-menu-gap, 2px);\n /* The grid row is what collapses; the list has to be allowed to be clipped by it. */\n min-height: 0;\n overflow: hidden;\n margin: 0;\n /*\n * Wider than the gap between siblings, because that gap is what a branch has to be\n * read against: with the same two pixels above it, the first child sat against its\n * own title and the pair looked like one row that had grown a second line.\n */\n padding: var(--wx-space-4) 0 0;\n list-style: none;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-submenu__panel {\n transition: none;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport {\n computed,\n nextTick,\n onMounted,\n provide,\n reactive,\n ref,\n useSlots,\n watch,\n type VNode,\n} from 'vue'\nimport WxSubmenu from '../Submenu/Submenu.vue'\nimport { menuKey, type MenuValue } from '../../composables/useMenu'\nimport { useElementWidth } from '../../composables/useElementWidth'\nimport { WxNodes, flattenNodes } from '../../internal/nodes'\nimport type { MenuEmits, MenuProps } from './types'\n\ndefineOptions({ name: 'WxMenu' })\n\nconst props = withDefaults(defineProps<MenuProps>(), {\n mode: 'vertical',\n size: 'md',\n overflow: 'menu',\n overflowTitle: 'More',\n collapsed: false,\n accordion: false,\n autoExpand: true,\n label: undefined,\n})\n\nconst emit = defineEmits<MenuEmits>()\n\n/** The branch the overflow moves into. Reserved: an entry may not use this value. */\nconst OVERFLOW = '__wx-menu-overflow'\n\nconst active = defineModel<MenuValue | undefined>({ default: undefined })\nconst openKeys = defineModel<MenuValue[]>('open', { default: () => [] })\n\n/* ---------------------------------------------------------------- overflow --- */\n\n/**\n * A bar gets whatever room the header has left over, which is rarely as much as the\n * sections need. Rather than clip them or scroll them out of sight, the entries that\n * do not fit move into a branch at the end of the bar.\n *\n * They *move*: every entry is rendered once, in the bar or in the branch, so it\n * registers its position once and the branch can report that it holds the page you\n * are on. That is why the entries are split as vnodes, rather than rendered twice\n * and hidden with CSS in whichever half is not wanted.\n */\nconst slots = useSlots()\nconst list = ref<HTMLElement | null>(null)\nconst listWidth = useElementWidth(list)\n\nconst splits = computed(() => props.mode === 'horizontal' && props.overflow === 'menu')\n\n/** How many entries stand in the bar. All of them, until a measurement says fewer. */\nconst fits = ref(Number.POSITIVE_INFINITY)\n\n/* While this is on everything is in the bar, and the branch is there to be measured. */\nconst measuring = ref(false)\n\n/* Every open flyout listens for this to change; nothing reads the number itself. */\nconst closeSignal = ref(0)\n\n/**\n * Whether anything is in the branch. It is read off the last measurement rather than\n * off the entries, because everything that asks the slot for its entries has to do\n * so while rendering — Vue tracks a slot's dependencies only there — and this is\n * wanted outside the template.\n */\nconst overflowing = ref(false)\n\n/*\n * Only the template reads these. Keep it that way: evaluating them is invoking the\n * slot, and that belongs in a render.\n */\nconst entries = computed<VNode[]>(() => (splits.value ? flattenNodes(slots.default?.() ?? []) : []))\n\n/* Which half an entry is in changes; `WxNodes` is what makes moving between them safe. */\nconst inBar = computed(() => entries.value.slice(0, fits.value))\nconst inBranch = computed(() => entries.value.slice(fits.value))\n\nfunction lengthOf(value: string) {\n const parsed = Number.parseFloat(value)\n return Number.isFinite(parsed) ? parsed : 0\n}\n\nasync function measure() {\n if (!splits.value) {\n fits.value = Number.POSITIVE_INFINITY\n overflowing.value = false\n return\n }\n\n /*\n * A panel hanging off the branch is stale the moment the bar is re-split, and it is\n * emptied by the measurement itself: everything goes back into the bar to be measured,\n * so a flyout left standing shows an empty list — which is what the open, empty \"More\"\n * was. It is shut before the bar is touched rather than after, so it never shows one.\n */\n closeSignal.value += 1\n\n /* Everything back in the bar, at its natural width, before anything is read. */\n measuring.value = true\n fits.value = Number.POSITIVE_INFINITY\n await nextTick()\n\n const el = list.value\n if (!el) {\n measuring.value = false\n return\n }\n\n const style = getComputedStyle(el)\n const gap = lengthOf(style.columnGap)\n const room = el.clientWidth - lengthOf(style.paddingLeft) - lengthOf(style.paddingRight)\n\n /* The branch is the last child; the entries are everything before it. */\n const children = [...el.children] as HTMLElement[]\n const branch = children.at(-1)\n const widths = children.slice(0, -1).map((child) => child.getBoundingClientRect().width)\n\n const needed = widths.reduce((total, width, index) => total + width + (index ? gap : 0), 0)\n\n if (needed <= room) {\n fits.value = widths.length\n } else {\n /* Room for the branch comes out of the budget before any entry is counted. */\n const budget = room - (branch?.getBoundingClientRect().width ?? 0) - gap\n let used = 0\n let count = 0\n\n for (const width of widths) {\n const next = used + width + (count ? gap : 0)\n if (next > budget) break\n used = next\n count += 1\n }\n\n fits.value = count\n }\n\n /* Counted off the elements just measured, so the slot is not asked again. */\n overflowing.value = fits.value < widths.length\n\n await nextTick()\n measuring.value = false\n}\n\nwatch(\n [listWidth, splits],\n () => {\n /* The bar changing width is what asks for a measurement — and measuring it back\n * to its natural width can change it again, which is not a new question. */\n if (!measuring.value) void measure()\n },\n { immediate: true },\n)\n\nonMounted(() => {\n /*\n * And again once the typeface has arrived. The first measurement is taken in the\n * fallback face, which is a few pixels narrower per label — enough, over a row of\n * them, to leave one entry in the bar that the real face has no room for.\n */\n void document.fonts?.ready.then(() => measure())\n})\n\n/** Where every entry sits: its value against the submenus above it. */\nconst positions = reactive(new Map<MenuValue, MenuValue[]>())\n\n/*\n * Where entries have been seen, which is not the same thing. A flyout unmounts what\n * it holds as it closes, so an entry that moved into the overflow branch stops\n * reporting its position the moment the panel shuts — and the bar still has to show\n * which branch the page you are on is in.\n */\nconst seen = new Map<MenuValue, MenuValue[]>()\n\nconst collapsed = computed(() => props.collapsed && props.mode === 'vertical')\n\nconst trail = computed(() => {\n if (active.value === undefined) return []\n\n const here = positions.get(active.value)\n if (here) {\n seen.set(active.value, here)\n return here\n }\n\n /*\n * Nothing on the page reports holding it. The one place an entry can be and not be\n * on the page is inside a shut overflow panel, so that is where it is — in front of\n * wherever it last said it sat.\n */\n const known = seen.get(active.value) ?? []\n return overflowing.value ? [OVERFLOW, ...known] : known\n})\n\nfunction setOpen(value: MenuValue, open: boolean, ancestors: MenuValue[]) {\n if (!open) {\n openKeys.value = openKeys.value.filter((key) => key !== value)\n return\n }\n\n /*\n * In accordion mode the branch that opens is the whole answer: its own ancestors\n * stay open, everything else closes. Listing the ancestors beats hunting for\n * siblings, which would mean knowing the depth of every open key.\n */\n openKeys.value = props.accordion\n ? [...ancestors, value]\n : [...openKeys.value.filter((key) => key !== value), value]\n}\n\nprovide(menuKey, {\n mode: computed(() => props.mode),\n size: computed(() => props.size),\n collapsed,\n active: computed(() => active.value),\n trail,\n select: (value, event) => {\n active.value = value\n emit('select', value, event)\n },\n isOpen: (value) => openKeys.value.includes(value),\n setOpen,\n closeSignal: computed(() => closeSignal.value),\n closeFlyouts: () => {\n closeSignal.value += 1\n },\n register: (value, ancestors) => positions.set(value, ancestors),\n unregister: (value) => positions.delete(value),\n})\n\n/*\n * Following the active entry rather than the click: a sidebar is normally rendered\n * against the current route, so the branch has to open for a value that arrived\n * with the page instead of through a trigger.\n */\nwatch(\n [trail, () => props.autoExpand],\n ([ancestors, autoExpand]) => {\n if (!autoExpand || ancestors.length === 0) return\n const missing = ancestors.filter((key) => !openKeys.value.includes(key))\n if (missing.length === 0) return\n openKeys.value = props.accordion ? [...ancestors] : [...openKeys.value, ...missing]\n },\n { immediate: true },\n)\n\nconst classes = computed(() => [\n 'wx-menu',\n `wx-menu--${props.mode}`,\n `wx-menu--${props.size}`,\n {\n 'wx-menu--collapsed': collapsed.value,\n 'wx-menu--overflow': splits.value,\n },\n])\n</script>\n\n<template>\n <ul ref=\"list\" :class=\"classes\" :aria-label=\"label\">\n <template v-if=\"splits\">\n <wx-nodes :nodes=\"inBar\" />\n\n <!--\n Rendered whether or not it is needed, because its own width is part of the\n sum that decides how many entries fit beside it.\n -->\n <wx-submenu\n :value=\"OVERFLOW\"\n class=\"wx-menu__overflow\"\n icon=\"more-horizontal\"\n :title=\"overflowTitle\"\n :hidden=\"inBranch.length === 0 && !measuring\"\n >\n <wx-nodes :nodes=\"inBranch\" />\n </wx-submenu>\n </template>\n\n <slot v-else />\n </ul>\n</template>\n\n<style scoped>\n/*\n * A list of links in a list of items, not `role=\"menu\"`. That role promises the\n * keyboard model of a desktop application menu — arrow keys, type-ahead, one tab\n * stop — and navigation that is really a list of links is easier to use, and to\n * read out, exactly as what it is.\n */\n.wx-menu {\n --wx-menu-row-height: 36px;\n --wx-menu-row-padding: var(--wx-space-10);\n --wx-menu-indent: var(--wx-space-16);\n --wx-menu-gap: 2px;\n\n display: flex;\n box-sizing: border-box;\n margin: 0;\n padding: var(--wx-space-8);\n list-style: none;\n background: transparent;\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-menu--sm {\n --wx-menu-row-height: 30px;\n --wx-menu-row-padding: var(--wx-space-8);\n --wx-menu-indent: var(--wx-space-12);\n\n font-size: var(--wx-font-size-xs);\n}\n\n.wx-menu--vertical {\n flex-direction: column;\n gap: var(--wx-menu-gap);\n width: 100%;\n}\n\n.wx-menu--horizontal {\n flex-direction: row;\n align-items: center;\n gap: var(--wx-space-2);\n overflow-x: auto;\n /* A bar that has to scroll should not show a bar of its own doing it. */\n scrollbar-width: none;\n}\n\n.wx-menu--horizontal::-webkit-scrollbar {\n display: none;\n}\n\n/*\n * A bar that folds its overflow away never scrolls: what does not fit has somewhere\n * to be. It is still clipped, for the frame in which everything is measured.\n *\n * `clip` rather than `hidden`, which only hides the scrollbar: a box with `hidden` is\n * still a scroll container, and the browser scrolls one to reveal a focused button\n * inside it. During the frame in which everything is back in the bar to be measured,\n * that leaves the bar pushed sideways, showing the middle of the row and no start to it.\n */\n.wx-menu--overflow {\n overflow-x: clip;\n}\n\n/*\n * The rail is a column of squares, so the padding around it comes down to the gap\n * that keeps them off the edge — the width of the sidebar is doing the spacing.\n */\n.wx-menu--collapsed {\n align-items: center;\n padding: var(--wx-space-6) var(--wx-space-4);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useMenu, useSubmenu } from '../../composables/useMenu'\nimport '../../styles/menu.css'\nimport type { MenuGroupProps } from './types'\n\ndefineOptions({ name: 'WxMenuGroup' })\n\nconst props = withDefaults(defineProps<MenuGroupProps>(), {\n title: undefined,\n})\n\nconst menu = useMenu()\nconst submenu = useSubmenu()\n\n/*\n * A group labels entries; it does not contain them the way a submenu does. It adds\n * no depth, so the entries under it line up with everything else at their level.\n */\n/*\n * The rail is what has no room. A flyout that opens beside it has the full width again, so\n * a group there keeps its heading and lines its entries up at the start like any other.\n */\nconst collapsed = computed(() => (menu?.collapsed.value ?? false) && !submenu.inFlyout)\nconst hasTitle = computed(() => Boolean(props.title || !collapsed.value))\n</script>\n\n<template>\n <li class=\"wx-menu-group\" :class=\"{ 'wx-menu-group--collapsed': collapsed }\">\n <span\n v-if=\"hasTitle && !collapsed\"\n class=\"wx-menu-group__title\"\n :style=\"{ '--wx-menu-depth': submenu.depth }\"\n >\n <slot name=\"title\">{{ title }}</slot>\n </span>\n <!-- On the rail there is no room for a heading, so the group becomes a rule. -->\n <span v-else class=\"wx-menu-group__rule\" role=\"separator\" />\n\n <ul class=\"wx-menu-group__list\">\n <slot />\n </ul>\n </li>\n</template>\n\n<style scoped>\n.wx-menu-group {\n display: flex;\n flex-direction: column;\n gap: var(--wx-menu-gap, 2px);\n min-width: 0;\n /*\n * Air above the heading, so a group reads as a break in the list — and nothing but\n * that air: a scoped rule, to outweigh a host stylesheet spacing `li + li`.\n */\n margin: var(--wx-space-8) 0 0;\n}\n\n.wx-menu-group:first-child {\n margin-top: 0;\n}\n\n.wx-menu-group__title {\n padding-inline: calc(\n var(--wx-menu-row-padding, 10px) + var(--wx-menu-depth, 0) * var(--wx-menu-indent, 16px)\n )\n var(--wx-menu-row-padding, 10px);\n padding-block: var(--wx-space-4);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n font-weight: var(--wx-font-weight-medium);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n}\n\n.wx-menu-group__rule {\n height: 1px;\n margin-block: var(--wx-space-4);\n margin-inline: var(--wx-space-6);\n background: var(--wx-border-muted);\n}\n\n.wx-menu-group__list {\n display: flex;\n flex-direction: column;\n gap: var(--wx-menu-gap, 2px);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.wx-menu-group--collapsed .wx-menu-group__list {\n align-items: center;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, watch } from 'vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport { useMenu, useSubmenu } from '../../composables/useMenu'\nimport '../../styles/menu.css'\nimport type { MenuItemEmits, MenuItemProps } from './types'\n\ndefineOptions({ name: 'WxMenuItem', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<MenuItemProps>(), {\n value: undefined,\n icon: undefined,\n label: undefined,\n href: undefined,\n target: undefined,\n as: undefined,\n disabled: false,\n})\n\nconst emit = defineEmits<MenuItemEmits>()\n\nconst menu = useMenu()\nconst submenu = useSubmenu()\n\nconst collapsed = computed(() => menu?.collapsed.value ?? false)\nconst isActive = computed(() => props.value !== undefined && menu?.active.value === props.value)\n\nconst tag = computed(() => props.as ?? (props.href ? 'a' : 'button'))\n\nconst nativeAttrs = computed(() => {\n const attrs: Record<string, unknown> = {}\n\n if (props.href) {\n attrs.href = props.disabled ? undefined : props.href\n attrs.target = props.target\n if (props.target === '_blank') attrs.rel = 'noopener noreferrer'\n } else if (!props.as) {\n attrs.type = 'button'\n attrs.disabled = props.disabled\n }\n\n if (props.disabled) {\n attrs['aria-disabled'] = 'true'\n if (props.href || props.as) attrs.tabindex = -1\n }\n\n /*\n * `aria-current` on a link, `aria-pressed` on a button: the entry is either the\n * page you are on or a control that is switched on, and a screen reader is told\n * which of the two this menu is made of.\n */\n if (isActive.value) {\n if (props.href || props.as) attrs['aria-current'] = 'page'\n else attrs['aria-pressed'] = 'true'\n }\n\n return attrs\n})\n\nconst classes = computed(() => [\n 'wx-menu-row',\n { 'is-active': isActive.value, 'is-disabled': props.disabled },\n])\n\n/*\n * The entry reports where it sits so its branch can be highlighted and expanded\n * without the menu walking the component tree to find out.\n */\nwatch(\n () => props.value,\n (value, previous) => {\n if (previous !== undefined) menu?.unregister(previous)\n if (value !== undefined) menu?.register(value, submenu.ancestors)\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n if (props.value !== undefined) menu?.unregister(props.value)\n})\n\nfunction onClick(event: MouseEvent) {\n if (props.disabled) {\n event.preventDefault()\n event.stopPropagation()\n return\n }\n\n emit('click', event)\n if (props.value !== undefined) menu?.select(props.value, event)\n\n /*\n * Choosing an entry is what a flyout was opened for, so it closes here rather than\n * on any click inside the panel — the branches in a panel are opened by clicking\n * too, and a panel that shut on that could never be opened past its first level.\n */\n menu?.closeFlyouts()\n}\n</script>\n\n<template>\n <li class=\"wx-menu-item\">\n <component\n :is=\"tag\"\n v-bind=\"{ ...nativeAttrs, ...$attrs }\"\n :class=\"classes\"\n :style=\"{ '--wx-menu-depth': submenu.depth }\"\n :title=\"collapsed ? label : undefined\"\n :aria-label=\"collapsed ? label : undefined\"\n @click=\"onClick\"\n >\n <span v-if=\"icon || $slots.icon\" class=\"wx-menu-row__icon\">\n <slot name=\"icon\">\n <wx-icon v-if=\"icon\" :name=\"icon\" />\n </slot>\n </span>\n\n <span class=\"wx-menu-row__label\">\n <slot>{{ label }}</slot>\n </span>\n\n <span v-if=\"$slots.trailing\" class=\"wx-menu-row__trailing\">\n <slot name=\"trailing\" />\n </span>\n </component>\n </li>\n</template>\n\n<style scoped>\n/*\n * The entry owns its margins, and says so from a scoped rule so that it outweighs a\n * host stylesheet spacing list items — VitePress puts 8px between every `li + li`,\n * and a CMS theme will have its own. Left alone, that walks a menu bar down the page\n * like a staircase and pulls a sidebar's rows apart.\n */\n.wx-menu-item {\n min-width: 0;\n margin: 0;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { PaginationEmits, PaginationProps } from './types'\n\ndefineOptions({ name: 'WxPagination' })\n\nconst props = withDefaults(defineProps<PaginationProps>(), {\n paginator: null,\n total: undefined,\n lastPage: undefined,\n siblings: 1,\n perPageOptions: () => [],\n showTotal: true,\n disabled: false,\n size: 'md',\n ariaLabel: 'Pagination',\n})\n\nconst emit = defineEmits<PaginationEmits>()\n\n/**\n * Both models fall back to the paginator, so `:paginator=\"page\"` alone is a working\n * component and `v-model:page` is there for state the caller would rather own.\n */\nconst page = defineModel<number | undefined>('page', { default: undefined })\nconst perPage = defineModel<number | undefined>('perPage', { default: undefined })\n\nconst currentPerPage = computed(() => perPage.value ?? props.paginator?.per_page ?? 15)\nconst total = computed(() => props.total ?? props.paginator?.total ?? 0)\n\nconst lastPage = computed(() => {\n if (props.lastPage !== undefined) return Math.max(1, props.lastPage)\n if (props.paginator) return Math.max(1, props.paginator.last_page)\n return Math.max(1, Math.ceil(total.value / currentPerPage.value))\n})\n\n/**\n * Clamped to what exists. A remembered page can outlive the result it belonged to —\n * a filter narrows eleven pages down to two — and a pagination with no page marked\n * current tells the reader they are nowhere.\n */\nconst currentPage = computed(() => {\n const asked = page.value ?? props.paginator?.current_page ?? 1\n return Math.min(Math.max(1, asked), lastPage.value)\n})\n\n/** Laravel counts these for us; without it they follow from the page and its size. */\nconst from = computed(() => {\n if (props.paginator) return props.paginator.from\n return total.value === 0 ? null : (currentPage.value - 1) * currentPerPage.value + 1\n})\n\nconst to = computed(() => {\n if (props.paginator) return props.paginator.to\n return total.value === 0 ? null : Math.min(total.value, currentPage.value * currentPerPage.value)\n})\n\ntype PageItem = { type: 'page'; value: number } | { type: 'gap'; value: string }\n\n/**\n * First and last are always reachable, the current page keeps `siblings` neighbours,\n * and what is skipped becomes an ellipsis. A gap of exactly one page is spelled out\n * instead — an ellipsis hiding a single number helps nobody.\n */\nconst items = computed<PageItem[]>(() => {\n const last = lastPage.value\n const current = currentPage.value\n const span = props.siblings\n\n const wanted = new Set<number>([1, last])\n for (let i = current - span; i <= current + span; i++) {\n if (i >= 1 && i <= last) wanted.add(i)\n }\n\n const numbers = [...wanted].sort((a, b) => a - b)\n const result: PageItem[] = []\n let previous = 0\n\n for (const value of numbers) {\n const distance = value - previous\n if (previous && distance === 2) result.push({ type: 'page', value: value - 1 })\n else if (previous && distance > 2) result.push({ type: 'gap', value: `gap-${value}` })\n result.push({ type: 'page', value })\n previous = value\n }\n\n return result\n})\n\nconst classes = computed(() => [\n 'wx-pagination',\n `wx-pagination--${props.size}`,\n { 'is-disabled': props.disabled },\n])\n\nfunction go(next: number) {\n const target = Math.min(Math.max(1, next), lastPage.value)\n if (props.disabled || target === currentPage.value) return\n page.value = target\n emit('change', { page: target, perPage: currentPerPage.value })\n}\n\n/**\n * A bigger page can put the current position past the end, so the size change also\n * moves back to the first page — the alternative is asking for a page that is not there.\n */\nfunction setPerPage(event: Event) {\n const value = Number((event.target as HTMLSelectElement).value)\n if (!Number.isFinite(value) || value === currentPerPage.value) return\n perPage.value = value\n page.value = 1\n emit('change', { page: 1, perPage: value })\n}\n</script>\n\n<template>\n <nav :class=\"classes\" :aria-label=\"ariaLabel\">\n <p v-if=\"showTotal\" class=\"wx-pagination__total\">\n <slot name=\"total\" :from=\"from\" :to=\"to\" :total=\"total\">\n <template v-if=\"from === null\">Nothing to show</template>\n <template v-else>{{ from }}–{{ to }} of {{ total }}</template>\n </slot>\n </p>\n\n <div class=\"wx-pagination__controls\">\n <label v-if=\"perPageOptions.length\" class=\"wx-pagination__per-page\">\n <span class=\"wx-pagination__per-page-label\">Per page</span>\n <select\n class=\"wx-pagination__select\"\n :value=\"currentPerPage\"\n :disabled=\"disabled\"\n @change=\"setPerPage\"\n >\n <option v-for=\"option in perPageOptions\" :key=\"option\" :value=\"option\">\n {{ option }}\n </option>\n </select>\n </label>\n\n <ul class=\"wx-pagination__list\">\n <li>\n <button\n class=\"wx-pagination__button wx-pagination__button--arrow\"\n type=\"button\"\n :disabled=\"disabled || currentPage <= 1\"\n aria-label=\"Previous page\"\n @click=\"go(currentPage - 1)\"\n >\n <svg viewBox=\"0 0 8 12\" aria-hidden=\"true\"><path d=\"M6.5 1 1.5 6l5 5\" /></svg>\n </button>\n </li>\n\n <li v-for=\"item in items\" :key=\"item.value\">\n <span v-if=\"item.type === 'gap'\" class=\"wx-pagination__gap\" aria-hidden=\"true\"\n >…</span\n >\n <button\n v-else\n class=\"wx-pagination__button\"\n type=\"button\"\n :class=\"{ 'is-current': item.value === currentPage }\"\n :disabled=\"disabled\"\n :aria-current=\"item.value === currentPage ? 'page' : undefined\"\n :aria-label=\"`Page ${item.value}`\"\n @click=\"go(item.value)\"\n >\n {{ item.value }}\n </button>\n </li>\n\n <li>\n <button\n class=\"wx-pagination__button wx-pagination__button--arrow\"\n type=\"button\"\n :disabled=\"disabled || currentPage >= lastPage\"\n aria-label=\"Next page\"\n @click=\"go(currentPage + 1)\"\n >\n <svg viewBox=\"0 0 8 12\" aria-hidden=\"true\"><path d=\"M1.5 1 6.5 6l-5 5\" /></svg>\n </button>\n </li>\n </ul>\n </div>\n </nav>\n</template>\n\n<style scoped>\n.wx-pagination {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--wx-space-12);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-pagination__total {\n margin: 0;\n padding: 0;\n}\n\n/*\n * Everything below wraps rather than overflows. On a phone the row of buttons is wider\n * than the screen well before the page count gets interesting, and a nav that runs off\n * the edge takes the last pages with it — including, often enough, the next arrow.\n */\n.wx-pagination__controls {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: flex-end;\n gap: var(--wx-space-12);\n margin-left: auto;\n}\n\n.wx-pagination__per-page {\n display: flex;\n align-items: center;\n gap: var(--wx-space-6);\n}\n\n.wx-pagination__per-page-label {\n white-space: nowrap;\n}\n\n.wx-pagination__select {\n height: var(--wx-pagination-size, 34px);\n padding: 0 var(--wx-space-8);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-control);\n color: var(--wx-text-default);\n font: inherit;\n cursor: pointer;\n}\n\n.wx-pagination__select:focus-visible {\n outline: none;\n border-color: var(--wx-border-focus);\n box-shadow: var(--wx-ring-focus);\n}\n\n/*\n * The same explicit resets the table needs. A host stylesheet that puts space between\n * consecutive list items — VitePress adds 8px, and every CSS framework has a rule of\n * its own — lands inside the row of buttons and steps them down one by one, because\n * the margin arrives on all but the first item.\n */\n.wx-pagination__list {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: flex-end;\n gap: var(--wx-space-4);\n margin: 0;\n padding: 0;\n border: 0;\n list-style: none;\n}\n\n.wx-pagination__list li {\n display: flex;\n align-items: center;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.wx-pagination__button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n min-width: var(--wx-pagination-size, 34px);\n height: var(--wx-pagination-size, 34px);\n padding: 0 var(--wx-space-8);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-control);\n color: var(--wx-text-default);\n font: inherit;\n cursor: pointer;\n transition:\n background var(--wx-duration-fast) var(--wx-easing-standard),\n border-color var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-pagination--sm {\n --wx-pagination-size: 28px;\n}\n\n.wx-pagination--lg {\n --wx-pagination-size: 42px;\n}\n\n.wx-pagination__button:hover:not(:disabled):not(.is-current) {\n border-color: var(--wx-border-strong);\n background: var(--wx-bg-fill);\n}\n\n.wx-pagination__button:focus-visible {\n outline: none;\n border-color: var(--wx-border-focus);\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-pagination__button.is-current {\n background: var(--wx-color-primary);\n border-color: var(--wx-color-primary);\n color: var(--wx-color-primary-contrast);\n cursor: default;\n}\n\n.wx-pagination__button:disabled {\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n.wx-pagination__button--arrow svg {\n width: 8px;\n height: 12px;\n fill: none;\n stroke: currentColor;\n stroke-width: 1.5;\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n\n.wx-pagination__gap {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: var(--wx-space-24);\n color: var(--wx-text-muted);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { ProgressProps } from './types'\n\ndefineOptions({ name: 'WxProgress' })\n\nconst props = withDefaults(defineProps<ProgressProps>(), {\n value: 0,\n max: 100,\n type: 'line',\n status: 'default',\n size: 'md',\n thickness: undefined,\n showValue: false,\n formatter: undefined,\n indeterminate: false,\n ariaLabel: undefined,\n})\n\ndefineSlots<{\n /** Replaces the figure — a count, a size, a time remaining. */\n default?: (props: { value: number; max: number; percent: number }) => unknown\n}>()\n\nconst max = computed(() => (props.max > 0 ? props.max : 100))\n\nconst value = computed(() => Math.min(Math.max(props.value, 0), max.value))\n\nconst percent = computed(() => Math.round((value.value / max.value) * 100))\n\nconst text = computed(() =>\n props.formatter ? props.formatter(value.value, max.value) : `${percent.value}%`,\n)\n\n/* The ring is drawn as one stroked circle, dashed to the share that is done. */\nconst RADIUS = 44\n\nconst circumference = computed(() => 2 * Math.PI * RADIUS)\n\nconst thickness = computed(() => {\n if (props.thickness !== undefined) return props.thickness\n if (props.type === 'circle') return { sm: 8, md: 10, lg: 12 }[props.size]\n return { sm: 4, md: 6, lg: 10 }[props.size]\n})\n\nconst classes = computed(() => [\n 'wx-progress',\n `wx-progress--${props.type}`,\n `wx-progress--${props.status}`,\n `wx-progress--${props.size}`,\n { 'wx-progress--indeterminate': props.indeterminate },\n])\n\n/*\n * An indeterminate bar reports no number: `aria-valuenow` left off is exactly how a\n * progressbar says \"busy, and I cannot tell you how far\".\n */\nconst aria = computed(() =>\n props.indeterminate\n ? { 'aria-valuemin': 0, 'aria-valuemax': max.value }\n : { 'aria-valuemin': 0, 'aria-valuemax': max.value, 'aria-valuenow': value.value },\n)\n</script>\n\n<template>\n <div :class=\"classes\" :style=\"{ '--wx-progress-thickness': `${thickness}px` }\">\n <div\n class=\"wx-progress__track\"\n role=\"progressbar\"\n :aria-label=\"ariaLabel\"\n :aria-valuetext=\"indeterminate ? undefined : text\"\n v-bind=\"aria\"\n >\n <template v-if=\"type === 'line'\">\n <div class=\"wx-progress__fill\" :style=\"{ width: `${percent}%` }\" />\n </template>\n\n <svg v-else class=\"wx-progress__ring\" viewBox=\"0 0 100 100\" aria-hidden=\"true\">\n <circle class=\"wx-progress__ring-track\" cx=\"50\" cy=\"50\" :r=\"RADIUS\" />\n <circle\n class=\"wx-progress__ring-fill\"\n cx=\"50\"\n cy=\"50\"\n :r=\"RADIUS\"\n :stroke-dasharray=\"circumference\"\n :stroke-dashoffset=\"\n indeterminate ? circumference * 0.75 : circumference * (1 - percent / 100)\n \"\n />\n </svg>\n </div>\n\n <div v-if=\"showValue || $slots.default\" class=\"wx-progress__value\">\n <slot :value=\"value\" :max=\"max\" :percent=\"percent\">{{ text }}</slot>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-progress {\n --wx-progress-accent: var(--wx-color-primary);\n\n display: flex;\n align-items: center;\n box-sizing: border-box;\n gap: var(--wx-space-10);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n}\n\n.wx-progress--success {\n --wx-progress-accent: var(--wx-color-success);\n}\n\n.wx-progress--warning {\n --wx-progress-accent: var(--wx-color-warning);\n}\n\n.wx-progress--danger {\n --wx-progress-accent: var(--wx-color-danger);\n}\n\n.wx-progress__value {\n flex: 0 0 auto;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n font-variant-numeric: tabular-nums;\n line-height: 1;\n}\n\n/* --- line --- */\n\n.wx-progress--line .wx-progress__track {\n position: relative;\n flex: 1 1 auto;\n height: var(--wx-progress-thickness, 6px);\n overflow: hidden;\n background: var(--wx-bg-fill);\n border-radius: var(--wx-radius-full);\n}\n\n.wx-progress__fill {\n height: 100%;\n background: var(--wx-progress-accent);\n border-radius: inherit;\n transition: width var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n/*\n * Indeterminate: a short bar travelling the length of the track. It is the same\n * element, so nothing switches shape when a real number finally arrives.\n */\n.wx-progress--line.wx-progress--indeterminate .wx-progress__fill {\n width: 35% !important;\n animation: wx-progress-travel 1.3s ease-in-out infinite;\n transition: none;\n}\n\n@keyframes wx-progress-travel {\n from {\n transform: translateX(-100%);\n }\n\n to {\n transform: translateX(286%);\n }\n}\n\n/* --- circle --- */\n\n.wx-progress--circle {\n display: inline-grid;\n place-items: center;\n}\n\n.wx-progress--circle .wx-progress__track,\n.wx-progress--circle .wx-progress__value {\n grid-area: 1 / 1;\n}\n\n.wx-progress--circle .wx-progress__track {\n width: var(--wx-progress-ring, 96px);\n height: var(--wx-progress-ring, 96px);\n}\n\n.wx-progress--circle.wx-progress--sm {\n --wx-progress-ring: 56px;\n}\n\n.wx-progress--circle.wx-progress--md {\n --wx-progress-ring: 96px;\n}\n\n.wx-progress--circle.wx-progress--lg {\n --wx-progress-ring: 140px;\n}\n\n.wx-progress__ring {\n width: 100%;\n height: 100%;\n /* Twelve o'clock, clockwise — which is where a reader expects it to start. */\n transform: rotate(-90deg);\n}\n\n.wx-progress__ring-track,\n.wx-progress__ring-fill {\n fill: none;\n stroke-width: var(--wx-progress-thickness, 10px);\n}\n\n.wx-progress__ring-track {\n stroke: var(--wx-bg-fill);\n}\n\n.wx-progress__ring-fill {\n stroke: var(--wx-progress-accent);\n stroke-linecap: round;\n transition: stroke-dashoffset var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-progress--circle.wx-progress--indeterminate .wx-progress__ring {\n animation: wx-progress-spin 1.1s linear infinite;\n}\n\n.wx-progress--circle.wx-progress--indeterminate .wx-progress__ring-fill {\n transition: none;\n}\n\n@keyframes wx-progress-spin {\n from {\n transform: rotate(-90deg);\n }\n\n to {\n transform: rotate(270deg);\n }\n}\n\n.wx-progress--circle .wx-progress__value {\n font-size: var(--wx-font-size-sm);\n font-weight: var(--wx-font-weight-semibold);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-progress__fill,\n .wx-progress__ring,\n .wx-progress__ring-fill {\n animation: none;\n transition: none;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { ProseProps } from './types'\n\ndefineOptions({ name: 'WxProse' })\n\nconst props = withDefaults(defineProps<ProseProps>(), {\n html: undefined,\n size: 'md',\n as: 'div',\n})\n\nconst classes = computed(() => ['wx-prose', `wx-prose--${props.size}`])\n</script>\n\n<template>\n <component :is=\"as\" :class=\"classes\">\n <!--\n The markup goes into a plain element rather than onto the dynamic tag itself:\n `v-html` on `<component :is>` is meaningless when `as` names a component, and\n every rule below matches descendants, so the extra div changes nothing visually.\n\n The rule is right that this is where an XSS would land, and there is nothing the\n component can do about it: what counts as allowed markup — an embed, an inline\n style, a class — is the application's decision, not a design system's. The prop\n is documented as server-sanitised, and this is the line that trusts it.\n -->\n <!-- eslint-disable-next-line vue/no-v-html -->\n <div v-if=\"html !== undefined\" class=\"wx-prose__content\" v-html=\"html\"></div>\n <slot v-else />\n </component>\n</template>\n\n<style scoped>\n/*\n * Every rule is a `:deep` one on purpose: the markup usually arrives through `v-html`\n * and therefore carries no scope attribute of its own.\n */\n.wx-prose {\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n font-size: var(--wx-prose-font-size, var(--wx-font-size-md));\n line-height: var(--wx-font-line-height-relaxed);\n /* The rhythm between blocks: one variable, so a caller can tighten the whole block. */\n --wx-prose-flow: var(--wx-space-16);\n}\n\n.wx-prose--sm {\n --wx-prose-font-size: var(--wx-font-size-sm);\n --wx-prose-flow: var(--wx-space-12);\n}\n\n.wx-prose--lg {\n --wx-prose-font-size: var(--wx-font-size-lg);\n --wx-prose-flow: var(--wx-space-18);\n}\n\n/* The rhythm: every block carries the gap below it, the last one drops it again. */\n.wx-prose :deep(p),\n.wx-prose :deep(ul),\n.wx-prose :deep(ol),\n.wx-prose :deep(dl),\n.wx-prose :deep(blockquote),\n.wx-prose :deep(pre),\n.wx-prose :deep(figure),\n.wx-prose :deep(table) {\n margin: 0 0 var(--wx-prose-flow);\n}\n\n.wx-prose :deep(:last-child) {\n margin-bottom: 0;\n}\n\n/* headings */\n.wx-prose :deep(h1),\n.wx-prose :deep(h2),\n.wx-prose :deep(h3),\n.wx-prose :deep(h4),\n.wx-prose :deep(h5),\n.wx-prose :deep(h6) {\n /* Air above a heading, tight to the paragraph it introduces. */\n margin: var(--wx-space-32) 0 var(--wx-space-12);\n color: var(--wx-text-strong);\n font-weight: var(--wx-font-weight-semibold);\n line-height: var(--wx-font-line-height-tight);\n text-wrap: balance;\n}\n\n.wx-prose :deep(h1) {\n font-size: var(--wx-font-size-3xl);\n font-weight: var(--wx-font-weight-bold);\n}\n\n.wx-prose :deep(h2) {\n font-size: var(--wx-font-size-2xl);\n}\n\n.wx-prose :deep(h3) {\n font-size: var(--wx-font-size-xl);\n}\n\n.wx-prose :deep(h4) {\n font-size: var(--wx-font-size-lg);\n}\n\n.wx-prose :deep(h5),\n.wx-prose :deep(h6) {\n font-size: var(--wx-font-size-md);\n}\n\n.wx-prose :deep(:first-child) {\n margin-top: 0;\n}\n\n.wx-prose :deep(a) {\n color: var(--wx-text-link);\n text-decoration: underline;\n text-underline-offset: 0.2em;\n}\n\n.wx-prose :deep(a:hover) {\n color: var(--wx-color-primary-hover);\n}\n\n.wx-prose :deep(strong),\n.wx-prose :deep(b) {\n color: var(--wx-text-strong);\n font-weight: var(--wx-font-weight-semibold);\n}\n\n.wx-prose :deep(small) {\n font-size: var(--wx-font-size-sm);\n color: var(--wx-text-muted);\n}\n\n.wx-prose :deep(mark) {\n padding: 0 2px;\n background: var(--wx-color-warning-soft);\n border-radius: var(--wx-radius-none);\n color: inherit;\n}\n\n/* lists */\n.wx-prose :deep(ul),\n.wx-prose :deep(ol) {\n padding-left: var(--wx-space-24);\n}\n\n.wx-prose :deep(li + li) {\n margin-top: var(--wx-space-6);\n}\n\n.wx-prose :deep(li > ul),\n.wx-prose :deep(li > ol) {\n margin-top: var(--wx-space-6);\n}\n\n.wx-prose :deep(ul) {\n list-style: disc;\n}\n\n.wx-prose :deep(ol) {\n list-style: decimal;\n}\n\n.wx-prose :deep(li::marker) {\n color: var(--wx-text-muted);\n}\n\n.wx-prose :deep(dt) {\n color: var(--wx-text-strong);\n font-weight: var(--wx-font-weight-semibold);\n}\n\n.wx-prose :deep(dd) {\n margin: 0 0 var(--wx-space-8);\n color: var(--wx-text-muted);\n}\n\n/* quotes and rules */\n.wx-prose :deep(blockquote) {\n padding: var(--wx-space-4) var(--wx-space-16);\n border-left: 3px solid var(--wx-color-primary);\n color: var(--wx-text-muted);\n}\n\n.wx-prose :deep(hr) {\n height: 0;\n margin: var(--wx-space-24) 0;\n border: none;\n border-top: 1px solid var(--wx-border-default);\n}\n\n/* code */\n.wx-prose :deep(code) {\n padding: 1px 5px;\n background: var(--wx-bg-fill);\n border-radius: var(--wx-radius-xs);\n font-family: var(--wx-font-family-mono);\n font-size: 0.9em;\n}\n\n.wx-prose :deep(pre) {\n padding: var(--wx-space-14) var(--wx-space-16);\n background: var(--wx-bg-muted);\n border-radius: var(--wx-radius-sm);\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-sm);\n line-height: var(--wx-font-line-height-normal);\n overflow-x: auto;\n}\n\n.wx-prose :deep(pre code) {\n padding: 0;\n background: none;\n font-size: inherit;\n}\n\n/* media */\n.wx-prose :deep(img),\n.wx-prose :deep(video) {\n max-width: 100%;\n height: auto;\n border-radius: var(--wx-radius-sm);\n}\n\n.wx-prose :deep(figcaption) {\n margin-top: var(--wx-space-8);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n text-align: center;\n}\n\n.wx-prose :deep(iframe) {\n max-width: 100%;\n border: none;\n border-radius: var(--wx-radius-sm);\n}\n\n/*\n * A pasted table is usually wider than the column it lands in, so it scrolls inside\n * its own box instead of pushing the page sideways.\n */\n.wx-prose :deep(table) {\n display: block;\n width: 100%;\n max-width: 100%;\n border-collapse: collapse;\n font-size: var(--wx-font-size-sm);\n overflow-x: auto;\n}\n\n.wx-prose :deep(th),\n.wx-prose :deep(td) {\n padding: var(--wx-space-8) var(--wx-space-12);\n border: 1px solid var(--wx-border-default);\n text-align: start;\n vertical-align: top;\n}\n\n.wx-prose :deep(th) {\n background: var(--wx-bg-subtle);\n color: var(--wx-text-strong);\n font-weight: var(--wx-font-weight-semibold);\n white-space: nowrap;\n}\n\n.wx-prose :deep(caption) {\n margin-bottom: var(--wx-space-8);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n text-align: start;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, inject } from 'vue'\nimport { radioGroupKey, useFormField, type ChoiceValue } from '../../composables/useFormField'\nimport type { RadioEmits, RadioProps } from './types'\nimport { useControlAttrs } from '../../composables/useControlAttrs'\n\ndefineOptions({ name: 'WxRadio', inheritAttrs: false })\n\n/* `class` and `style` belong to the control; the rest belongs to its input. */\nconst { rootAttrs, controlAttrs } = useControlAttrs()\n\nconst props = withDefaults(defineProps<RadioProps>(), {\n label: undefined,\n disabled: undefined,\n size: undefined,\n id: undefined,\n name: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<RadioEmits>()\n\nconst model = defineModel<ChoiceValue>({ default: null })\n\nconst group = inject(radioGroupKey, null)\nconst field = useFormField(props)\n\nconst checked = computed(() =>\n group ? group.modelValue.value === props.value : model.value === props.value,\n)\n\nconst disabled = computed(() => props.disabled || group?.disabled.value || field.disabled.value)\nconst size = computed(() => props.size ?? group?.size.value ?? field.size.value)\n\nconst classes = computed(() => [\n 'wx-radio',\n `wx-radio--${size.value}`,\n { 'is-checked': checked.value, 'is-disabled': disabled.value },\n])\n\nfunction onChange() {\n if (group) group.toggle(props.value, true)\n else model.value = props.value\n emit('change', props.value)\n}\n</script>\n\n<template>\n <label :class=\"classes\" v-bind=\"rootAttrs\">\n <input\n :id=\"field.id.value\"\n v-bind=\"controlAttrs\"\n class=\"wx-radio__native\"\n type=\"radio\"\n :name=\"name ?? group?.name.value\"\n :checked=\"checked\"\n :disabled=\"disabled\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"field.describedBy.value\"\n @change=\"onChange\"\n />\n\n <span class=\"wx-radio__box\" aria-hidden=\"true\">\n <svg class=\"wx-radio__mark\" viewBox=\"0 0 20 20\">\n <circle class=\"wx-radio__ring\" cx=\"10\" cy=\"10\" r=\"9.5\" />\n <circle class=\"wx-radio__dot\" cx=\"10\" cy=\"10\" r=\"4\" />\n </svg>\n </span>\n\n <span v-if=\"label || $slots.default\" class=\"wx-radio__label\">\n <slot>{{ label }}</slot>\n </span>\n </label>\n</template>\n\n<style scoped>\n.wx-radio {\n display: inline-flex;\n align-items: center;\n gap: var(--wx-space-8);\n cursor: pointer;\n user-select: none;\n color: var(--wx-text-default);\n}\n\n.wx-radio.is-disabled {\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n.wx-radio__native {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n border: 0;\n}\n\n/*\n * The box only holds the size and the focus ring; the circles are drawn inside it. A CSS\n * border plus a centred child cannot stay concentric at a fractional device pixel ratio —\n * Windows at 125% or 150% rounds the 1px border to a whole device pixel on each side\n * independently, which moves the content box off the centre of the border box and takes\n * the dot with it. Ring and dot as two circles on one origin cannot drift apart: the\n * renderer resolves both against real geometry and antialiases, instead of snapping boxes.\n */\n.wx-radio__box {\n display: block;\n flex: 0 0 auto;\n box-sizing: border-box;\n width: var(--wx-radio-size, 20px);\n height: var(--wx-radio-size, 20px);\n border-radius: var(--wx-radius-full);\n transition: box-shadow var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-radio--sm {\n --wx-radio-size: 16px;\n font-size: var(--wx-font-size-control-sm);\n}\n\n.wx-radio--md {\n --wx-radio-size: 20px;\n /* A tick beside a label is a choice in a list, and reads at the list size. */\n font-size: var(--wx-font-size-control-md);\n}\n\n.wx-radio--lg {\n --wx-radio-size: 24px;\n font-size: var(--wx-font-size-control-lg);\n}\n\n/* The ring's outer half of stroke sits on the viewport edge, so it must not be clipped. */\n.wx-radio__mark {\n display: block;\n width: 100%;\n height: 100%;\n overflow: visible;\n}\n\n/*\n * `non-scaling-stroke` keeps the ring one pixel wide at every size, the way the checkbox\n * border is, instead of thinning to 0.8px on `sm` and thickening to 1.2px on `lg`.\n */\n.wx-radio__ring {\n fill: var(--wx-bg-surface);\n stroke: var(--wx-border-strong);\n stroke-width: 1;\n vector-effect: non-scaling-stroke;\n transition: stroke var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-radio__dot {\n fill: var(--wx-color-primary);\n transform: scale(0);\n transform-box: fill-box;\n transform-origin: center;\n transition: transform var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-radio:hover:not(.is-disabled) .wx-radio__ring {\n stroke: var(--wx-color-primary);\n}\n\n.wx-radio.is-checked .wx-radio__ring {\n stroke: var(--wx-color-primary);\n}\n\n.wx-radio.is-checked .wx-radio__dot {\n transform: scale(1);\n}\n\n.wx-radio.is-disabled .wx-radio__ring {\n fill: var(--wx-bg-disabled);\n stroke: var(--wx-border-default);\n}\n\n.wx-radio.is-disabled .wx-radio__dot {\n fill: var(--wx-color-primary-disabled);\n}\n\n.wx-radio__native:focus-visible + .wx-radio__box {\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-radio__native:focus-visible + .wx-radio__box .wx-radio__ring {\n stroke: var(--wx-color-primary);\n}\n\n.wx-radio__label {\n line-height: var(--wx-font-line-height-normal);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-radio__box,\n .wx-radio__ring,\n .wx-radio__dot {\n transition: none;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, provide } from 'vue'\nimport {\n radioGroupKey,\n useFormField,\n useId,\n type ChoiceValue,\n} from '../../composables/useFormField'\nimport WxRadio from '../Radio/Radio.vue'\nimport type { RadioGroupEmits, RadioGroupProps } from './types'\n\ndefineOptions({ name: 'WxRadioGroup' })\n\nconst props = withDefaults(defineProps<RadioGroupProps>(), {\n options: undefined,\n disabled: undefined,\n size: undefined,\n name: undefined,\n inline: false,\n})\n\nconst emit = defineEmits<RadioGroupEmits>()\n\nconst model = defineModel<ChoiceValue>({ default: null })\n\nconst field = useFormField(props)\nconst fallbackName = useId('wx-radio-group')\n\n/** A group cannot be the target of a `for`, so the item label becomes a span. */\nfield.item?.registerLabelTarget(undefined)\n\nconst disabled = computed(() => props.disabled ?? field.disabled.value)\nconst size = computed(() => props.size ?? field.size.value)\n\n/**\n * Radios sharing a `name` are one roving-tabindex group in the browser, which is\n * what gives arrow-key navigation for free — so a name is always set.\n */\nconst name = computed(() => props.name ?? fallbackName)\n\nfunction toggle(value: ChoiceValue) {\n if (model.value === value) return\n model.value = value\n emit('change', value)\n}\n\nprovide(radioGroupKey, {\n name,\n modelValue: computed(() => model.value),\n disabled,\n size,\n toggle,\n})\n</script>\n\n<template>\n <div\n :class=\"['wx-radio-group', { 'wx-radio-group--inline': inline }]\"\n role=\"radiogroup\"\n :aria-labelledby=\"field.item ? `${field.item.id.value}-label` : undefined\"\n :aria-describedby=\"field.describedBy.value\"\n >\n <slot>\n <wx-radio\n v-for=\"option in options\"\n :key=\"String(option.value)\"\n :value=\"option.value\"\n :label=\"option.label\"\n :disabled=\"option.disabled\"\n />\n </slot>\n </div>\n</template>\n\n<style scoped>\n.wx-radio-group {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n}\n\n.wx-radio-group--inline {\n flex-direction: row;\n flex-wrap: wrap;\n gap: var(--wx-space-16);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport { useFormField } from '../../composables/useFormField'\nimport type { RateEmits, RateProps } from './types'\n\ndefineOptions({ name: 'WxRate', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<RateProps>(), {\n max: 5,\n allowHalf: false,\n clearable: true,\n showValue: false,\n readonly: false,\n disabled: undefined,\n size: undefined,\n id: undefined,\n name: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<RateEmits>()\n\nconst model = defineModel<number>({ default: 0 })\n\nconst field = useFormField(props)\nconst hovered = ref<number | null>(null)\n\nconst interactive = computed(() => !field.disabled.value && !props.readonly)\n\n/** What the stars show right now: the hovered value while pointing, the model otherwise. */\nconst shown = computed(() => hovered.value ?? model.value ?? 0)\n\nconst stars = computed(() =>\n Array.from({ length: props.max }, (_, index) => {\n const position = index + 1\n const fill = Math.min(Math.max(shown.value - index, 0), 1)\n return { position, full: fill >= 1, half: fill > 0 && fill < 1 }\n }),\n)\n\nconst classes = computed(() => [\n 'wx-rate',\n `wx-rate--${field.size.value}`,\n { 'is-disabled': field.disabled.value, 'is-readonly': props.readonly },\n])\n\n/** Halves come from the pointer landing on the left side of a star. */\nfunction valueAt(position: number, event: MouseEvent): number {\n if (!props.allowHalf) return position\n const target = event.currentTarget as HTMLElement\n const { left, width } = target.getBoundingClientRect()\n return event.clientX - left < width / 2 ? position - 0.5 : position\n}\n\n/** `toggle` is what makes clicking the current value clear it — the arrow keys must not. */\nfunction set(value: number, toggle = false) {\n const next = toggle && props.clearable && model.value === value ? 0 : value\n if (next === model.value) return\n model.value = next\n emit('change', next)\n}\n\nfunction onClick(position: number, event: MouseEvent) {\n if (!interactive.value) return\n set(valueAt(position, event), true)\n}\n\nfunction onHover(position: number, event: MouseEvent) {\n if (!interactive.value) return\n hovered.value = valueAt(position, event)\n}\n\nfunction onKeydown(event: KeyboardEvent) {\n if (!interactive.value) return\n const step = props.allowHalf ? 0.5 : 1\n const current = model.value ?? 0\n\n if (event.key === 'ArrowRight' || event.key === 'ArrowUp') {\n event.preventDefault()\n set(Math.min(current + step, props.max))\n } else if (event.key === 'ArrowLeft' || event.key === 'ArrowDown') {\n event.preventDefault()\n set(Math.max(current - step, 0))\n } else if (event.key === 'Home') {\n event.preventDefault()\n set(0)\n } else if (event.key === 'End') {\n event.preventDefault()\n set(props.max)\n }\n}\n</script>\n\n<template>\n <div\n :id=\"field.id.value\"\n v-bind=\"$attrs\"\n :class=\"classes\"\n role=\"slider\"\n :tabindex=\"interactive ? 0 : -1\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"field.describedBy.value\"\n :aria-valuemin=\"0\"\n :aria-valuemax=\"max\"\n :aria-valuenow=\"model ?? 0\"\n :aria-readonly=\"readonly || undefined\"\n :aria-disabled=\"field.disabled.value || undefined\"\n @keydown=\"onKeydown\"\n @mouseleave=\"hovered = null\"\n >\n <span\n v-for=\"star in stars\"\n :key=\"star.position\"\n class=\"wx-rate__star\"\n :class=\"{ 'is-full': star.full, 'is-half': star.half }\"\n @click=\"onClick(star.position, $event)\"\n @mousemove=\"onHover(star.position, $event)\"\n >\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path\n class=\"wx-rate__outline\"\n d=\"M12 3.5l2.6 5.3 5.9.9-4.2 4.1 1 5.8-5.3-2.8-5.3 2.8 1-5.8-4.2-4.1 5.9-.9z\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linejoin=\"round\"\n />\n <path\n class=\"wx-rate__fill\"\n d=\"M12 3.5l2.6 5.3 5.9.9-4.2 4.1 1 5.8-5.3-2.8-5.3 2.8 1-5.8-4.2-4.1 5.9-.9z\"\n fill=\"currentColor\"\n />\n </svg>\n </span>\n\n <span v-if=\"showValue\" class=\"wx-rate__value\">{{ model ?? 0 }}</span>\n\n <input v-if=\"name\" type=\"hidden\" :name=\"name\" :value=\"model ?? 0\" />\n </div>\n</template>\n\n<style scoped>\n.wx-rate {\n display: inline-flex;\n align-items: center;\n gap: var(--wx-space-2);\n color: var(--wx-border-strong);\n}\n\n.wx-rate:focus-visible {\n outline: none;\n border-radius: var(--wx-radius-xs);\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-rate--sm {\n --wx-rate-size: 18px;\n font-size: var(--wx-font-size-control-sm);\n}\n\n.wx-rate--md {\n --wx-rate-size: 22px;\n font-size: var(--wx-font-size-control-md);\n}\n\n.wx-rate--lg {\n --wx-rate-size: 28px;\n font-size: var(--wx-font-size-control-lg);\n}\n\n.wx-rate__star {\n display: inline-flex;\n width: var(--wx-rate-size, 22px);\n height: var(--wx-rate-size, 22px);\n cursor: pointer;\n}\n\n.wx-rate.is-disabled .wx-rate__star,\n.wx-rate.is-readonly .wx-rate__star {\n cursor: default;\n}\n\n.wx-rate.is-disabled {\n opacity: 0.6;\n}\n\n.wx-rate__star svg {\n width: 100%;\n height: 100%;\n overflow: visible;\n}\n\n/* The filled star is clipped to nothing, then revealed whole or by half. */\n.wx-rate__fill {\n color: var(--wx-color-warning);\n clip-path: inset(0 100% 0 0);\n transition: clip-path var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-rate__star.is-full .wx-rate__fill {\n clip-path: inset(0);\n}\n\n.wx-rate__star.is-half .wx-rate__fill {\n clip-path: inset(0 50% 0 0);\n}\n\n.wx-rate__star.is-full,\n.wx-rate__star.is-half {\n color: var(--wx-color-warning);\n}\n\n.wx-rate__value {\n margin-left: var(--wx-space-6);\n color: var(--wx-text-muted);\n font-variant-numeric: tabular-nums;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-rate__fill {\n transition: none;\n }\n}\n</style>\n","<script setup lang=\"ts\" generic=\"T\">\nimport { computed, nextTick, ref, useSlots, useTemplateRef } from 'vue'\nimport { VueDraggable } from 'vue-draggable-plus'\nimport WxIcon from '../Icon/Icon.vue'\nimport type { SortableListEmits, SortableListProps, SortableVia } from './types'\n\ndefineOptions({ name: 'WxSortableList' })\n\nconst props = withDefaults(defineProps<SortableListProps<T>>(), {\n title: undefined,\n handle: 'grip',\n itemKey: 'id',\n itemLabel: undefined,\n group: undefined,\n disabled: false,\n size: 'md',\n plain: false,\n hoverable: false,\n emptyText: 'Nothing here yet',\n dragLabel: 'Reorder',\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<SortableListEmits<T>>()\n\ndefineSlots<{\n /** Replaces the title. */\n header?: () => unknown\n /** The end of the heading — a search button, a menu, whatever the list can do. */\n extra?: () => unknown\n /** One row. */\n default?: (props: { item: T; index: number }) => unknown\n /** The end of a row, where the buttons that act on it go. */\n actions?: (props: { item: T; index: number }) => unknown\n /** Shown in place of an empty list. */\n empty?: () => unknown\n}>()\n\nconst items = defineModel<T[]>({ default: () => [] })\n\nconst slots = useSlots()\n\nconst root = useTemplateRef<HTMLElement>('root')\n\nconst hasHeader = computed(() => Boolean(props.title || slots.header || slots.extra))\n\n/*\n * The grip is ours by default, because a list whose rows can only be moved by dragging\n * them bodily is a list a keyboard cannot reorder at all — and because the thing that\n * starts a drag has to look like it does. `handle` gives that up to the caller: the whole\n * row, or a selector for a button of their own.\n */\nconst grip = computed(() => props.handle === 'grip')\n\nconst handleSelector = computed(() => {\n if (props.handle === 'grip') return '.wx-sortable-list__grip'\n if (props.handle === 'row') return undefined\n return props.handle\n})\n\nconst classes = computed(() => [\n 'wx-sortable-list',\n `wx-sortable-list--${props.size}`,\n {\n 'is-plain': props.plain,\n 'is-hoverable': props.hoverable,\n 'is-disabled': props.disabled,\n 'is-headed': hasHeader.value,\n },\n])\n\nfunction keyOf(item: T, index: number) {\n if (typeof props.itemKey === 'function') return props.itemKey(item, index)\n if (item && typeof item === 'object') {\n const value = (item as Record<string, unknown>)[props.itemKey]\n if (typeof value === 'string' || typeof value === 'number') return value\n }\n return index\n}\n\n/**\n * What to call a row when there is nothing but the item itself to go on: the grip needs\n * an accessible name, and so does everything a keyboard move says out loud.\n */\nfunction labelOf(item: T, index: number) {\n if (typeof props.itemLabel === 'function') return props.itemLabel(item, index)\n\n if (item && typeof item === 'object') {\n if (props.itemLabel) {\n const named = (item as Record<string, unknown>)[props.itemLabel]\n if (typeof named === 'string' && named.trim()) return named\n if (typeof named === 'number') return String(named)\n }\n\n const record = item as Record<string, unknown>\n for (const field of ['title', 'name', 'label']) {\n const value = record[field]\n if (typeof value === 'string' && value) return value\n }\n return `Item ${index + 1}`\n }\n return String(item)\n}\n\nfunction nameAt(index: number) {\n const item = items.value[index]\n return item === undefined ? `Item ${index + 1}` : labelOf(item, index)\n}\n\n/* ---------------------------------------------------------------------------\n * Moving\n * ------------------------------------------------------------------------- */\n\nfunction move(from: number, to: number, via: SortableVia) {\n if (to < 0 || to >= items.value.length || from === to) return\n\n const next = [...items.value]\n const [item] = next.splice(from, 1)\n if (item === undefined) return\n next.splice(to, 0, item)\n items.value = next\n\n emit('move', { item, from, to, via })\n}\n\n/*\n * Which row is under the pointer, remembered when the drag begins. By the time it ends\n * the library has rewritten the list and told the parent, but the new array has not come\n * back down as a prop yet — so reading the row out of the model at that point gets\n * whatever used to be at that position. It is the same reason a keyboard move reads the\n * name before it moves anything.\n */\nlet dragged: T | undefined\n\nfunction onLift(event: { oldIndex?: number }) {\n dragged = items.value[event.oldIndex ?? -1]\n}\n\n/**\n * A pointer drag is over by the time this runs, so all that is left is to say what\n * happened. A row dragged into another list is left alone: two models changed, and\n * neither of them is a move within this one.\n */\nfunction onDrop(event: {\n from: HTMLElement\n to: HTMLElement\n oldIndex?: number\n newIndex?: number\n}) {\n const item = dragged\n dragged = undefined\n\n if (event.from !== event.to || item === undefined) return\n\n const from = event.oldIndex ?? -1\n const to = event.newIndex ?? -1\n if (from < 0 || to < 0 || from === to) return\n\n emit('move', { item, from, to, via: 'pointer' })\n}\n\n/* ---------------------------------------------------------------------------\n * Moving without a mouse\n *\n * SortableJS is a pointer library and has nothing to say to a keyboard, so the list\n * carries its own: space picks a row up, the arrows move it, space drops it, escape puts\n * it back. It is the same splice a drag performs; what a keyboard needs on top is\n * somewhere to read the result, and that is the live region.\n * ------------------------------------------------------------------------- */\n\nconst grabbed = ref<number | null>(null)\n\nconst origin = ref(-1)\n\nconst announcement = ref('')\n\nfunction rowElements() {\n return root.value?.querySelectorAll<HTMLElement>(':scope > .wx-sortable-list__body > li') ?? []\n}\n\n/** The row is somewhere else in the DOM now, so the focus has to follow it there. */\nasync function refocus(index: number) {\n await nextTick()\n const row = rowElements()[index]\n if (!row) return\n const target = grip.value\n ? row.querySelector<HTMLElement>(':scope > .wx-sortable-list__grip')\n : row\n target?.focus()\n}\n\nfunction onKeydown(event: KeyboardEvent, index: number) {\n /* A button inside the row keeps its own keys. */\n if (props.disabled || event.target !== event.currentTarget) return\n\n const total = items.value.length\n const held = grabbed.value === index\n\n if (event.key === ' ' || event.key === 'Spacebar' || event.key === 'Enter') {\n event.preventDefault()\n if (held) {\n grabbed.value = null\n announcement.value = `Dropped ${nameAt(index)}, ${index + 1} of ${total}.`\n } else {\n grabbed.value = index\n origin.value = index\n announcement.value = `Picked up ${nameAt(index)}. Use the arrow keys to move it, space to drop it, escape to put it back.`\n }\n return\n }\n\n if (!held) return\n\n if (event.key === 'Escape') {\n event.preventDefault()\n grabbed.value = null\n move(index, origin.value, 'keyboard')\n announcement.value = 'Move cancelled.'\n void refocus(origin.value)\n return\n }\n\n const up = event.key === 'ArrowUp' || event.key === 'ArrowLeft'\n const down = event.key === 'ArrowDown' || event.key === 'ArrowRight'\n if (!up && !down) return\n\n event.preventDefault()\n const to = index + (up ? -1 : 1)\n if (to < 0 || to >= total) {\n announcement.value = `${nameAt(index)} is already ${index + 1} of ${total}.`\n return\n }\n\n /* Read before the move: a parent that writes the model back can take a tick over it. */\n const name = nameAt(index)\n move(index, to, 'keyboard')\n grabbed.value = to\n announcement.value = `${name} is now ${to + 1} of ${total}.`\n void refocus(to)\n}\n</script>\n\n<template>\n <div ref=\"root\" :class=\"classes\">\n <header v-if=\"hasHeader\" class=\"wx-sortable-list__head\">\n <h3 class=\"wx-sortable-list__title\">\n <slot name=\"header\">{{ title }}</slot>\n </h3>\n <div v-if=\"$slots.extra\" class=\"wx-sortable-list__extra\">\n <slot name=\"extra\" />\n </div>\n </header>\n\n <vue-draggable\n v-model=\"items\"\n tag=\"ul\"\n class=\"wx-sortable-list__body\"\n :group=\"group\"\n :disabled=\"disabled\"\n :handle=\"handleSelector\"\n draggable=\".wx-sortable-list__row\"\n :animation=\"160\"\n :delay=\"150\"\n :delay-on-touch-only=\"true\"\n filter=\"button, a, input, .wx-sortable-list__actions\"\n :prevent-on-filter=\"false\"\n ghost-class=\"wx-sortable-list__row--ghost\"\n chosen-class=\"wx-sortable-list__row--chosen\"\n :aria-label=\"ariaLabel\"\n @start=\"onLift\"\n @end=\"onDrop\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"keyOf(item, index)\"\n class=\"wx-sortable-list__row\"\n :class=\"{ 'is-grabbed': grabbed === index }\"\n :tabindex=\"grip || disabled ? undefined : 0\"\n :role=\"grip || disabled ? undefined : 'button'\"\n :aria-roledescription=\"grip || disabled ? undefined : 'Sortable row'\"\n :aria-pressed=\"grip || disabled ? undefined : grabbed === index\"\n @keydown=\"onKeydown($event, index)\"\n >\n <!--\n A span with the role rather than a button, so that the `filter` below can keep a\n drag from starting on the buttons in a row without also disarming the grip.\n -->\n <span\n v-if=\"grip\"\n class=\"wx-sortable-list__grip\"\n :tabindex=\"disabled ? -1 : 0\"\n :role=\"disabled ? undefined : 'button'\"\n :aria-label=\"`${dragLabel}: ${labelOf(item, index)}`\"\n aria-roledescription=\"Drag handle\"\n :aria-pressed=\"disabled ? undefined : grabbed === index\"\n @keydown=\"onKeydown($event, index)\"\n >\n <wx-icon name=\"drag\" />\n </span>\n\n <div class=\"wx-sortable-list__content\">\n <slot :item=\"item\" :index=\"index\">{{ labelOf(item, index) }}</slot>\n </div>\n\n <div v-if=\"$slots.actions\" class=\"wx-sortable-list__actions\">\n <slot name=\"actions\" :item=\"item\" :index=\"index\" />\n </div>\n </li>\n\n <!--\n Inside the list rather than after it, so that an empty list is still somewhere a\n row from another list can be dropped. `draggable` above keeps it out of the order.\n -->\n <li v-if=\"!items.length\" class=\"wx-sortable-list__empty\">\n <slot name=\"empty\">{{ emptyText }}</slot>\n </li>\n </vue-draggable>\n\n <!-- What a keyboard move says out loud. -->\n <div class=\"wx-sortable-list__live\" role=\"status\" aria-live=\"polite\">{{ announcement }}</div>\n </div>\n</template>\n\n<style scoped>\n.wx-sortable-list {\n position: relative;\n box-sizing: border-box;\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-muted);\n border-radius: var(--wx-radius-md);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n}\n\n/* Inside a card that already has a frame, the list brings only its rules. */\n.wx-sortable-list.is-plain {\n background: none;\n border: none;\n border-radius: 0;\n}\n\n.wx-sortable-list__head {\n display: flex;\n align-items: center;\n gap: var(--wx-space-12);\n padding: var(--wx-space-12) var(--wx-space-16);\n border-bottom: 1px solid var(--wx-border-muted);\n}\n\n.is-plain .wx-sortable-list__head {\n padding-inline: 0;\n}\n\n.wx-sortable-list__title {\n flex: 1 1 auto;\n min-width: 0;\n margin: 0;\n color: var(--wx-text-strong);\n font-size: var(--wx-font-size-md);\n font-weight: var(--wx-font-weight-semibold);\n line-height: var(--wx-font-line-height-tight);\n}\n\n.wx-sortable-list__extra {\n display: flex;\n align-items: center;\n flex: 0 0 auto;\n gap: var(--wx-space-8);\n}\n\n.wx-sortable-list__body {\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.wx-sortable-list__row {\n display: flex;\n align-items: center;\n gap: var(--wx-space-12);\n /*\n * The row owns its margins, and says so from a scoped rule so that it outweighs a host\n * stylesheet spacing list items — VitePress puts 8px between every `li + li`, and a CMS\n * theme will have its own.\n */\n margin: 0;\n padding: var(--wx-space-10) var(--wx-space-16);\n /*\n * A row paints no background of its own. It would be the same colour as the list it sits\n * in, and a square corner over a rounded one is how the frame loses its corners.\n */\n background: none;\n /*\n * Dragging is what a pointer is for here, and the first thing anybody tries is the row\n * itself. Without this that gesture smears a text selection across the list.\n */\n user-select: none;\n}\n\n/* The corners the frame is rounded by, so a tinted row does not square them off again. */\n.wx-sortable-list:not(.is-plain) .wx-sortable-list__row:last-child {\n border-end-start-radius: calc(var(--wx-radius-md) - 1px);\n border-end-end-radius: calc(var(--wx-radius-md) - 1px);\n}\n\n.wx-sortable-list:not(.is-plain, .is-headed) .wx-sortable-list__row:first-child {\n border-start-start-radius: calc(var(--wx-radius-md) - 1px);\n border-start-end-radius: calc(var(--wx-radius-md) - 1px);\n}\n\n.is-plain .wx-sortable-list__row {\n padding-inline: 0;\n}\n\n.wx-sortable-list--sm .wx-sortable-list__row {\n gap: var(--wx-space-8);\n padding-block: var(--wx-space-6);\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-sortable-list__row + .wx-sortable-list__row {\n border-top: 1px solid var(--wx-border-muted);\n}\n\n/*\n * The tint of the row under the pointer and of the current one. The rules either side of it go:\n * its own and the next row's — a tinted row with a line through its edges reads as a stain\n * between two rows rather than a row. In a plain list the tint has corners of its own; in a frame\n * the first and the last row take the frame's.\n */\n.wx-sortable-list.is-hoverable\n .wx-sortable-list__row:is(:hover, :has(.is-current, [aria-current])) {\n background: var(--wx-bg-subtle);\n}\n\n.wx-sortable-list.is-hoverable.is-plain\n .wx-sortable-list__row:is(:hover, :has(.is-current, [aria-current])) {\n border-radius: var(--wx-radius-sm);\n}\n\n.wx-sortable-list.is-hoverable .wx-sortable-list__row:is(:hover, :has(.is-current, [aria-current])),\n.wx-sortable-list.is-hoverable\n .wx-sortable-list__row:is(:hover, :has(.is-current, [aria-current]))\n + .wx-sortable-list__row {\n border-top-color: transparent;\n}\n\n/*\n * The row runs the full width of the frame, so its ring is drawn inside it: a halo around\n * a row that wide lies over the frame's own border and past its corners.\n */\n.wx-sortable-list__row:focus-visible,\n.wx-sortable-list__row.is-grabbed {\n outline: 2px solid var(--wx-border-focus);\n outline-offset: -2px;\n}\n\n/* Held by the keyboard: the ring, and the tint that says this one is in hand. */\n.wx-sortable-list__row.is-grabbed {\n background: var(--wx-bg-muted);\n}\n\n.wx-sortable-list__grip:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n border-radius: var(--wx-radius-xs);\n}\n\n.wx-sortable-list__grip {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 24px;\n height: 24px;\n color: var(--wx-text-placeholder);\n cursor: grab;\n}\n\n.wx-sortable-list__grip:hover {\n color: var(--wx-text-muted);\n}\n\n.is-disabled .wx-sortable-list__grip {\n cursor: default;\n opacity: 0.5;\n}\n\n.wx-sortable-list__content {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.wx-sortable-list__actions {\n display: flex;\n align-items: center;\n flex: 0 0 auto;\n gap: var(--wx-space-4);\n}\n\n/*\n * Buttons stand close, as a toolbar does; a line of text before them — a count, a status — is\n * something else, and pressed up against the first button it reads as that button's caption.\n */\n.wx-sortable-list__actions > :slotted(.wx-text + :not(.wx-text)) {\n margin-inline-start: var(--wx-space-8);\n}\n\n/* What is left behind in the list while the row is being dragged. */\n.wx-sortable-list__row--ghost {\n opacity: 0.4;\n}\n\n/* The one under the pointer is opaque, whatever it is passing over. */\n.wx-sortable-list__row--chosen {\n background: var(--wx-bg-surface);\n cursor: grabbing;\n}\n\n.wx-sortable-list__empty {\n margin: 0;\n padding: var(--wx-space-16);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n text-align: center;\n}\n\n.is-plain .wx-sortable-list__empty {\n padding-inline: 0;\n}\n\n/* Read out, never drawn. */\n.wx-sortable-list__live {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n border: 0;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n</style>\n","import { computed, defineComponent, inject, provide, type PropType } from 'vue'\nimport { formContextKey, type ValidationErrors } from '../composables/useFormField'\n\n/**\n * A part of a form that answers to its own errors: the form around it, with `errors` replaced.\n *\n * A row of a repeater is a small form inside the big one, and its fields are named as the row\n * names them — `title`, `url`. `WxFormItem` looks its error up by that name on the form, so\n * without a scope a row's `title` shows the error of the record's own `title`, in every row at\n * once, and the row that was actually refused (`articles.2.title.en`) shows nothing.\n *\n * Outside a form there is nothing to narrow, and the slot renders as it is.\n */\nexport default defineComponent({\n name: 'WxFormScope',\n props: {\n errors: { type: Object as PropType<ValidationErrors>, required: true },\n },\n setup(props, { slots }) {\n const form = inject(formContextKey, null)\n\n if (form !== null) {\n provide(formContextKey, { ...form, errors: computed(() => props.errors) })\n }\n\n return () => slots.default?.()\n },\n})\n","<script setup lang=\"ts\" generic=\"T extends object = Record<string, unknown>\">\nimport { computed, ref, watch } from 'vue'\nimport WxAction from '../Action/Action.vue'\nimport WxActions from '../Actions/Actions.vue'\nimport WxButton from '../Button/Button.vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport WxPopconfirm from '../Popconfirm/Popconfirm.vue'\nimport WxSortableList from '../SortableList/SortableList.vue'\nimport WxFormScope from '../../internal/FormScope'\nimport type { SortableMove } from '../SortableList/types'\nimport { localizedValue, useLocales, type LocalizedValue } from '../../composables/useLocalized'\nimport type { RepeaterEmits, RepeaterProps } from './types'\n\ndefineOptions({ name: 'WxRepeater' })\n\nconst props = withDefaults(defineProps<RepeaterProps<T>>(), {\n title: undefined,\n itemLabel: undefined,\n newItem: undefined,\n addLabel: 'Add',\n removeLabel: 'Remove',\n confirmRemove: false,\n removeQuestion: 'Remove this row?',\n cancelLabel: 'Cancel',\n dragLabel: 'Reorder',\n collapsible: false,\n collapsed: false,\n min: 0,\n max: undefined,\n sortable: true,\n disabled: false,\n emptyText: 'Nothing here yet',\n size: 'md',\n plain: false,\n ariaLabel: undefined,\n rowErrors: undefined,\n})\n\nconst emit = defineEmits<RepeaterEmits<T>>()\n\ndefineSlots<{\n /** Replaces the title. */\n header?: () => unknown\n /** The end of the heading — whatever else the repeater can do. */\n extra?: () => unknown\n /** The fields of one row. */\n default?: (props: { item: T; index: number; update: (patch: Partial<T>) => void }) => unknown\n /** Row actions, before the one that removes it. */\n actions?: (props: { item: T; index: number }) => unknown\n /** Shown in place of an empty repeater. */\n empty?: () => unknown\n}>()\n\nconst items = defineModel<T[]>({ default: () => [] })\n\n/* ---------------------------------------------------------------------------\n * Keys\n *\n * A row is a form, and a form that remounts loses the caret. Positions cannot key one:\n * removing the first row would renumber every row under it, and Vue would rebuild them\n * all. Item identity cannot either — writing a field replaces the item with a copy, which\n * is exactly what must not remount anything. So the keys are the repeater's own, kept\n * alongside the model and moved with it.\n * ------------------------------------------------------------------------- */\n\nlet sequence = 0\n\nconst keys = ref<string[]>([])\n\nconst folded = ref(new Set<string>())\n\nfunction nextKey(): string {\n sequence += 1\n return `row-${sequence}`\n}\n\n/**\n * Rows the repeater did not add itself — a model that arrived from the server, or one the\n * parent replaced. They start folded when the caller asked for that; a row somebody just\n * added never does, and `add` below gives it its key before the model changes.\n */\nwatch(\n () => items.value.length,\n (length) => {\n while (keys.value.length < length) {\n const key = nextKey()\n keys.value.push(key)\n if (props.collapsed) folded.value.add(key)\n }\n if (keys.value.length > length) keys.value.length = length\n },\n { immediate: true },\n)\n\nfunction keyAt(index: number): string {\n return keys.value[index] ?? `row-${index}`\n}\n\nconst classes = computed(() => [\n 'wx-repeater',\n `wx-repeater--${props.size}`,\n { 'is-plain': props.plain, 'is-disabled': props.disabled },\n])\n\nconst foldable = computed(() => props.collapsible || props.collapsed)\n\nconst atMax = computed(() => props.max !== undefined && items.value.length >= props.max)\n\nconst atMin = computed(() => items.value.length <= props.min)\n\nconst locales = useLocales()\n\n/**\n * The header of a row: its position, then what the row is about — `#2 · Mushroom coffee`.\n *\n * The position stays when there is a name, because a folded list of similar titles is read by\n * number as often as by name. A key that holds a translated field holds every language of it,\n * so the one being edited is shown, else whichever is filled in; the bare map would print as\n * nothing at all. A function answers for the whole header.\n */\nfunction labelOf(item: T, index: number): string {\n if (typeof props.itemLabel === 'function') return props.itemLabel(item, index)\n\n const position = `#${index + 1}`\n\n if (props.itemLabel) {\n const value = (item as Record<string, unknown>)?.[props.itemLabel]\n const text =\n typeof value === 'number'\n ? String(value)\n : typeof value === 'string' || (value !== null && typeof value === 'object')\n ? localizedValue(value as LocalizedValue | string, locales.active.value).trim()\n : ''\n\n if (text !== '') return `${position} · ${text}`\n }\n\n return position\n}\n\n/** A row the server refused: something in `rowErrors` at its position. */\nfunction isInvalid(index: number): boolean {\n const errors = props.rowErrors?.[index]\n\n return errors !== undefined && Object.keys(errors).length > 0\n}\n\n/*\n * A refused row opens by itself: the error is under a field, and a folded row hides the field —\n * the save fails and nothing on screen says where.\n */\nwatch(\n () => items.value.map((_item, index) => isInvalid(index)).join(),\n () => {\n const next = new Set(folded.value)\n\n items.value.forEach((_item, index) => {\n if (isInvalid(index)) next.delete(keyAt(index))\n })\n\n if (next.size !== folded.value.size) folded.value = next\n },\n { immediate: true },\n)\n\nfunction isOpen(index: number): boolean {\n return !foldable.value || !folded.value.has(keyAt(index))\n}\n\nfunction toggle(index: number) {\n const key = keyAt(index)\n const next = new Set(folded.value)\n if (next.has(key)) next.delete(key)\n else next.add(key)\n folded.value = next\n}\n\nfunction add() {\n if (props.disabled || atMax.value) return\n\n const item = props.newItem ? props.newItem() : ({} as T)\n const index = items.value.length\n\n /* Before the model, so the watcher above sees a key already there and leaves it open. */\n keys.value.push(nextKey())\n items.value = [...items.value, item]\n\n emit('add', item, index)\n}\n\nfunction remove(index: number) {\n if (props.disabled || atMin.value) return\n\n const item = items.value[index]\n if (item === undefined) return\n\n const [key] = keys.value.splice(index, 1)\n if (key !== undefined && folded.value.has(key)) {\n const next = new Set(folded.value)\n next.delete(key)\n folded.value = next\n }\n\n const next = [...items.value]\n next.splice(index, 1)\n items.value = next\n\n emit('remove', item, index)\n}\n\n/** Writing a field: a copy of the row in a copy of the list, never a mutation of a prop. */\nfunction update(index: number, patch: Partial<T>) {\n const item = items.value[index]\n if (item === undefined) return\n\n const next = [...items.value]\n next[index] = { ...item, ...patch }\n items.value = next\n}\n\n/** The list has already reordered the model; the keys follow it so the rows stay put. */\nfunction onMove(move: SortableMove<T>) {\n const [key] = keys.value.splice(move.from, 1)\n if (key !== undefined) keys.value.splice(move.to, 0, key)\n\n emit('move', move)\n}\n</script>\n\n<template>\n <div :class=\"classes\">\n <wx-sortable-list\n v-model=\"items\"\n class=\"wx-repeater__list\"\n :title=\"title\"\n :plain=\"plain\"\n :size=\"size\"\n :item-key=\"(_item: T, index: number) => keyAt(index)\"\n :item-label=\"(item: T, index: number) => labelOf(item, index)\"\n :disabled=\"disabled || !sortable\"\n :handle=\"sortable ? 'grip' : 'row'\"\n :empty-text=\"emptyText\"\n :aria-label=\"ariaLabel ?? title\"\n :drag-label=\"dragLabel\"\n @move=\"onMove\"\n >\n <template v-if=\"$slots.header\" #header><slot name=\"header\" /></template>\n <template v-if=\"$slots.extra\" #extra><slot name=\"extra\" /></template>\n\n <template #default=\"{ index }\">\n <div class=\"wx-repeater__row\">\n <component\n :is=\"foldable ? 'button' : 'div'\"\n v-if=\"foldable || itemLabel\"\n class=\"wx-repeater__head\"\n :class=\"{ 'is-invalid': isInvalid(index) }\"\n :type=\"foldable ? 'button' : undefined\"\n :aria-expanded=\"foldable ? isOpen(index) : undefined\"\n @click=\"foldable && toggle(index)\"\n >\n <svg\n v-if=\"foldable\"\n class=\"wx-repeater__chevron\"\n :class=\"{ 'is-open': isOpen(index) }\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"m6 4 4 4-4 4\"\n stroke=\"currentColor\"\n stroke-width=\"1.6\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <span class=\"wx-repeater__title\">{{ labelOf(items[index] as T, index) }}</span>\n </component>\n\n <div v-show=\"isOpen(index)\" class=\"wx-repeater__body\">\n <wx-form-scope v-if=\"rowErrors\" :errors=\"rowErrors[index] ?? {}\">\n <slot\n :item=\"items[index] as T\"\n :index=\"index\"\n :update=\"(patch: Partial<T>) => update(index, patch)\"\n />\n </wx-form-scope>\n <slot\n v-else\n :item=\"items[index] as T\"\n :index=\"index\"\n :update=\"(patch: Partial<T>) => update(index, patch)\"\n />\n </div>\n </div>\n </template>\n\n <template #actions=\"{ index }\">\n <wx-actions :size=\"size === 'sm' ? 'sm' : 'md'\">\n <slot name=\"actions\" :item=\"items[index] as T\" :index=\"index\" />\n <wx-popconfirm\n v-if=\"confirmRemove\"\n :title=\"removeQuestion\"\n :confirm-text=\"removeLabel\"\n :cancel-text=\"cancelLabel\"\n confirm-type=\"danger\"\n side=\"bottom\"\n align=\"end\"\n :disabled=\"disabled || atMin\"\n @confirm=\"remove(index)\"\n >\n <template #trigger>\n <wx-action type=\"remove\" :label=\"removeLabel\" :disabled=\"disabled || atMin\" />\n </template>\n </wx-popconfirm>\n <wx-action\n v-else\n type=\"remove\"\n :label=\"removeLabel\"\n :disabled=\"disabled || atMin\"\n @click=\"remove(index)\"\n />\n </wx-actions>\n </template>\n\n <template #empty\n ><slot name=\"empty\">{{ emptyText }}</slot></template\n >\n </wx-sortable-list>\n\n <div class=\"wx-repeater__foot\">\n <wx-button\n class=\"wx-repeater__add\"\n variant=\"outline\"\n :size=\"size === 'sm' ? 'sm' : 'md'\"\n :disabled=\"disabled || atMax\"\n @click=\"add\"\n >\n <wx-icon name=\"plus\" />\n {{ addLabel }}\n </wx-button>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-repeater {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n font-family: var(--wx-font-family-sans);\n}\n\n/*\n * A row of a sortable list is one line of text, centred and unselectable. A row here is a\n * form: it starts at the top, next to a grip that stays with the header, and its text is\n * there to be selected.\n */\n.wx-repeater {\n /* The width that decides whether a row's fields may run under the grip. */\n container-type: inline-size;\n}\n\n/*\n * A row is a grid of two lines: the grip, the header and the actions on the first, centred on\n * each other; the fields on the second. The list's own row is `grip | content | actions`, and\n * the header and the fields both live in the content — so the content and our row step aside\n * (`display: contents`) and their children take places in the list's row directly. That is\n * what lets the fields run under the actions instead of leaving a column of nothing beside\n * every field, and what lets a header line up with a 32px button instead of hanging above it.\n */\n.wx-repeater :deep(.wx-sortable-list__row) {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) auto;\n align-items: center;\n column-gap: 0;\n row-gap: var(--wx-space-8);\n user-select: auto;\n}\n\n.wx-repeater :deep(.wx-sortable-list__content),\n.wx-repeater__row {\n display: contents;\n}\n\n.wx-repeater :deep(.wx-sortable-list__grip) {\n grid-area: 1 / 1;\n margin-inline-end: var(--wx-space-12);\n}\n\n.wx-repeater :deep(.wx-sortable-list__actions) {\n grid-area: 1 / 3;\n margin-inline-start: var(--wx-space-12);\n}\n\n.wx-repeater__head {\n grid-area: 1 / 2;\n}\n\n.wx-repeater__body {\n grid-row: 2;\n grid-column: 2 / -1;\n min-width: 0;\n}\n\n/* No header — no title, not foldable: the fields take the first line themselves. */\n.wx-repeater__body:first-child {\n grid-row: 1;\n grid-column: 2;\n align-self: start;\n}\n\n/* Narrow, the indent under the grip is a field's worth of width nobody can spare. */\n@container (max-width: 560px) {\n .wx-repeater__body:not(:first-child) {\n grid-column: 1 / -1;\n }\n}\n\n.wx-repeater__head {\n display: flex;\n align-items: center;\n gap: var(--wx-space-6);\n margin: 0;\n padding: 0;\n border: none;\n background: none;\n color: var(--wx-text-muted);\n font: inherit;\n font-size: var(--wx-font-size-sm);\n font-weight: var(--wx-font-weight-medium);\n text-align: start;\n /* A long title is cut, not wrapped: the header is one line beside the grip and the actions. */\n min-width: 0;\n}\n\n.wx-repeater__title {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\nbutton.wx-repeater__head {\n cursor: pointer;\n}\n\nbutton.wx-repeater__head:hover {\n color: var(--wx-text-default);\n}\n\nbutton.wx-repeater__head:focus-visible {\n outline: none;\n border-radius: var(--wx-radius-xs);\n box-shadow: var(--wx-ring-focus);\n}\n\nbutton.wx-repeater__head.is-invalid,\n.wx-repeater__head.is-invalid {\n color: var(--wx-color-danger);\n}\n\n.wx-repeater__chevron {\n flex: 0 0 auto;\n width: 14px;\n height: 14px;\n transition: transform var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-repeater__chevron.is-open {\n transform: rotate(90deg);\n}\n\n.wx-repeater__body {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n}\n\n.wx-repeater__foot {\n display: flex;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport type { IconName } from '../Icon/types'\nimport type { ResultProps, ResultStatus } from './types'\n\ndefineOptions({ name: 'WxResult' })\n\nconst props = withDefaults(defineProps<ResultProps>(), {\n status: 'info',\n title: undefined,\n subtitle: undefined,\n icon: undefined,\n})\n\ndefineSlots<{\n icon?: () => unknown\n title?: () => unknown\n subtitle?: () => unknown\n /** The way out: back to the list, try again, contact somebody. */\n actions?: () => unknown\n /** Anything under the actions — a stack trace behind a disclosure, a reference. */\n default?: () => unknown\n}>()\n\nconst GLYPH: Record<ResultStatus, IconName> = {\n success: 'check-circle',\n warning: 'warning',\n danger: 'close-circle',\n info: 'info',\n 403: 'lock',\n 404: 'search',\n 500: 'warning',\n}\n\n/* The three numbers borrow a colour rather than having one of their own. */\nconst TONE: Record<ResultStatus, string> = {\n success: 'success',\n warning: 'warning',\n danger: 'danger',\n info: 'info',\n 403: 'warning',\n 404: 'info',\n 500: 'danger',\n}\n\nconst icon = computed(() => props.icon ?? GLYPH[props.status])\n\nconst classes = computed(() => ['wx-result', `wx-result--${TONE[props.status]}`])\n</script>\n\n<template>\n <div :class=\"classes\">\n <div class=\"wx-result__icon\" aria-hidden=\"true\">\n <slot name=\"icon\">\n <wx-icon :name=\"icon\" />\n </slot>\n </div>\n\n <p v-if=\"title || $slots.title\" class=\"wx-result__title\">\n <slot name=\"title\">{{ title }}</slot>\n </p>\n\n <p v-if=\"subtitle || $slots.subtitle\" class=\"wx-result__subtitle\">\n <slot name=\"subtitle\">{{ subtitle }}</slot>\n </p>\n\n <div v-if=\"$slots.actions\" class=\"wx-result__actions\">\n <slot name=\"actions\" />\n </div>\n\n <div v-if=\"$slots.default\" class=\"wx-result__body\">\n <slot />\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-result {\n display: flex;\n flex-direction: column;\n align-items: center;\n box-sizing: border-box;\n gap: var(--wx-space-8);\n padding: var(--wx-space-48) var(--wx-space-24);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n text-align: center;\n}\n\n/*\n * The glyph carries the outcome, so it is the one thing here drawn in a colour —\n * the words below it say the same thing for anyone who cannot use the colour.\n */\n.wx-result__icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 56px;\n height: 56px;\n margin-bottom: var(--wx-space-4);\n background: var(--wx-result-soft);\n border-radius: var(--wx-radius-full);\n color: var(--wx-result-accent);\n}\n\n.wx-result__icon :deep(.wx-icon) {\n width: 28px;\n height: 28px;\n}\n\n.wx-result--success {\n --wx-result-accent: var(--wx-color-success-active);\n --wx-result-soft: var(--wx-color-success-soft);\n}\n\n.wx-result--warning {\n --wx-result-accent: var(--wx-color-warning-active);\n --wx-result-soft: var(--wx-color-warning-soft);\n}\n\n.wx-result--danger {\n --wx-result-accent: var(--wx-color-danger);\n --wx-result-soft: var(--wx-color-danger-soft);\n}\n\n.wx-result--info {\n --wx-result-accent: var(--wx-color-info-active);\n --wx-result-soft: var(--wx-color-info-soft);\n}\n\n.wx-result__title {\n margin: 0;\n color: var(--wx-text-strong);\n font-size: var(--wx-font-size-xl);\n font-weight: var(--wx-font-weight-semibold);\n line-height: var(--wx-font-line-height-tight);\n}\n\n.wx-result__subtitle {\n max-width: 52ch;\n margin: 0;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n line-height: var(--wx-font-line-height-normal);\n}\n\n.wx-result__actions {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: center;\n gap: var(--wx-space-8);\n margin-top: var(--wx-space-8);\n}\n\n.wx-result__body {\n width: 100%;\n margin-top: var(--wx-space-16);\n text-align: start;\n}\n</style>\n","import { defineAsyncComponent } from 'vue'\n\n/*\n * Loaded when first drawn, not with the panel: Tiptap and ProseMirror are a fifth of what the\n * panel downloaded before anything appeared, and a list or a settings screen has no text field.\n * The component is the same one — props, events, `v-model` and the instance a template ref\n * points at — it just arrives a moment after the screen that holds it.\n */\nexport const WxRichText = Object.assign(\n defineAsyncComponent({ loader: () => import('./RichText.vue'), suspensible: false }),\n // Named like what it loads: a test — ours or a site's — that stubs `WxRichText` by name still does.\n { name: 'WxRichText' },\n)\nexport type * from './types'\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { RowProps } from './types'\n\ndefineOptions({ name: 'WxRow' })\n\nconst props = withDefaults(defineProps<RowProps>(), {\n gutter: undefined,\n gutterY: undefined,\n justify: undefined,\n align: undefined,\n wrap: true,\n as: 'div',\n})\n\n/*\n * Unasked, the gutter between columns is the panel's step (§6 of the visual spec): the same\n * number that stands between cards and around the sidebar, so a grid does not have a rhythm of\n * its own. Outside a panel the fallback is the desktop step, which is what it always was.\n */\nconst STEP = 'var(--wx-gap, var(--wx-space-16))'\n\nfunction toLength(value: number | string | undefined) {\n if (value === undefined) return STEP\n return typeof value === 'number' ? `${value}px` : value\n}\n\n/**\n * The gutter is published as a variable rather than passed down through a provide:\n * a custom property inherits through the DOM, so `WxCol` picks it up wherever it\n * sits — even wrapped in a `<template v-for>` or a component of your own.\n */\nconst style = computed(() => ({\n '--wx-row-gutter': toLength(props.gutter),\n '--wx-row-gutter-y': toLength(props.gutterY ?? props.gutter),\n}))\n\nconst classes = computed(() => [\n 'wx-row',\n {\n 'wx-row--nowrap': !props.wrap,\n [`wx-row--justify-${props.justify}`]: Boolean(props.justify),\n [`wx-row--align-${props.align}`]: Boolean(props.align),\n },\n])\n</script>\n\n<template>\n <component :is=\"as\" :class=\"classes\" :style=\"style\">\n <slot />\n </component>\n</template>\n\n<style scoped>\n.wx-row {\n display: flex;\n flex-wrap: wrap;\n box-sizing: border-box;\n /*\n * The row is what its columns measure themselves against: they reflow on the width\n * of the row, not of the window, so a grid dropped into a drawer or into a main\n * column squeezed by a sidebar behaves like the narrow thing it is. The container\n * is named so that a stray column outside a row does not start answering to the\n * nearest card instead.\n */\n container: wx-row / inline-size;\n /*\n * The gutter is padding on the columns, pulled back by this negative margin, so a\n * column's width stays an honest percentage of the row. A `column-gap` would be\n * subtracted from the track and leave `span=\"12\"` twice over a line too wide.\n */\n margin-inline: calc(var(--wx-row-gutter, 0px) / -2);\n row-gap: var(--wx-row-gutter-y, 0px);\n}\n\n.wx-row--nowrap {\n flex-wrap: nowrap;\n}\n\n.wx-row--justify-start {\n justify-content: flex-start;\n}\n\n.wx-row--justify-center {\n justify-content: center;\n}\n\n.wx-row--justify-end {\n justify-content: flex-end;\n}\n\n.wx-row--justify-between {\n justify-content: space-between;\n}\n\n.wx-row--justify-around {\n justify-content: space-around;\n}\n\n.wx-row--justify-evenly {\n justify-content: space-evenly;\n}\n\n.wx-row--align-start {\n align-items: flex-start;\n}\n\n.wx-row--align-center {\n align-items: center;\n}\n\n.wx-row--align-end {\n align-items: flex-end;\n}\n\n.wx-row--align-stretch {\n align-items: stretch;\n}\n\n.wx-row--align-baseline {\n align-items: baseline;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport type { ScrollbarEmits, ScrollbarProps, ScrollMotion, ScrollTarget } from './types'\n\ndefineOptions({ name: 'WxScrollbar' })\n\nconst props = withDefaults(defineProps<ScrollbarProps>(), {\n height: undefined,\n maxHeight: undefined,\n axis: 'y',\n size: 'md',\n always: false,\n chainScroll: false,\n})\n\nconst emit = defineEmits<ScrollbarEmits>()\n\nconst viewport = ref<HTMLElement | null>(null)\n\nfunction toLength(value: number | string | undefined) {\n if (value === undefined) return undefined\n return typeof value === 'number' ? `${value}px` : value\n}\n\nconst style = computed(() => {\n const vars: Record<string, string> = {}\n const height = toLength(props.height)\n const maxHeight = toLength(props.maxHeight)\n if (height) vars['--wx-scrollbar-height'] = height\n if (maxHeight) vars['--wx-scrollbar-max-height'] = maxHeight\n return vars\n})\n\nconst classes = computed(() => [\n 'wx-scrollbar',\n `wx-scrollbar--${props.axis}`,\n `wx-scrollbar--${props.size}`,\n {\n 'wx-scrollbar--always': props.always,\n 'wx-scrollbar--chain': props.chainScroll,\n },\n])\n\n/*\n * The element itself is exposed alongside the helpers: a virtual list or a chat\n * panel needs `scrollHeight` and `scrollTop` directly, and hiding them behind a\n * wrapper would only mean re-inventing them one method at a time.\n */\ndefineExpose({\n /** The scrolling element. */\n el: viewport,\n scrollTo: (options: ScrollTarget) => viewport.value?.scrollTo(options),\n scrollToTop: (behavior: ScrollMotion = 'auto') => viewport.value?.scrollTo({ top: 0, behavior }),\n scrollToBottom: (behavior: ScrollMotion = 'auto') =>\n viewport.value?.scrollTo({ top: viewport.value.scrollHeight, behavior }),\n})\n</script>\n\n<template>\n <div ref=\"viewport\" :class=\"classes\" :style=\"style\" @scroll=\"emit('scroll', $event)\">\n <slot />\n </div>\n</template>\n\n<style scoped>\n/*\n * Native scrolling, themed — not a pair of divs moved about in JavaScript. The\n * browser keeps keyboard scrolling, momentum and the trackpad overlay bar; all this\n * adds is the colour and the thickness.\n */\n.wx-scrollbar {\n --wx-scrollbar-thickness: 10px;\n --wx-scrollbar-thumb: color-mix(in srgb, var(--wx-text-muted) 45%, transparent);\n --wx-scrollbar-thumb-hover: color-mix(in srgb, var(--wx-text-muted) 70%, transparent);\n\n box-sizing: border-box;\n height: var(--wx-scrollbar-height, auto);\n max-height: var(--wx-scrollbar-max-height, none);\n /* The thin bar in Firefox takes layout space; reserving it keeps text from jumping. */\n scrollbar-gutter: stable;\n scrollbar-width: thin;\n scrollbar-color: var(--wx-scrollbar-thumb) transparent;\n overscroll-behavior: contain;\n}\n\n.wx-scrollbar--chain {\n overscroll-behavior: auto;\n}\n\n.wx-scrollbar--sm {\n --wx-scrollbar-thickness: 6px;\n}\n\n.wx-scrollbar--y {\n overflow-x: hidden;\n overflow-y: auto;\n}\n\n.wx-scrollbar--x {\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-gutter: auto;\n}\n\n.wx-scrollbar--both {\n overflow: auto;\n}\n\n/* WebKit and Blink ignore `scrollbar-color`, so the same look is spelled out again. */\n.wx-scrollbar::-webkit-scrollbar {\n width: var(--wx-scrollbar-thickness);\n height: var(--wx-scrollbar-thickness);\n}\n\n.wx-scrollbar::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.wx-scrollbar::-webkit-scrollbar-thumb {\n background: var(--wx-scrollbar-thumb);\n /* Clipping to the padding box insets the thumb without a track of its own. */\n background-clip: padding-box;\n border: 2px solid transparent;\n border-radius: var(--wx-radius-full);\n}\n\n.wx-scrollbar::-webkit-scrollbar-thumb:hover {\n background: var(--wx-scrollbar-thumb-hover);\n background-clip: padding-box;\n}\n\n.wx-scrollbar::-webkit-scrollbar-corner {\n background: transparent;\n}\n\n/*\n * Quiet until the pointer is in the box or something inside it has focus — the bar\n * reports a scroll position, it is not a border, and a page of panels reads calmer\n * without a stack of them.\n */\n.wx-scrollbar:not(.wx-scrollbar--always) {\n scrollbar-color: transparent transparent;\n}\n\n.wx-scrollbar:not(.wx-scrollbar--always):hover,\n.wx-scrollbar:not(.wx-scrollbar--always):focus-within {\n scrollbar-color: var(--wx-scrollbar-thumb) transparent;\n}\n\n.wx-scrollbar:not(.wx-scrollbar--always)::-webkit-scrollbar-thumb {\n background: transparent;\n}\n\n.wx-scrollbar:not(.wx-scrollbar--always):hover::-webkit-scrollbar-thumb,\n.wx-scrollbar:not(.wx-scrollbar--always):focus-within::-webkit-scrollbar-thumb {\n background: var(--wx-scrollbar-thumb);\n background-clip: padding-box;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport {\n ComboboxAnchor,\n ComboboxContent,\n ComboboxEmpty,\n ComboboxInput,\n ComboboxItem,\n ComboboxItemIndicator,\n ComboboxPortal,\n ComboboxRoot,\n ComboboxTrigger,\n ComboboxViewport,\n} from 'reka-ui'\nimport { useFormField } from '../../composables/useFormField'\nimport type { SelectEmits, SelectModelValue, SelectProps, SelectValue } from './types'\nimport { useControlAttrs } from '../../composables/useControlAttrs'\n\ndefineOptions({ name: 'WxSelect', inheritAttrs: false })\n\n/* `class` and `style` belong to the control; the rest belongs to its input. */\nconst { rootAttrs, controlAttrs } = useControlAttrs()\n\n/** The box that filters, when there is one — its `$el` is the `<input>` itself. */\nconst filterRef = ref<{ $el: HTMLInputElement } | null>(null)\n\nconst props = withDefaults(defineProps<SelectProps>(), {\n options: () => [],\n multiple: false,\n filterable: false,\n clearable: false,\n placeholder: undefined,\n emptyText: 'Nothing found',\n teleport: true,\n disabled: undefined,\n size: undefined,\n status: undefined,\n id: undefined,\n name: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<SelectEmits>()\n\nconst model = defineModel<SelectModelValue>({ default: null })\n\nconst field = useFormField(props)\nconst open = ref(false)\n\n/**\n * The text in the search field. Controlled here rather than left to the combobox:\n * with `multiple` the input has no display value to fall back on and renders the\n * model itself, so picking two tags leaves \"news,releases\" sitting in the box.\n */\nconst searchText = ref('')\n\n/** Reka wants an array for multiple and a bare value otherwise. */\nconst selection = computed({\n get: () => (props.multiple ? ((model.value as SelectValue[]) ?? []) : (model.value ?? null)),\n set: (value) => {\n model.value = value as SelectModelValue\n emit('change', value as SelectModelValue)\n },\n})\n\nconst labelOf = (value: SelectValue) =>\n props.options.find((option) => option.value === value)?.label ?? String(value)\n\nconst selectedOptions = computed(() => {\n if (!props.multiple) return []\n return ((model.value as SelectValue[]) ?? []).map((value) => ({ value, label: labelOf(value) }))\n})\n\nconst singleLabel = computed(() => {\n if (props.multiple) return ''\n const value = model.value as SelectValue | null\n return value === null || value === undefined ? '' : labelOf(value)\n})\n\nconst hasSelection = computed(() =>\n props.multiple\n ? selectedOptions.value.length > 0\n : model.value !== null && model.value !== undefined && model.value !== '',\n)\n\nconst showClear = computed(() => props.clearable && !field.disabled.value && hasSelection.value)\n\nconst classes = computed(() => [\n 'wx-select',\n `wx-select--${field.size.value}`,\n {\n [`wx-select--${field.status.value}`]: field.status.value !== 'default',\n 'is-open': open.value,\n 'is-disabled': field.disabled.value,\n 'is-multiple': props.multiple,\n },\n])\n\n/** A pick clears the search in multiple mode and shows the label in single mode. */\nwatch(\n () => model.value,\n () => {\n searchText.value = props.multiple ? '' : singleLabel.value\n },\n { immediate: true },\n)\n\n/*\n * The options may arrive after the value — a list asked from the server — and the box would go on\n * showing the value itself. While the list is closed nobody is typing into it, so it follows.\n */\nwatch(singleLabel, (label) => {\n if (!open.value && !props.multiple) searchText.value = label\n})\n\nwatch(open, (value) => {\n if (value) {\n emit('open')\n return\n }\n searchText.value = props.multiple ? '' : singleLabel.value\n emit('close')\n})\n\n/**\n * Clicking the field is how everyone expects a select to open — and, when it filters, how the\n * caret gets into the box that does the filtering.\n *\n * The caret is put there here and not by Reka's `autoFocus`, which fires once on mount: on a\n * form the filter is the field itself rather than a box inside an open list, so a mounted\n * `autoFocus` never focused anything anybody had just opened, and instead handed the focus to\n * whichever select was drawn last. A tab of the panel with four of them scrolled itself to the\n * bottom the moment it appeared.\n */\nfunction openList() {\n if (field.disabled.value) return\n\n open.value = true\n filterRef.value?.$el?.focus()\n}\n\n/**\n * What a filterable field shows once a value is picked. Without it the input falls\n * back to the raw value, so choosing \"Maria Kovalenko\" leaves \"12\" in the box.\n */\nfunction displayValue(value: unknown): string {\n return value === null || value === undefined ? '' : labelOf(value as SelectValue)\n}\n\n/**\n * Reka filters the list itself and keeps no public search term, so the value is read\n * straight off the input — that is what a caller loading options from a backend needs.\n */\nfunction onSearch(event: Event) {\n emit('search', (event.target as HTMLInputElement).value)\n}\n\nfunction clear() {\n model.value = props.multiple ? [] : null\n emit('change', model.value)\n emit('clear')\n}\n\nfunction removeTag(value: SelectValue) {\n const next = ((model.value as SelectValue[]) ?? []).filter((item) => item !== value)\n model.value = next\n emit('change', next)\n}\n</script>\n\n<template>\n <combobox-root\n v-model=\"selection\"\n v-model:open=\"open\"\n :multiple=\"multiple\"\n :disabled=\"field.disabled.value\"\n :name=\"name\"\n :ignore-filter=\"!filterable\"\n :open-on-click=\"true\"\n :class=\"classes\"\n v-bind=\"rootAttrs\"\n as=\"div\"\n >\n <combobox-anchor class=\"wx-select__anchor\" as=\"div\" @click=\"openList\">\n <div class=\"wx-select__value\">\n <template v-if=\"multiple\">\n <span\n v-for=\"option in selectedOptions\"\n :key=\"String(option.value)\"\n class=\"wx-select__tag\"\n >\n {{ option.label }}\n <button\n v-if=\"!field.disabled.value\"\n class=\"wx-select__tag-remove\"\n type=\"button\"\n tabindex=\"-1\"\n :aria-label=\"`Remove ${option.label}`\"\n @click.stop=\"removeTag(option.value)\"\n >\n ✕\n </button>\n </span>\n </template>\n\n <combobox-input\n v-if=\"filterable\"\n :id=\"field.id.value\"\n ref=\"filterRef\"\n v-bind=\"controlAttrs\"\n v-model=\"searchText\"\n class=\"wx-select__input\"\n :placeholder=\"placeholder\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"field.describedBy.value\"\n :aria-invalid=\"field.status.value === 'error' || undefined\"\n :display-value=\"multiple ? undefined : displayValue\"\n @input=\"onSearch\"\n />\n\n <template v-else>\n <span v-if=\"!multiple && hasSelection\" class=\"wx-select__single\">{{ singleLabel }}</span>\n <span v-else-if=\"!hasSelection\" class=\"wx-select__placeholder\">{{ placeholder }}</span>\n </template>\n </div>\n\n <button\n v-if=\"showClear\"\n class=\"wx-select__clear\"\n type=\"button\"\n tabindex=\"-1\"\n aria-label=\"Clear\"\n @click.stop=\"clear\"\n >\n ✕\n </button>\n\n <combobox-trigger\n :id=\"filterable ? undefined : field.id.value\"\n class=\"wx-select__toggle\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"field.describedBy.value\"\n >\n <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"m4 6 4 4 4-4\"\n stroke=\"currentColor\"\n stroke-width=\"1.6\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </combobox-trigger>\n </combobox-anchor>\n\n <combobox-portal :disabled=\"!teleport\">\n <combobox-content class=\"wx-select__content\" position=\"popper\" :side-offset=\"4\">\n <combobox-viewport class=\"wx-select__viewport\">\n <combobox-empty class=\"wx-select__empty\">{{ emptyText }}</combobox-empty>\n\n <slot>\n <combobox-item\n v-for=\"option in options\"\n :key=\"String(option.value)\"\n class=\"wx-select__option\"\n :value=\"option.value\"\n :disabled=\"option.disabled\"\n >\n <span class=\"wx-select__option-label\">{{ option.label }}</span>\n <combobox-item-indicator class=\"wx-select__check\">\n <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"m3.5 8.5 3 3 6-6\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </combobox-item-indicator>\n </combobox-item>\n </slot>\n </combobox-viewport>\n </combobox-content>\n </combobox-portal>\n </combobox-root>\n</template>\n\n<style scoped>\n.wx-select {\n display: block;\n width: 100%;\n}\n\n.wx-select__anchor {\n display: flex;\n align-items: center;\n gap: var(--wx-space-6);\n box-sizing: border-box;\n min-height: var(--wx-size-control-md);\n padding: 0 var(--wx-space-6) 0 var(--wx-space-12);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-control);\n color: var(--wx-text-default);\n /* A select is a list of choices, and it reads like the one in the sidebar does. */\n font-size: var(--wx-font-size-control-md);\n font-weight: var(--wx-font-weight-medium);\n cursor: pointer;\n transition: border-color var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-select--sm .wx-select__anchor {\n min-height: var(--wx-size-control-sm);\n font-size: var(--wx-font-size-control-sm);\n}\n\n.wx-select--lg .wx-select__anchor {\n min-height: var(--wx-size-control-lg);\n font-size: var(--wx-font-size-control-lg);\n}\n\n.wx-select__anchor:hover {\n border-color: var(--wx-border-strong);\n}\n\n.wx-select.is-open .wx-select__anchor {\n border-color: var(--wx-border-focus);\n}\n\n.wx-select--error .wx-select__anchor,\n.wx-select--error.is-open .wx-select__anchor {\n border-color: var(--wx-color-danger);\n}\n\n.wx-select--success .wx-select__anchor {\n border-color: var(--wx-color-success);\n}\n\n.wx-select--warning .wx-select__anchor {\n border-color: var(--wx-color-warning);\n}\n\n.wx-select.is-disabled .wx-select__anchor {\n background: var(--wx-bg-disabled);\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n.wx-select__value {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-4);\n flex: 1 1 auto;\n min-width: 0;\n padding: var(--wx-space-4) 0;\n}\n\n.wx-select__single,\n.wx-select__placeholder {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wx-select__placeholder {\n color: var(--wx-text-placeholder);\n}\n\n.wx-select__input {\n flex: 1 1 60px;\n min-width: 0;\n padding: 0;\n background: transparent;\n border: none;\n outline: none;\n color: inherit;\n font-family: inherit;\n font-size: inherit;\n}\n\n.wx-select__input::placeholder {\n color: var(--wx-text-placeholder);\n}\n\n.wx-select__tag {\n display: inline-flex;\n align-items: center;\n gap: var(--wx-space-4);\n padding: 2px var(--wx-space-6);\n background: var(--wx-bg-fill);\n border-radius: var(--wx-radius-xs);\n font-size: var(--wx-font-size-sm);\n line-height: var(--wx-font-line-height-tight);\n}\n\n.wx-select__tag-remove,\n.wx-select__clear {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n background: transparent;\n border: none;\n border-radius: var(--wx-radius-full);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n line-height: 1;\n cursor: pointer;\n}\n\n.wx-select__tag-remove:hover,\n.wx-select__clear:hover {\n color: var(--wx-text-default);\n}\n\n.wx-select__clear {\n flex: 0 0 auto;\n width: 18px;\n height: 18px;\n}\n\n.wx-select__toggle {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 24px;\n height: 24px;\n padding: 0;\n background: transparent;\n border: none;\n color: var(--wx-text-muted);\n cursor: inherit;\n transition: transform var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-select__toggle svg {\n width: 16px;\n height: 16px;\n}\n\n.wx-select.is-open .wx-select__toggle {\n transform: rotate(180deg);\n}\n</style>\n\n<style>\n/* The list is teleported, so its styles cannot be scoped to the component. */\n.wx-select__content {\n /* One layer for every floating panel, so the one opened last is the one on top. */\n z-index: var(--wx-z-index-popover);\n box-sizing: border-box;\n width: var(--reka-combobox-trigger-width);\n max-height: 280px;\n padding: var(--wx-space-4);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-sm);\n box-shadow: var(--wx-shadow-popover);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n font-size: var(--wx-font-size-control-md);\n font-weight: var(--wx-font-weight-medium);\n overflow: hidden;\n}\n\n.wx-select__viewport {\n max-height: 272px;\n overflow-y: auto;\n}\n\n.wx-select__option {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--wx-space-8);\n padding: var(--wx-space-6) var(--wx-space-10);\n border-radius: var(--wx-radius-xs);\n cursor: pointer;\n user-select: none;\n}\n\n.wx-select__option[data-highlighted] {\n background: var(--wx-bg-fill);\n outline: none;\n}\n\n.wx-select__option[data-state='checked'] {\n color: var(--wx-color-primary);\n font-weight: var(--wx-font-weight-medium);\n}\n\n.wx-select__option[data-disabled] {\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n.wx-select__option-label {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wx-select__check {\n display: inline-flex;\n flex: 0 0 auto;\n color: var(--wx-color-primary);\n}\n\n.wx-select__check svg {\n width: 16px;\n height: 16px;\n}\n\n.wx-select__empty {\n padding: var(--wx-space-10);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n text-align: center;\n}\n</style>\n","import type { ObjectDirective } from 'vue'\nimport type { SelectionValue } from './types'\n\n/** Marks an element as something a selection box can catch. */\nexport const SELECTABLE = 'data-wx-selectable'\n\n/*\n * The value is kept against the element instead of in a registry the area holds, because\n * the area reads its items out of the DOM when a drag begins: `v-for` may have rewritten\n * the list since the last one, a virtual scroller may have recycled half of it, and a\n * registry would have to be kept in step with all of that to say the same thing. The map\n * is weak, so an element that leaves the page takes its entry with it.\n */\nconst values = new WeakMap<Element, SelectionValue>()\n\n/**\n * The value of a selectable element. Falls back to the attribute, so markup that is not\n * written in Vue can say `data-wx-selectable=\"42\"` and be caught the same way — as the\n * string `'42'`, since that is all an attribute can hold.\n */\nexport function valueOf(el: Element): SelectionValue | undefined {\n const known = values.get(el)\n if (known !== undefined) return known\n const written = el.getAttribute(SELECTABLE)\n return written ? written : undefined\n}\n\nfunction mark(el: HTMLElement, value: SelectionValue) {\n values.set(el, value)\n el.setAttribute(SELECTABLE, '')\n}\n\n/**\n * `v-wx-select=\"item.id\"` hands an element to the selection area around it.\n *\n * A directive rather than a component, because the element is already there — a card, a\n * row, a list item — and wrapping every one of them in a box of ours would break the grid\n * or table it sits in. It also keeps the value's type: an attribute could only carry the\n * string `'42'`, and the selection would stop matching the numbers the model holds.\n */\nexport const vWxSelect: ObjectDirective<HTMLElement, SelectionValue> = {\n mounted(el, binding) {\n mark(el, binding.value)\n },\n updated(el, binding) {\n if (binding.value !== binding.oldValue) mark(el, binding.value)\n },\n unmounted(el) {\n values.delete(el)\n el.removeAttribute(SELECTABLE)\n },\n}\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, ref } from 'vue'\nimport { SELECTABLE, valueOf } from './directive'\nimport type {\n SelectionAreaEmits,\n SelectionAreaProps,\n SelectionAreaSlotProps,\n SelectionValue,\n} from './types'\n\ndefineOptions({ name: 'WxSelectionArea' })\n\nconst props = withDefaults(defineProps<SelectionAreaProps>(), {\n multiple: true,\n match: 'intersect',\n threshold: 5,\n clickSelect: true,\n touch: false,\n dragItems: false,\n edgeScroll: 48,\n disabled: false,\n})\n\nconst emit = defineEmits<SelectionAreaEmits>()\n\nconst model = defineModel<SelectionValue[]>({ default: () => [] })\n\ndefineSlots<{ default?: (props: SelectionAreaSlotProps) => unknown }>()\n\ninterface Box {\n left: number\n top: number\n width: number\n height: number\n}\n\ninterface Candidate extends Box {\n value: SelectionValue\n right: number\n bottom: number\n}\n\n/*\n * Anything a pointer already means something to is left alone: a drag that begins on a\n * link, a button or a field is that control's drag, not a selection. `data-wx-no-select`\n * opts a region out by hand — a description a reader needs to copy, say.\n */\nconst INTERACTIVE =\n 'a[href], button, input, select, textarea, label, summary, [contenteditable], [draggable=\"true\"], [data-wx-no-select]'\n\nconst root = ref<HTMLElement | null>(null)\n\nconst selecting = ref(false)\n\nconst box = ref<Box | null>(null)\n\nconst selected = computed(() => new Set(model.value))\n\nfunction isSelected(value: SelectionValue) {\n return selected.value.has(value)\n}\n\n/* The drag is plain variables rather than refs: none of it is rendered except the box. */\nlet pointer = -1\nlet started = false\n/** Whether this gesture is allowed to become a box, or is only ever a click. */\nlet boxDrag = true\n/**\n * What the gesture began on. Read here rather than off the event that ends it: once the\n * pointer is captured every event is retargeted to the area, so the release reports the\n * area itself — which read as a click on the background, and cleared the selection every\n * time a card was clicked. It is also the right question to ask: a click is a press and a\n * release on the same thing.\n */\nlet downTarget: HTMLElement | null = null\n/*\n * The modifiers held when the press began. A click is read on release, and a key let go a\n * moment early — or a tool that holds it for the press only — made a ctrl-click a plain one\n * that replaced the selection instead of adding to it.\n */\nlet downShift = false\nlet downToggle = false\nlet downX = 0\nlet downY = 0\nlet originX = 0\nlet originY = 0\nlet atX = 0\nlet atY = 0\nlet borderLeft = 0\nlet borderTop = 0\nlet candidates: Candidate[] = []\nlet base: SelectionValue[] = []\nlet mode: 'replace' | 'add' | 'subtract' = 'replace'\nlet anchor = -1\nlet scroller: HTMLElement | null = null\nlet frame = 0\n\nfunction items() {\n const el = root.value\n if (!el) return [] as { el: HTMLElement; value: SelectionValue }[]\n const found: { el: HTMLElement; value: SelectionValue }[] = []\n for (const node of el.querySelectorAll<HTMLElement>(`[${SELECTABLE}]`)) {\n const value = valueOf(node)\n if (value !== undefined) found.push({ el: node, value })\n }\n return found\n}\n\n/*\n * Everything is worked out in the area's own content coordinates — the distance from the\n * inside of its top left corner, with whatever it is scrolled by added back. Those numbers\n * do not move when anything scrolls, which is why the items can be measured once at the\n * start of a drag and still be right after the box has pulled the list down a screen and a\n * half. It is also the frame the box is drawn in: an absolutely positioned child of a\n * scrolling parent is placed in exactly these coordinates.\n */\nfunction point(clientX: number, clientY: number) {\n const el = root.value\n if (!el) return { x: 0, y: 0 }\n const rect = el.getBoundingClientRect()\n return {\n x: clientX - rect.left - borderLeft + el.scrollLeft,\n y: clientY - rect.top - borderTop + el.scrollTop,\n }\n}\n\nfunction measure() {\n const el = root.value\n if (!el) return\n const style = getComputedStyle(el)\n borderLeft = Number.parseFloat(style.borderLeftWidth) || 0\n borderTop = Number.parseFloat(style.borderTopWidth) || 0\n const rect = el.getBoundingClientRect()\n const left = rect.left + borderLeft - el.scrollLeft\n const top = rect.top + borderTop - el.scrollTop\n candidates = items().map(({ el: node, value }) => {\n const at = node.getBoundingClientRect()\n return {\n value,\n left: at.left - left,\n top: at.top - top,\n right: at.right - left,\n bottom: at.bottom - top,\n width: at.width,\n height: at.height,\n }\n })\n}\n\nfunction hits(at: Box) {\n const right = at.left + at.width\n const bottom = at.top + at.height\n const caught: SelectionValue[] = []\n for (const item of candidates) {\n const inside =\n props.match === 'contain'\n ? item.left >= at.left && item.top >= at.top && item.right <= right && item.bottom <= bottom\n : item.left < right && item.right > at.left && item.top < bottom && item.bottom > at.top\n if (inside) caught.push(item.value)\n }\n return caught\n}\n\n/*\n * What the drag started from decides what it does to what was already selected: on its own\n * it replaces it, held with a modifier it adds to it, held with alt it takes away. The\n * selection the drag began with is kept aside so that every move works out from there\n * rather than from the last frame — a box dragged back over its own path has to let items\n * go again.\n */\nfunction resolve(caught: SelectionValue[]) {\n if (mode === 'replace') return caught\n if (mode === 'subtract') {\n const drop = new Set(caught)\n return base.filter((value) => !drop.has(value))\n }\n const have = new Set(base)\n return [...base, ...caught.filter((value) => !have.has(value))]\n}\n\nfunction apply(next: SelectionValue[]) {\n const now = model.value\n if (next.length === now.length && next.every((value, index) => value === now[index])) return\n model.value = next\n}\n\nfunction update() {\n const at = point(atX, atY)\n const next = {\n left: Math.min(at.x, originX),\n top: Math.min(at.y, originY),\n width: Math.abs(at.x - originX),\n height: Math.abs(at.y - originY),\n }\n box.value = next\n apply(resolve(hits(next)))\n}\n\nfunction viewport(el: HTMLElement) {\n if (el === document.scrollingElement) {\n return { left: 0, top: 0, right: window.innerWidth, bottom: window.innerHeight }\n }\n const rect = el.getBoundingClientRect()\n return { left: rect.left, top: rect.top, right: rect.right, bottom: rect.bottom }\n}\n\n/* The further past the edge the pointer is, the faster it goes. */\nfunction speed(at: number, min: number, max: number, edge: number) {\n const step = 18\n if (at < min + edge) return -Math.ceil(Math.min(1, (min + edge - at) / edge) * step)\n if (at > max - edge) return Math.ceil(Math.min(1, (at - (max - edge)) / edge) * step)\n return 0\n}\n\nfunction scrollerOf(from: HTMLElement) {\n const scrolls = /auto|scroll|overlay/\n let el: HTMLElement | null = from\n while (el) {\n const style = getComputedStyle(el)\n if (\n (scrolls.test(style.overflowY) && el.scrollHeight > el.clientHeight) ||\n (scrolls.test(style.overflowX) && el.scrollWidth > el.clientWidth)\n ) {\n return el\n }\n el = el.parentElement\n }\n return (document.scrollingElement as HTMLElement | null) ?? null\n}\n\n/*\n * The frame loop is there for the edge scrolling alone. A box held still against the foot\n * of the list has to keep pulling it up, and a pointer that is not moving sends no events —\n * so where it last was is remembered, and read again every frame.\n */\nfunction tick() {\n frame = requestAnimationFrame(tick)\n if (scroller) {\n const view = viewport(scroller)\n const dx = speed(atX, view.left, view.right, props.edgeScroll)\n const dy = speed(atY, view.top, view.bottom, props.edgeScroll)\n if (dx) scroller.scrollLeft += dx\n if (dy) scroller.scrollTop += dy\n }\n update()\n}\n\nfunction stop() {\n if (frame) cancelAnimationFrame(frame)\n frame = 0\n const el = root.value\n if (el && pointer !== -1 && el.hasPointerCapture?.(pointer)) el.releasePointerCapture(pointer)\n pointer = -1\n started = false\n downTarget = null\n scroller = null\n selecting.value = false\n box.value = null\n}\n\nfunction pick(event: PointerEvent, from: HTMLElement | null) {\n const el = from?.closest(`[${SELECTABLE}]`)\n if (!el) {\n /* The background is what clears a selection — the one gesture every file list shares. */\n if (mode === 'replace') apply([])\n return\n }\n const value = valueOf(el)\n if (value === undefined) return\n const index = candidates.findIndex((item) => item.value === value)\n\n /*\n * One at a time. The run and the toggle are both ways of ending up holding more than\n * one, so neither is offered: picking is picking, and the background is how you end up\n * holding none.\n */\n if (!props.multiple) {\n anchor = index\n apply([value])\n return\n }\n\n if ((event.shiftKey || downShift) && anchor >= 0 && index >= 0) {\n const [from, to] = anchor < index ? [anchor, index] : [index, anchor]\n apply(resolve(candidates.slice(from, to + 1).map((item) => item.value)))\n return\n }\n\n anchor = index\n\n /*\n * A finger has no ctrl key and no box to draw, so on a touch screen the tap is the only\n * gesture there is — and a tap that replaces the selection can never build one. It adds\n * and removes instead; the background still clears, which is the way back out.\n */\n const toggles = event.ctrlKey || event.metaKey || downToggle || event.pointerType === 'touch'\n\n if (toggles) {\n apply(selected.value.has(value) ? base.filter((held) => held !== value) : [...base, value])\n return\n }\n\n apply([value])\n}\n\n/**\n * A control inside the area keeps its press: a button, a field, something dragged on its own.\n * An item that is draggable because of `dragItems` is not one of those — it is still an item,\n * and a click on it still picks it.\n */\nfunction ownControl(target: HTMLElement): boolean {\n const hit = target.closest(INTERACTIVE)\n\n return hit !== null && !(props.dragItems && hit.hasAttribute(SELECTABLE))\n}\n\nfunction onPointerDown(event: PointerEvent) {\n const el = root.value\n if (props.disabled || !el || event.button !== 0) return\n if (ownControl(event.target as HTMLElement)) return\n\n const isTouch = event.pointerType === 'touch'\n\n /*\n * A rubber band is a gesture for taking several things, so there is none where only one\n * may be held. And a finger dragged across a list means scroll: without `touch` that\n * gesture is followed but never becomes a box. It is still followed — a tap has to pick\n * the item under it, and bailing out here is how a touch screen came to select nothing.\n */\n boxDrag =\n props.multiple &&\n (!isTouch || props.touch) &&\n !(props.dragItems && (event.target as HTMLElement).closest(`[${SELECTABLE}]`))\n\n pointer = event.pointerId\n started = false\n downTarget = event.target as HTMLElement\n downShift = event.shiftKey\n downToggle = event.ctrlKey || event.metaKey\n downX = event.clientX\n downY = event.clientY\n atX = event.clientX\n atY = event.clientY\n base = [...model.value]\n mode = event.altKey\n ? 'subtract'\n : event.shiftKey || event.ctrlKey || event.metaKey\n ? 'add'\n : 'replace'\n\n measure()\n const at = point(event.clientX, event.clientY)\n originX = at.x\n originY = at.y\n\n /* Puts the shortcuts within reach. */\n el.focus({ preventScroll: true })\n\n /*\n * A finger's gesture belongs to the page unless the box is about to take it. A mouse\n * has nothing to lose either way, so it is captured whether or not a box follows —\n * that is what keeps a press and its release one gesture.\n */\n if (isTouch && !boxDrag) return\n\n /*\n * A finger has the scroll taken out of the page here, which is why a tap-only gesture is\n * left alone above.\n *\n * A mouse must not: preventing the default on `pointerdown` also suppresses the\n * compatibility mouse events the browser builds a double click out of, and `dblclick` then\n * never fires inside the area. A grid where double click opens an item silently stops\n * opening anything — and a synthetic `dblclick` in a test still works, so nothing catches\n * it. The caret is taken out of the text when a box actually starts instead.\n */\n if (isTouch) event.preventDefault()\n}\n\n/**\n * Capture is what keeps the moves coming once the pointer leaves the area — so it is taken\n * when a box actually starts, not when the pointer goes down.\n *\n * Capturing on press retargets everything that follows to the area, and the compatibility\n * mouse events go with it: an item below never sees `mouseup`, `click` or `dblclick`. That is\n * invisible in a test, where a synthetic `dblclick` is dispatched straight at the item.\n *\n * Best effort: a pointer the browser is not tracking cannot be captured, and the drag is no\n * worse for it while the pointer stays inside.\n */\nfunction capture(pointerId: number): void {\n try {\n root.value?.setPointerCapture?.(pointerId)\n } catch {\n /* No live pointer by that id. */\n }\n}\n\nfunction onPointerMove(event: PointerEvent) {\n if (event.pointerId !== pointer) return\n atX = event.clientX\n atY = event.clientY\n\n if (!started) {\n if (Math.hypot(event.clientX - downX, event.clientY - downY) < props.threshold) return\n /* Travelled too far to be a tap, and there is no box to turn into: it was a scroll. */\n if (!boxDrag) {\n stop()\n return\n }\n started = true\n selecting.value = true\n capture(event.pointerId)\n /*\n * The press was allowed to place a caret so that a double click still reaches the items;\n * now that a box is being drawn, the text it started in goes.\n */\n event.preventDefault()\n window.getSelection?.()?.removeAllRanges()\n emit('start')\n if (props.edgeScroll > 0 && root.value) scroller = scrollerOf(root.value)\n if (scroller) frame = requestAnimationFrame(tick)\n }\n\n update()\n}\n\nfunction onPointerUp(event: PointerEvent) {\n if (event.pointerId !== pointer) return\n const dragged = started\n /* `stop` forgets where the gesture began, and the click still has to be told. */\n const from = downTarget\n stop()\n if (dragged) emit('end', [...model.value])\n else if (props.clickSelect) pick(event, from)\n}\n\n/*\n * The browser taking the gesture over — a finger that turned into a scroll, a palm on the\n * screen. Whatever was drawn is over, but nothing was chosen: a cancelled gesture that\n * picked the item it happened to start on is how a scroll comes to change the selection.\n */\nfunction onPointerCancel(event: PointerEvent) {\n if (event.pointerId !== pointer) return\n const dragged = started\n stop()\n if (dragged) emit('end', [...model.value])\n}\n\nfunction onKeydown(event: KeyboardEvent) {\n if (props.disabled) return\n\n if (event.key === 'Escape') {\n if (started) {\n apply(base)\n stop()\n } else if (model.value.length) {\n apply([])\n }\n return\n }\n\n if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'a') {\n if (!props.multiple) return\n if ((event.target as HTMLElement).closest(INTERACTIVE)) return\n event.preventDefault()\n selectAll()\n }\n}\n\n/** Everything there is. Nothing at all where only one may be held. */\nfunction selectAll() {\n if (!props.multiple) return\n apply(items().map((item) => item.value))\n}\n\nfunction clear() {\n apply([])\n}\n\nonBeforeUnmount(stop)\n\ndefineExpose({ selectAll, clear })\n</script>\n\n<template>\n <div\n ref=\"root\"\n class=\"wx-selection-area\"\n :class=\"{ 'is-selecting': selecting, 'is-disabled': disabled, 'is-touch': touch }\"\n tabindex=\"-1\"\n @pointerdown=\"onPointerDown\"\n @pointermove=\"onPointerMove\"\n @pointerup=\"onPointerUp\"\n @pointercancel=\"onPointerCancel\"\n @keydown=\"onKeydown\"\n >\n <slot :selected=\"selected\" :is-selected=\"isSelected\" :selecting=\"selecting\" />\n\n <div\n v-if=\"box\"\n class=\"wx-selection-area__box\"\n :style=\"{\n left: `${box.left}px`,\n top: `${box.top}px`,\n width: `${box.width}px`,\n height: `${box.height}px`,\n }\"\n />\n </div>\n</template>\n\n<style scoped>\n.wx-selection-area {\n position: relative;\n /* Its own stacking context, so the box is over its items and under nothing else. */\n isolation: isolate;\n}\n\n/* The area is focusable so the shortcuts have somewhere to land, not as a stop on the way. */\n.wx-selection-area:focus {\n outline: none;\n}\n\n/*\n * A finger drag is the browser's before it is ours: left alone it becomes a scroll and the\n * pointer events stop arriving, which is why box selection worked in a desktop browser's\n * device emulator and did nothing at all on a phone. Claiming the gesture is the price of\n * `touch`, and it is why `touch` is off by default.\n */\n.wx-selection-area.is-touch {\n touch-action: none;\n}\n\n.wx-selection-area.is-selecting {\n user-select: none;\n -webkit-user-select: none;\n}\n\n.wx-selection-area__box {\n position: absolute;\n /* Over the items it is drawn across — within this area, which is a stacking context. */\n z-index: 10;\n background: color-mix(in srgb, var(--wx-color-primary) 12%, transparent);\n border: 1px solid var(--wx-color-primary);\n border-radius: var(--wx-radius-xs);\n pointer-events: none;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { SkeletonItemProps } from '../Skeleton/types'\n\ndefineOptions({ name: 'WxSkeletonItem' })\n\nconst props = withDefaults(defineProps<SkeletonItemProps>(), {\n variant: 'text',\n width: undefined,\n height: undefined,\n animated: true,\n})\n\nfunction length(value: string | number | undefined) {\n if (value === undefined) return undefined\n return typeof value === 'number' ? `${value}px` : value\n}\n\nconst classes = computed(() => [\n 'wx-skeleton-item',\n `wx-skeleton-item--${props.variant}`,\n { 'wx-skeleton-item--animated': props.animated },\n])\n\nconst style = computed(() => ({\n width: length(props.width),\n height: length(props.height),\n}))\n</script>\n\n<template>\n <span :class=\"classes\" :style=\"style\" aria-hidden=\"true\" />\n</template>\n\n<style scoped>\n.wx-skeleton-item {\n display: block;\n box-sizing: border-box;\n background: var(--wx-bg-fill);\n border-radius: var(--wx-radius-xs);\n}\n\n.wx-skeleton-item--text {\n width: 100%;\n height: 0.85em;\n border-radius: var(--wx-radius-xs);\n}\n\n.wx-skeleton-item--title {\n width: 40%;\n height: 1.25em;\n}\n\n.wx-skeleton-item--circle {\n width: 32px;\n height: 32px;\n flex: 0 0 auto;\n border-radius: var(--wx-radius-full);\n}\n\n.wx-skeleton-item--square {\n width: 32px;\n height: 32px;\n flex: 0 0 auto;\n}\n\n.wx-skeleton-item--image {\n width: 100%;\n height: 140px;\n border-radius: var(--wx-radius-sm);\n}\n\n.wx-skeleton-item--button {\n width: 96px;\n height: var(--wx-size-control-md);\n border-radius: var(--wx-radius-control);\n}\n\n/*\n * A sheen travelling across the fill rather than the whole block pulsing. A pulse\n * reads as something blinking at you; a sheen reads as work in progress, which is\n * what it is.\n */\n.wx-skeleton-item--animated {\n background-image: linear-gradient(\n 90deg,\n transparent 0%,\n var(--wx-bg-surface) 40%,\n var(--wx-bg-surface) 60%,\n transparent 100%\n );\n background-repeat: no-repeat;\n background-size: 240px 100%;\n animation: wx-skeleton-sheen 1.4s ease-in-out infinite;\n}\n\n@keyframes wx-skeleton-sheen {\n from {\n background-position: -240px 0;\n }\n\n to {\n background-position: calc(100% + 240px) 0;\n }\n}\n\n/*\n * Reduced motion means the sheen stops; the placeholder stays, because it is the\n * message. A still block still says \"not yet\".\n */\n@media (prefers-reduced-motion: reduce) {\n .wx-skeleton-item--animated {\n background-image: none;\n animation: none;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, ref, watch } from 'vue'\nimport WxSkeletonItem from '../SkeletonItem/SkeletonItem.vue'\nimport type { SkeletonProps } from './types'\n\ndefineOptions({ name: 'WxSkeleton' })\n\nconst props = withDefaults(defineProps<SkeletonProps>(), {\n loading: true,\n rows: 3,\n avatar: false,\n title: false,\n animated: true,\n delay: 0,\n})\n\ndefineSlots<{\n /** The real thing, once it has arrived. */\n default?: () => unknown\n /** A placeholder shaped like the real thing, instead of the rows. */\n template?: () => unknown\n}>()\n\n/*\n * A request that answers quickly should not flash a skeleton on the way past. The\n * delay is on showing it, never on hiding it: content that has arrived is shown at\n * once, and a placeholder that has appeared stays long enough to be read as one.\n */\nconst showing = ref(props.delay === 0 && props.loading)\n\nlet timer: ReturnType<typeof setTimeout> | undefined\n\nwatch(\n [() => props.loading, () => props.delay],\n ([loading, delay]) => {\n clearTimeout(timer)\n\n if (!loading) {\n showing.value = false\n return\n }\n\n if (delay === 0) {\n showing.value = true\n return\n }\n\n timer = setTimeout(() => {\n showing.value = true\n }, delay)\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => clearTimeout(timer))\n\nconst lines = computed(() => Math.max(0, props.rows))\n</script>\n\n<template>\n <div v-if=\"showing\" class=\"wx-skeleton\" aria-busy=\"true\" aria-live=\"polite\">\n <slot name=\"template\">\n <div class=\"wx-skeleton__row\">\n <wx-skeleton-item v-if=\"avatar\" variant=\"circle\" :animated=\"animated\" />\n\n <div class=\"wx-skeleton__lines\">\n <wx-skeleton-item v-if=\"title\" variant=\"title\" :animated=\"animated\" />\n <wx-skeleton-item\n v-for=\"line in lines\"\n :key=\"line\"\n variant=\"text\"\n :animated=\"animated\"\n :class=\"{ 'wx-skeleton__last': line === lines && lines > 1 }\"\n />\n </div>\n </div>\n </slot>\n </div>\n\n <slot v-else />\n</template>\n\n<style scoped>\n/*\n * `border-box`, because `width: 100%` and a padding the caller adds are otherwise the width of\n * the parent *plus* that padding — measured, a loader 23px wider than the card it was standing\n * in, hanging over both of its rounded corners. A skeleton stands where the content it stands\n * in for would, and that content is usually inset.\n */\n.wx-skeleton {\n box-sizing: border-box;\n width: 100%;\n}\n\n.wx-skeleton__row {\n display: flex;\n align-items: flex-start;\n gap: var(--wx-space-12);\n}\n\n.wx-skeleton__lines {\n display: flex;\n flex: 1 1 auto;\n flex-direction: column;\n gap: var(--wx-space-8);\n min-width: 0;\n}\n\n/* The last line stops short, the way a paragraph does. */\n.wx-skeleton__last {\n width: 62%;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { SpaceProps } from './types'\n\ndefineOptions({ name: 'WxSpace' })\n\nconst props = withDefaults(defineProps<SpaceProps>(), {\n direction: 'horizontal',\n size: 'md',\n align: undefined,\n justify: undefined,\n wrap: true,\n fill: false,\n inline: false,\n as: 'div',\n})\n\nconst sizes: Record<string, string> = {\n xs: 'var(--wx-space-4)',\n sm: 'var(--wx-space-8)',\n md: 'var(--wx-space-12)',\n lg: 'var(--wx-space-16)',\n xl: 'var(--wx-space-24)',\n}\n\nconst gap = computed(() => {\n const { size } = props\n if (typeof size === 'number') return `${size}px`\n return sizes[size] ?? size\n})\n\nconst classes = computed(() => [\n 'wx-space',\n `wx-space--${props.direction}`,\n {\n 'wx-space--inline': props.inline,\n 'wx-space--wrap': props.wrap && props.direction === 'horizontal',\n 'wx-space--fill': props.fill,\n [`wx-space--align-${props.align}`]: Boolean(props.align),\n [`wx-space--justify-${props.justify}`]: Boolean(props.justify),\n },\n])\n</script>\n\n<template>\n <component :is=\"as\" :class=\"classes\" :style=\"{ '--wx-space-gap': gap }\">\n <slot />\n </component>\n</template>\n\n<style scoped>\n.wx-space {\n display: flex;\n gap: var(--wx-space-gap, var(--wx-space-12));\n /* Nothing may spill sideways out of a row that is told not to wrap. */\n min-width: 0;\n}\n\n.wx-space--inline {\n display: inline-flex;\n vertical-align: middle;\n}\n\n.wx-space--horizontal {\n flex-direction: row;\n align-items: center;\n}\n\n.wx-space--vertical {\n flex-direction: column;\n align-items: stretch;\n}\n\n.wx-space--wrap {\n flex-wrap: wrap;\n}\n\n/* alignment across the line */\n.wx-space--align-start {\n align-items: flex-start;\n}\n\n.wx-space--align-center {\n align-items: center;\n}\n\n.wx-space--align-end {\n align-items: flex-end;\n}\n\n.wx-space--align-baseline {\n align-items: baseline;\n}\n\n.wx-space--align-stretch {\n align-items: stretch;\n}\n\n/* distribution along it */\n.wx-space--justify-start {\n justify-content: flex-start;\n}\n\n.wx-space--justify-center {\n justify-content: center;\n}\n\n.wx-space--justify-end {\n justify-content: flex-end;\n}\n\n.wx-space--justify-between {\n justify-content: space-between;\n}\n\n.wx-space--justify-around {\n justify-content: space-around;\n}\n\n.wx-space--justify-evenly {\n justify-content: space-evenly;\n}\n\n/*\n * `fill` divides the line evenly. `min-width: 0` on the children matters more than\n * it looks: without it a long label makes its child refuse to shrink, and the row\n * overflows instead of sharing the space.\n */\n.wx-space--fill > :deep(*) {\n flex: 1 1 0;\n min-width: 0;\n}\n</style>\n","import { inject, type InjectionKey } from 'vue'\nimport type { StepsContext } from './types'\n\nexport const stepsKey: InjectionKey<StepsContext> = Symbol('wx-steps')\n\n/** A step outside a sequence is one step, on its own, and still renders. */\nexport function useSteps(): StepsContext {\n return inject(stepsKey, {\n register: () => {},\n unregister: () => {},\n indexOf: () => 0,\n stateOf: () => 'current',\n choose: () => {},\n direction: 'horizontal',\n size: 'md',\n clickable: false,\n total: 1,\n })\n}\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount } from 'vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport { useSteps } from '../Steps/context'\nimport type { StepProps } from '../Steps/types'\n\ndefineOptions({ name: 'WxStep' })\n\nwithDefaults(defineProps<StepProps>(), {\n title: undefined,\n description: undefined,\n icon: undefined,\n})\n\ndefineSlots<{\n title?: () => unknown\n /** The explanation. Overrides `description`. */\n default?: () => unknown\n /** Replaces the marker — a number by default, a tick once it is done. */\n marker?: (props: { index: number; state: string }) => unknown\n}>()\n\nconst steps = useSteps()\n\nconst id = Symbol('wx-step')\n\n/*\n * Registered while setting up rather than on mount. Children set up in the order\n * they are written, so the numbering is right for the first paint — registering\n * later means every step renders as finished for one frame before finding its\n * place, which is a flicker on every page that has a wizard on it.\n */\nsteps.register(id)\n\nonBeforeUnmount(() => steps.unregister(id))\n\nconst index = computed(() => steps.indexOf(id))\n\nconst state = computed(() => steps.stateOf(index.value))\n\nconst interactive = computed(() => steps.clickable && state.value === 'done')\n\nconst classes = computed(() => [\n 'wx-step',\n `wx-step--${state.value}`,\n { 'is-interactive': interactive.value },\n])\n</script>\n\n<template>\n <li :class=\"classes\" :aria-current=\"state === 'current' ? 'step' : undefined\">\n <component\n :is=\"interactive ? 'button' : 'div'\"\n class=\"wx-step__head\"\n :type=\"interactive ? 'button' : undefined\"\n @click=\"interactive && steps.choose(index)\"\n >\n <span class=\"wx-step__marker\">\n <slot name=\"marker\" :index=\"index\" :state=\"state\">\n <wx-icon v-if=\"state === 'done'\" name=\"check\" />\n <wx-icon v-else-if=\"state === 'error'\" name=\"close\" />\n <wx-icon v-else-if=\"icon\" :name=\"icon\" />\n <span v-else>{{ index + 1 }}</span>\n </slot>\n </span>\n\n <span class=\"wx-step__text\">\n <span v-if=\"title || $slots.title\" class=\"wx-step__title\">\n <slot name=\"title\">{{ title }}</slot>\n </span>\n <span v-if=\"description || $slots.default\" class=\"wx-step__description\">\n <slot>{{ description }}</slot>\n </span>\n </span>\n </component>\n </li>\n</template>\n\n<style scoped>\n.wx-step {\n position: relative;\n display: flex;\n min-width: 0;\n /*\n * The step owns its margins, and says so from a scoped rule so that it outweighs a\n * host stylesheet spacing list items — VitePress puts 8px between every `li + li`,\n * and a CMS theme will have its own. Left alone, that drops every step but the\n * first by eight pixels and the rule between them runs downhill.\n */\n margin: 0;\n}\n\n.wx-step__head {\n display: flex;\n gap: var(--wx-space-10);\n min-width: 0;\n padding: 0;\n background: none;\n border: none;\n color: inherit;\n font: inherit;\n text-align: start;\n}\n\n.is-interactive .wx-step__head {\n cursor: pointer;\n}\n\n.is-interactive .wx-step__head:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n border-radius: var(--wx-radius-xs);\n}\n\n/*\n * The marker carries the state — a number ahead, a tick behind, a cross where it\n * went wrong — and the ring around the current one is what a reader looks for to\n * find their place.\n */\n.wx-step__marker {\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n flex: 0 0 auto;\n width: var(--wx-step-marker, 32px);\n height: var(--wx-step-marker, 32px);\n background: var(--wx-bg-fill);\n border: 1px solid transparent;\n border-radius: var(--wx-radius-full);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n font-weight: var(--wx-font-weight-semibold);\n transition:\n background var(--wx-duration-fast) var(--wx-easing-standard),\n color var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-step--done .wx-step__marker {\n background: var(--wx-color-primary-soft);\n color: var(--wx-color-primary);\n}\n\n.wx-step--current .wx-step__marker {\n background: var(--wx-color-primary);\n color: var(--wx-color-primary-contrast);\n}\n\n.wx-step--error .wx-step__marker {\n background: var(--wx-color-danger-soft);\n color: var(--wx-color-danger);\n}\n\n.wx-step__text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n padding-top: 4px;\n}\n\n.wx-step__title {\n color: var(--wx-text-muted);\n font-size: var(--wx-step-title, var(--wx-font-size-md));\n font-weight: var(--wx-font-weight-medium);\n line-height: var(--wx-font-line-height-tight);\n}\n\n.wx-step--done .wx-step__title,\n.wx-step--current .wx-step__title {\n color: var(--wx-text-strong);\n}\n\n.wx-step--error .wx-step__title {\n color: var(--wx-color-danger);\n}\n\n.wx-step__description {\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n line-height: var(--wx-font-line-height-normal);\n}\n\n/*\n * The rule to the next step is a pseudo-element chosen by `:last-child` rather than\n * an element chosen by counting. A step that has to be told how many siblings it has\n * cannot know on its first render — every one of them would think it was the last,\n * and the rules would appear a frame later.\n */\n.wx-step:not(:last-child)::after {\n content: '';\n background: var(--wx-border-default);\n}\n\n/* A finished step's rule is drawn in the accent: the path taken so far. */\n.wx-step--done:not(:last-child)::after {\n background: var(--wx-color-primary);\n}\n\n/* --- horizontal --- */\n\n.wx-steps--horizontal .wx-step {\n flex: 1 1 0;\n align-items: flex-start;\n gap: var(--wx-space-8);\n}\n\n.wx-steps--horizontal .wx-step__head {\n min-width: 0;\n}\n\n/*\n * The step is a flex row, so the rule is simply the flex item after the head: it\n * takes whatever room is left between this step's text and the next step's marker.\n * Placing it absolutely instead would mean knowing where the text ends, which is\n * exactly what a pseudo-element cannot be told — and what drew the rule straight\n * through the titles.\n */\n.wx-steps--horizontal .wx-step:not(:last-child)::after {\n flex: 1 1 auto;\n /* Level with the middle of the marker, whatever size the markers are. */\n margin-top: calc(var(--wx-step-marker, 32px) / 2);\n min-width: var(--wx-space-16);\n height: 1px;\n}\n\n.wx-steps--horizontal .wx-step:last-child {\n flex: 0 1 auto;\n}\n\n/* --- vertical --- */\n\n.wx-steps--vertical .wx-step {\n flex-direction: column;\n padding-bottom: var(--wx-space-16);\n}\n\n.wx-steps--vertical .wx-step:last-child {\n padding-bottom: 0;\n}\n\n/*\n * Down the page the rule runs beside the text rather than after it, so here it is\n * taken out of the flow and hung from the marker's centre line.\n */\n.wx-steps--vertical .wx-step:not(:last-child)::after {\n position: absolute;\n top: calc(var(--wx-step-marker, 32px) + 4px);\n bottom: 4px;\n inset-inline-start: calc(var(--wx-step-marker, 32px) / 2);\n width: 1px;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-step__marker {\n transition: none;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, provide, ref } from 'vue'\nimport { useElementWidth } from '../../composables/useElementWidth'\nimport { stepsKey } from './context'\nimport type { StepsEmits, StepsProps, StepState } from './types'\n\ndefineOptions({ name: 'WxSteps' })\n\nconst props = withDefaults(defineProps<StepsProps>(), {\n current: 0,\n direction: 'horizontal',\n size: 'md',\n error: false,\n clickable: false,\n minStepWidth: 132,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<StepsEmits>()\n\ndefineSlots<{ default?: () => unknown }>()\n\n/*\n * The steps report themselves in mount order rather than being declared as data.\n * A step's content is markup — a title, a description, sometimes a form — and the\n * shape that holds markup is a slot, so the numbering has to come from the DOM.\n */\nconst ids = ref<symbol[]>([])\n\nconst list = ref<HTMLElement | null>(null)\nconst width = useElementWidth(list)\n\n/*\n * Across the page a step is a marker, a title and a line of explanation side by side, and\n * on a phone there is room for about one of those. Rather than let the titles wrap to a\n * letter a line, the sequence turns down the page — which is the same sequence, read the\n * way a narrow screen reads everything else.\n *\n * How many steps there are is part of the question, so this is a measurement rather than a\n * media or container query: four steps need four times the room two do. A width of `0` is\n * \"not measured yet\" — on the server and before the first frame — and the roomy answer is\n * the safe one there.\n */\nconst direction = computed(() => {\n if (props.direction === 'vertical' || props.minStepWidth <= 0) return props.direction\n if (width.value === 0 || ids.value.length === 0) return props.direction\n return width.value < ids.value.length * props.minStepWidth ? 'vertical' : 'horizontal'\n})\n\nprovide(stepsKey, {\n register: (id) => {\n if (!ids.value.includes(id)) ids.value.push(id)\n },\n unregister: (id) => {\n ids.value = ids.value.filter((known) => known !== id)\n },\n indexOf: (id) => ids.value.indexOf(id),\n stateOf: (index): StepState => {\n if (index < props.current) return 'done'\n if (index > props.current) return 'todo'\n return props.error ? 'error' : 'current'\n },\n choose: (index) => {\n /* Only backwards: the steps ahead are the ones not filled in yet. */\n if (!props.clickable || index >= props.current) return\n emit('change', index)\n },\n get direction() {\n return direction.value\n },\n get size() {\n return props.size\n },\n get clickable() {\n return props.clickable\n },\n get total() {\n return ids.value.length\n },\n})\n\nconst classes = computed(() => [\n 'wx-steps',\n `wx-steps--${direction.value}`,\n `wx-steps--${props.size}`,\n { 'is-folded': direction.value !== props.direction },\n])\n</script>\n\n<template>\n <ol ref=\"list\" :class=\"classes\" :aria-label=\"ariaLabel\">\n <slot />\n </ol>\n</template>\n\n<style scoped>\n.wx-steps {\n display: flex;\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n list-style: none;\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n}\n\n/*\n * The gap between steps is the other half of the one inside them. Each step already\n * holds its rule off its own text; without this the rule then ran straight into the\n * next step's marker, and the spacing either side of it did not match.\n */\n.wx-steps--horizontal {\n flex-direction: row;\n align-items: flex-start;\n gap: var(--wx-space-8);\n}\n\n.wx-steps--vertical {\n flex-direction: column;\n}\n\n.wx-steps--sm {\n --wx-step-marker: 24px;\n --wx-step-title: var(--wx-font-size-sm);\n}\n\n.wx-steps--md {\n --wx-step-marker: 32px;\n --wx-step-title: var(--wx-font-size-md);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { TabsContent } from 'reka-ui'\nimport type { TabProps } from './types'\n\ndefineOptions({ name: 'WxTab' })\n\n/*\n * A tab is written once and read twice: `WxTabs` looks at these props to build the\n * button in the strip, and the component itself renders only the panel. That is why\n * `label`, `icon` and `badge` live here rather than on a separate list of items —\n * a tab and its content stay together in the markup.\n */\nwithDefaults(defineProps<TabProps>(), {\n label: undefined,\n icon: undefined,\n badge: undefined,\n disabled: false,\n keepAlive: false,\n})\n\ndefineSlots<{\n /** The panel. */\n default?: () => unknown\n /** Replaces `label` in the strip — an avatar, a coloured dot, anything. */\n label?: () => unknown\n}>()\n</script>\n\n<template>\n <tabs-content class=\"wx-tab\" :value=\"value\" :force-mount=\"keepAlive || undefined\">\n <slot />\n </tabs-content>\n</template>\n\n<style scoped>\n/*\n * A panel is a column of things — cards, fields, a table — and it owes them the air between\n * them: they carry no margins of their own, so without this they stand flush and two cards\n * read as one with a line through it (§6.2 of the visual spec). The step is the panel's;\n * outside one it is the desktop step.\n *\n * The column is also how a page tells a tab to be as tall as the screen: a page that fills\n * adds `flex: 1` on top of this, and that only works on a flex child of a flex parent.\n */\n.wx-tab {\n display: flex;\n flex-direction: column;\n gap: var(--wx-gap, var(--wx-space-16));\n}\n\n.wx-tab:focus-visible {\n outline: none;\n}\n\n/*\n * Reka hides an inactive panel with the attribute, and the display above would take that\n * away — kept alive, the hidden panels are still in the document, and each would claim its\n * share of the height (CLAUDE.md §4). The attribute selector is the more specific of the two.\n */\n.wx-tab[hidden] {\n display: none;\n}\n</style>\n","import { computed, ref, toValue, watch, type MaybeRefOrGetter, type Ref } from 'vue'\n\nexport type TreeKey = string | number\n\n/** Where a dragged node lands relative to the one it was dropped on. */\nexport type TreeDropZone = 'before' | 'after' | 'inside'\n\n/**\n * How to read one node. Everything else here works through these four, which is what\n * lets the same machinery drive a tree of its own and a table whose rows happen to\n * nest: neither has to agree with the other on what a node looks like.\n */\nexport interface TreeAccessors<T> {\n key: (node: T, path: number[]) => TreeKey\n children: (node: T) => T[] | undefined\n /** Called when a branch that had no `children` array needs one. */\n setChildren: (node: T, children: T[]) => void\n label?: (node: T) => string\n disabled?: (node: T) => boolean\n /** Says a node has nothing under it — only needed with `lazy`, where an empty\n * `children` cannot tell \"not loaded yet\" from \"nothing there\". */\n leaf?: (node: T) => boolean\n}\n\n/** One node and everything about where it sits, kept for the whole tree. */\nexport interface TreeEntry<T> {\n node: T\n key: TreeKey\n depth: number\n /** The array this node currently lives in — moving is a splice on it. */\n siblings: T[]\n index: number\n parent: T | null\n parentKey: TreeKey | null\n children: T[]\n}\n\n/** A node as the screen shows it: visible, in order, at a depth. */\nexport interface TreeRow<T> extends TreeEntry<T> {\n expandable: boolean\n expanded: boolean\n loading: boolean\n disabled: boolean\n /** Matched the filter itself, as opposed to merely leading to a match. */\n matched: boolean\n}\n\nexport interface UseTreeNodesOptions<T> {\n /**\n * The tree. A getter or a plain array is enough for a tree that is only read; a\n * `ref` is what a tree that can be rearranged wants, since a move splices the array\n * the caller is holding.\n */\n nodes: MaybeRefOrGetter<T[]>\n accessors: TreeAccessors<T>\n /** Keys of the open branches. Owned by the caller, so `v-model:expanded` works. */\n expanded: Ref<TreeKey[]>\n /** Only branches matching this, and the branches leading to them, are shown. */\n filter?: MaybeRefOrGetter<string | undefined>\n /** Opening a branch closes the others at its level. */\n accordion?: MaybeRefOrGetter<boolean>\n /** Children arrive when a branch opens. Requires `load`. */\n lazy?: MaybeRefOrGetter<boolean>\n load?: (node: T) => T[] | Promise<T[]>\n /** Vetoes a move before it happens. */\n allowDrop?: (drag: T, drop: T, zone: TreeDropZone) => boolean\n}\n\n/*\n * Bumped whenever a fetched branch is written into its node, and shared by every index\n * in the application rather than kept per instance.\n *\n * Two reasons it cannot be private. A tree handed over as a plain array — which is what\n * a tree arriving through a prop usually is — holds no proxies, so writing children into\n * one of its nodes changes nothing an index is watching. And the same nodes are commonly\n * read by more than one index: `WxTreeSelect` keeps one to name the value in its field\n * while the tree inside its panel keeps another, and it is the second that does the\n * fetching. A counter the fetcher alone could see would leave the field showing an id.\n *\n * The cost is that an unrelated tree rebuilds its index when this one fetches. That is a\n * walk over an array that is already in memory, against a fetch that a person had to\n * click for.\n */\nconst fetched = ref(0)\n\n/**\n * The parts of a tree that have nothing to do with how it looks: what is where, what is\n * open, what a filter leaves standing, and what a move does to the arrays underneath.\n */\nexport function useTreeNodes<T>(options: UseTreeNodesOptions<T>) {\n const { nodes, accessors, expanded } = options\n\n const loading = ref(new Set<TreeKey>())\n /**\n * Branches `load` has already answered for — an empty answer still counts.\n *\n * Held against the node itself rather than its key, because a level that is fetched again\n * comes back as new objects under the same keys, and the children read into the old ones\n * are gone with them. Kept by key, the tree would take the new node's missing `children`\n * for the answer it already has and never ask again: the branch stays open and empty, its\n * chevron closes and opens the same nothing, and only a page reload brings it back.\n */\n const loaded = new WeakSet<object>()\n /** Nodes whose refill threw, so the retry is the reader's click and not a loop. */\n const refused = new WeakSet<object>()\n\n /** A node as the identity those two sets are keyed by. */\n const identity = (node: T) => node as unknown as object\n\n const entries = computed(() => {\n void fetched.value\n\n const map = new Map<TreeKey, TreeEntry<T>>()\n\n const walk = (\n list: T[],\n parent: T | null,\n parentKey: TreeKey | null,\n depth: number,\n path: number[],\n ) => {\n list.forEach((node, index) => {\n const here = [...path, index]\n const key = accessors.key(node, here)\n const children = accessors.children(node) ?? []\n map.set(key, { node, key, depth, siblings: list, index, parent, parentKey, children })\n if (children.length) walk(children, node, key, depth + 1, here)\n })\n }\n\n walk(toValue(nodes), null, null, 0, [])\n return map\n })\n\n const entry = (key: TreeKey) => entries.value.get(key)\n const keyOf = (node: T, path: number[] = []) => accessors.key(node, path)\n\n /* -------------------------------------------------------------- filtering */\n\n /**\n * A filter answers with two sets rather than a new tree: the nodes that matched, and\n * every node that has to stay on screen for a match to be reachable. Rebuilding the\n * array instead would lose the identity the expansion state and the drop targets are\n * keyed by.\n */\n const filtered = computed(() => {\n const term = toValue(options.filter)?.trim().toLowerCase()\n if (!term || !accessors.label) return null\n\n const keep = new Set<TreeKey>()\n const matched = new Set<TreeKey>()\n\n for (const item of entries.value.values()) {\n if (!accessors.label(item.node).toLowerCase().includes(term)) continue\n matched.add(item.key)\n let step: TreeEntry<T> | undefined = item\n while (step) {\n keep.add(step.key)\n step = step.parentKey === null ? undefined : entries.value.get(step.parentKey)\n }\n }\n\n return { keep, matched }\n })\n\n /* ------------------------------------------------------------- expansion */\n\n const openKeys = computed(() => new Set(expanded.value))\n\n const isExpandable = (node: T, children: T[]) => {\n if (children.length) return true\n if (!toValue(options.lazy)) return false\n return !accessors.leaf?.(node)\n }\n\n const isExpanded = (key: TreeKey) => openKeys.value.has(key)\n\n /** Visible rows, top to bottom — what a list renders, filter and all. */\n const rows = computed<TreeRow<T>[]>(() => {\n const out: TreeRow<T>[] = []\n const match = filtered.value\n\n const walk = (list: T[], path: number[]) => {\n list.forEach((node, index) => {\n const here = [...path, index]\n const key = accessors.key(node, here)\n if (match && !match.keep.has(key)) return\n\n const item = entries.value.get(key)\n if (!item) return\n\n const children = item.children\n const expandable = isExpandable(node, children)\n // A filter opens every branch it kept: hiding a match behind a closed\n // parent is the one thing a search must never do.\n const open = match ? true : openKeys.value.has(key)\n\n out.push({\n ...item,\n expandable,\n expanded: expandable && open,\n loading: loading.value.has(key),\n disabled: accessors.disabled?.(node) ?? false,\n matched: match ? match.matched.has(key) : false,\n })\n\n if (open && children.length) walk(children, here)\n })\n }\n\n walk(toValue(nodes), [])\n return out\n })\n\n function setExpanded(key: TreeKey, open: boolean) {\n const has = openKeys.value.has(key)\n if (has === open) return\n\n if (!open) {\n expanded.value = expanded.value.filter((k) => k !== key)\n return\n }\n\n if (toValue(options.accordion)) {\n const item = entry(key)\n const siblings = new Set((item?.siblings ?? []).map((node, index) => keyOf(node, [index])))\n expanded.value = [...expanded.value.filter((k) => !siblings.has(k)), key]\n return\n }\n\n expanded.value = [...expanded.value, key]\n }\n\n /**\n * Opening a lazy branch for the first time is a fetch. The branch opens once the\n * children are in, so that a spinner is never followed by an empty box that then\n * fills — and a failed load leaves the branch closed and unmarked, free to retry.\n */\n async function expand(key: TreeKey) {\n const item = entry(key)\n if (!item) return\n\n if (needsChildren(item)) {\n // Asked for by hand, so a branch the refill below gave up on is worth another try.\n refused.delete(identity(item.node))\n await fetchChildren(item)\n }\n\n setExpanded(key, true)\n }\n\n const needsChildren = (item: TreeEntry<T>) =>\n Boolean(toValue(options.lazy)) &&\n Boolean(options.load) &&\n !item.children.length &&\n !loaded.has(identity(item.node))\n\n async function fetchChildren(item: TreeEntry<T>) {\n loading.value = new Set(loading.value).add(item.key)\n try {\n const children = (await options.load?.(item.node)) ?? []\n accessors.setChildren(item.node, children)\n loaded.add(identity(item.node))\n fetched.value += 1\n } finally {\n const next = new Set(loading.value)\n next.delete(item.key)\n loading.value = next\n }\n }\n\n /**\n * An open branch with nothing under it fetches, once per node.\n *\n * That is the state a lazy tree is left in when the level it stands in is fetched again —\n * after a delete, a move, a filter: the open branches are keys in `expanded`, so they are\n * still open, while the nodes under those keys are new objects whose children never\n * arrived. Nobody would ask for them, since what the reader sees is a branch that is\n * already open, so the tree asks for itself.\n */\n watch(\n rows,\n (list) => {\n for (const item of list) {\n if (!item.expanded || loading.value.has(item.key)) continue\n if (refused.has(identity(item.node)) || !needsChildren(item)) continue\n\n void fetchChildren(item).catch(() => refused.add(identity(item.node)))\n }\n },\n { immediate: true, flush: 'post' },\n )\n\n const collapse = (key: TreeKey) => setExpanded(key, false)\n\n const toggle = (key: TreeKey) => (isExpanded(key) ? collapse(key) : expand(key))\n\n function expandAll() {\n const keys: TreeKey[] = []\n for (const item of entries.value.values()) {\n if (item.children.length) keys.push(item.key)\n }\n expanded.value = keys\n }\n\n const collapseAll = () => {\n expanded.value = []\n }\n\n /**\n * Opens a named path, one level at a time, waiting for each level before asking for\n * the next. It is what `reveal` cannot do on a lazy tree: there the ancestors are not\n * in the tree yet, so the way to them has to be walked rather than looked up. Stops\n * at the first key the level above did not contain — a path into a branch somebody\n * has since moved or deleted opens as far as it still goes.\n */\n async function openPath(keys: TreeKey[]) {\n for (const key of keys) {\n if (!entry(key)) return false\n await expand(key)\n }\n return true\n }\n\n /** Opens every branch on the way to a node, so it can be scrolled to. */\n function reveal(key: TreeKey) {\n const path = ancestors(key).map((item) => item.key)\n if (!path.length) return\n const open = new Set(expanded.value)\n for (const step of path) open.add(step)\n expanded.value = [...open]\n }\n\n /* ------------------------------------------------------------- relations */\n\n function ancestors(key: TreeKey): TreeEntry<T>[] {\n const out: TreeEntry<T>[] = []\n let step = entry(key)\n while (step && step.parentKey !== null) {\n const parent = entry(step.parentKey)\n if (!parent) break\n out.unshift(parent)\n step = parent\n }\n return out\n }\n\n /** The node itself and everything above it — the breadcrumb of a tree. */\n const path = (key: TreeKey): TreeEntry<T>[] => {\n const item = entry(key)\n return item ? [...ancestors(key), item] : []\n }\n\n const isAncestorOf = (key: TreeKey, other: TreeKey) =>\n ancestors(other).some((item) => item.key === key)\n\n function descendants(key: TreeKey): TreeEntry<T>[] {\n const out: TreeEntry<T>[] = []\n const item = entry(key)\n if (!item) return out\n\n const walk = (list: T[]) => {\n for (const node of list) {\n const child = entry(keyOf(node))\n if (!child) continue\n out.push(child)\n walk(child.children)\n }\n }\n\n walk(item.children)\n return out\n }\n\n /* ----------------------------------------------------------------- moving */\n\n /**\n * Whether a drop is allowed at all. A node cannot land on itself or inside its own\n * subtree — the check every tree needs and the one every tree that skips it loses a\n * branch to.\n */\n function canDrop(dragKey: TreeKey, dropKey: TreeKey, zone: TreeDropZone) {\n if (dragKey === dropKey) return false\n\n const drag = entry(dragKey)\n const drop = entry(dropKey)\n if (!drag || !drop) return false\n if (isAncestorOf(dragKey, dropKey)) return false\n\n return options.allowDrop?.(drag.node, drop.node, zone) ?? true\n }\n\n /**\n * Performs the move and reports where the node ended up. The arrays are spliced in\n * place, so a caller holding the tree in a `ref` sees it rearranged without a copy.\n */\n function move(dragKey: TreeKey, dropKey: TreeKey, zone: TreeDropZone) {\n if (!canDrop(dragKey, dropKey, zone)) return null\n\n const drag = entry(dragKey)\n const drop = entry(dropKey)\n if (!drag || !drop) return null\n\n drag.siblings.splice(drag.index, 1)\n\n if (zone === 'inside') {\n let children = accessors.children(drop.node)\n if (!children) {\n children = []\n accessors.setChildren(drop.node, children)\n }\n children.push(drag.node)\n setExpanded(dropKey, true)\n return { node: drag.node, parent: drop.node, siblings: children, index: children.length - 1 }\n }\n\n // Read after the splice above: dropping below a node that sat under the dragged\n // one in the same array means its index has already moved up by one.\n const siblings = drop.siblings\n const at = siblings.indexOf(drop.node) + (zone === 'after' ? 1 : 0)\n siblings.splice(at, 0, drag.node)\n\n return { node: drag.node, parent: drop.parent, siblings, index: at }\n }\n\n return {\n rows,\n entries,\n entry,\n keyOf,\n filtered,\n isExpanded,\n expand,\n collapse,\n toggle,\n expandAll,\n collapseAll,\n reveal,\n openPath,\n ancestors,\n path,\n descendants,\n isAncestorOf,\n canDrop,\n move,\n loading,\n }\n}\n\nexport type UseTreeNodes<T> = ReturnType<typeof useTreeNodes<T>>\n","<script setup lang=\"ts\" generic=\"T extends TableRow = TableRow\">\nimport {\n computed,\n getCurrentInstance,\n nextTick,\n onBeforeUnmount,\n onMounted,\n ref,\n useSlots,\n watch,\n} from 'vue'\nimport WxCheckbox from '../Checkbox/Checkbox.vue'\nimport WxInput from '../Input/Input.vue'\nimport type { InputModelValue } from '../Input/types'\nimport WxIcon from '../Icon/Icon.vue'\nimport WxAction from '../Action/Action.vue'\nimport WxIndicator from '../Indicator/Indicator.vue'\nimport WxPagination from '../Pagination/Pagination.vue'\nimport WxPopover from '../Popover/Popover.vue'\nimport { useElementWidth } from '../../composables/useElementWidth'\nimport {\n useTreeNodes,\n type TreeAccessors,\n type TreeDropZone,\n type TreeKey,\n type TreeRow,\n} from '../../composables/useTreeNodes'\nimport type {\n RowKey,\n TableColumn,\n TableEmits,\n TableProps,\n TableRow,\n TableSort,\n TableState,\n TableSummaryRow,\n} from './types'\n\ndefineOptions({ name: 'WxTable' })\n\n/** The disclosure and checkbox columns are square and never resize. */\nconst UTILITY_WIDTH = 44\n\nconst props = withDefaults(defineProps<TableProps<T>>(), {\n data: null,\n rowKey: 'id',\n title: undefined,\n searchable: false,\n searchPlaceholder: 'Search',\n searchDebounce: 300,\n filtersCount: 0,\n filtersLabel: 'Filters',\n filtersWidth: 300,\n loading: false,\n loadingText: 'Loading',\n emptyText: 'Nothing to show',\n selectRowLabel: 'Select row',\n selectAllLabel: 'Select every row on this page',\n stripe: false,\n bordered: false,\n hover: true,\n clickable: undefined,\n size: 'md',\n selectable: false,\n selectableIf: undefined,\n expandable: false,\n expandableIf: undefined,\n summary: () => [],\n /* A phone is 360–430 CSS pixels wide, and a table has to be wider than its widest row. */\n cardsBelow: 480,\n flush: false,\n pagination: undefined,\n perPageOptions: () => [],\n persist: undefined,\n maxHeight: undefined,\n stickyHeader: true,\n rowClass: undefined,\n layout: 'auto',\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<TableEmits<T>>()\n\n/** Keys rather than rows: a selection outlives the page it was made on. */\nconst selected = defineModel<RowKey[]>('selected', { default: () => [] })\nconst expanded = defineModel<RowKey[]>('expanded', { default: () => [] })\nconst sort = defineModel<TableSort | null>('sort', { default: null })\nconst search = defineModel<string>('search', { default: '' })\nconst page = defineModel<number>('page', { default: 1 })\nconst perPage = defineModel<number>('perPage', { default: 15 })\n\n/** An array or a paginator; the table only ever needs the rows out of it. */\nconst source = computed<T[]>(() => {\n const value = props.data\n if (!value) return []\n return Array.isArray(value) ? value : (value.data ?? [])\n})\n\n/* ---------------------------------------------------------------------------\n * Tree mode\n *\n * The rows nest: the first column carries the indentation and the disclosure, every\n * other column is still a column. What is where, what is open and what a move does to\n * the arrays is `useTreeNodes` — the same machinery `WxTree` runs on, so the two cannot\n * drift apart in what a drop means or when a lazy branch arrives.\n * ------------------------------------------------------------------------- */\n\nconst isTree = computed(() => Boolean(props.tree))\n\nconst treeOptions = computed(() => ({\n childrenKey: 'children',\n hasChildrenKey: 'has_children',\n indent: 20,\n springDelay: 600,\n ...props.tree,\n}))\n\n/** The tree needs a key from the row alone; the table's own falls back to a position. */\nfunction treeKeyOf(row: T, path: number[]): TreeKey {\n const index = path.at(-1) ?? 0\n if (typeof props.rowKey === 'function') return props.rowKey(row, index)\n if (props.rowKey) {\n const value = read(row, props.rowKey)\n if (typeof value === 'string' || typeof value === 'number') return value\n }\n return path.join('.')\n}\n\nconst treeAccessors: TreeAccessors<T> = {\n key: treeKeyOf,\n children: (row) => row[treeOptions.value.childrenKey] as T[] | undefined,\n setChildren: (row, children) => {\n ;(row as Record<string, unknown>)[treeOptions.value.childrenKey] = children\n },\n /*\n * Absent is not the same as false: a backend that never said anything about children\n * gets a chevron, and finding nothing behind it costs one request. Saying `false` —\n * `withCount` returning zero — is taken at its word.\n */\n leaf: (row) => {\n const flag = row[treeOptions.value.hasChildrenKey]\n return flag === undefined ? false : !flag\n },\n}\n\nconst tree = useTreeNodes<T>({\n nodes: () => source.value,\n accessors: treeAccessors,\n expanded,\n lazy: () => Boolean(treeOptions.value.lazy),\n load: (row) => treeOptions.value.load?.(row) ?? [],\n allowDrop: (drag, drop, zone) => treeOptions.value.allowDrop?.(drag, drop, zone) ?? true,\n})\n\nconst treeRows = computed(() => (isTree.value ? tree.rows.value : []))\n\n/** The rows on screen: the branch as it is opened, or the page as it arrived. */\nconst rows = computed<T[]>(() =>\n isTree.value ? treeRows.value.map((item) => item.node) : source.value,\n)\n\n/** The two arrays run in step, so a row's place in the tree is its index. */\nconst treeAt = (index: number) => (isTree.value ? treeRows.value[index] : undefined)\n\nif (props.tree?.defaultExpandAll) tree.expandAll()\n\nasync function toggleBranch(item: TreeRow<T>) {\n await tree.toggle(item.key)\n emit('expand-change', [...expanded.value], rowsFor(expanded.value))\n}\n\n/* ------------------------------------------------------------- moving rows */\n\nconst dragKey = ref<TreeKey | null>(null)\nconst dropKey = ref<TreeKey | null>(null)\nconst dropZone = ref<TreeDropZone | null>(null)\n\n/** The branch a row is hovering over, and the timer that will open it. */\nlet springKey: TreeKey | null = null\nlet springTimer: ReturnType<typeof setTimeout> | undefined\n\nconst canDragRow = (item: TreeRow<T>) =>\n Boolean(treeOptions.value.draggable) && (treeOptions.value.allowDrag?.(item.node) ?? true)\n\nfunction onRowDragStart(item: TreeRow<T>, event: DragEvent) {\n if (!canDragRow(item)) {\n event.preventDefault()\n return\n }\n dragKey.value = item.key\n event.dataTransfer?.setData('text/plain', String(item.key))\n if (event.dataTransfer) event.dataTransfer.effectAllowed = 'move'\n}\n\n/**\n * Which third of the row the pointer is over decides the landing: the edges put the row\n * beside the one under the pointer, the middle puts it inside.\n */\nfunction zoneAt(event: DragEvent, element: HTMLElement): TreeDropZone {\n const box = element.getBoundingClientRect()\n const y = (event.clientY - box.top) / box.height\n if (y <= 0.3) return 'before'\n if (y >= 0.7) return 'after'\n return 'inside'\n}\n\nfunction cancelSpring() {\n if (springTimer) clearTimeout(springTimer)\n springTimer = undefined\n springKey = null\n}\n\n/**\n * Dropping into a branch nobody can see the inside of is a guess. Holding a row over a\n * closed one opens it — and fetches it, where the children are not in yet — so the\n * guess becomes a look, and a move across the tree is one drag rather than three.\n */\nfunction spring(item: TreeRow<T>, zone: TreeDropZone) {\n const delay = treeOptions.value.springDelay ?? 0\n if (!delay || zone !== 'inside' || !item.expandable || item.expanded) {\n cancelSpring()\n return\n }\n if (springKey === item.key) return\n\n cancelSpring()\n springKey = item.key\n springTimer = setTimeout(() => {\n void tree.expand(item.key)\n cancelSpring()\n }, delay)\n}\n\nfunction onRowDragOver(item: TreeRow<T>, event: DragEvent) {\n if (dragKey.value === null) return\n\n const zone = zoneAt(event, event.currentTarget as HTMLElement)\n if (!tree.canDrop(dragKey.value, item.key, zone)) {\n dropKey.value = null\n dropZone.value = null\n cancelSpring()\n return\n }\n\n // Taking the event is what tells the browser this is a valid drop target.\n event.preventDefault()\n if (event.dataTransfer) event.dataTransfer.dropEffect = 'move'\n dropKey.value = item.key\n dropZone.value = zone\n spring(item, zone)\n}\n\nasync function onRowDrop(item: TreeRow<T>) {\n const key = dragKey.value\n const zone = dropZone.value\n if (key === null || zone === null || dropKey.value !== item.key) return\n\n cancelSpring()\n dragKey.value = null\n dropKey.value = null\n dropZone.value = null\n\n /*\n * Into a branch whose children have not arrived, the position is not ours to guess:\n * fetch first, then append to what is really there.\n */\n if (zone === 'inside' && treeOptions.value.lazy && !item.expanded) await tree.expand(item.key)\n\n const target = tree.entry(item.key)\n const landed = tree.move(key, item.key, zone)\n if (!landed || !target) return\n\n emit('node-drop', {\n row: landed.node,\n target: target.node,\n zone,\n parent: landed.parent,\n index: landed.index,\n via: 'pointer',\n })\n}\n\nfunction onRowDragEnd() {\n cancelSpring()\n dragKey.value = null\n dropKey.value = null\n dropZone.value = null\n}\n\nonBeforeUnmount(cancelSpring)\n\n/** A paginated response is a promise that there are more pages to reach. */\nconst paginator = computed(() => (props.data && !Array.isArray(props.data) ? props.data : null))\n\n/*\n * A page of a tree would cut branches in half, and the rows here are not a page anyway:\n * a lazy tree asks for a level at a time.\n */\n/*\n * One page is not a thing to page through. The control still costs a line of the screen and\n * asks to be read, and on a phone that line is most of what is left.\n */\nconst showPagination = computed(() => {\n if (isTree.value) return false\n\n if (paginator.value) {\n return (props.pagination ?? true) && paginator.value.last_page > 1\n }\n\n return props.pagination ?? false\n})\n\n/*\n * The table's own width decides this, not the window's: the same table is a page, half of a\n * dialog and a phone, and only one of those is the window.\n */\nconst root = ref<HTMLElement | null>(null)\nconst width = useElementWidth(root)\n\nconst visibleColumns = computed(() =>\n props.columns.filter(\n (column) =>\n !column.hidden &&\n // Measured before the first layout, `width` is 0 and nothing is dropped — which is the\n // right way round: a column that flashes in is better than one that flashes out.\n !(column.hideBelow && width.value > 0 && width.value < column.hideBelow),\n ),\n)\n\n/** Columns that carry no data of their own: the chevron and the checkbox. */\nconst utilityCount = computed(() => (props.expandable ? 1 : 0) + (props.selectable ? 1 : 0))\n\nconst columnCount = computed(() => visibleColumns.value.length + utilityCount.value)\n\n/*\n * The slots are declared rather than inferred. Left to infer, the type is read off a\n * template that builds slot names out of the column keys, and the circle that makes —\n * the slots depend on the template, the template on the slots — is answered with\n * `any`, which takes the table's props down with it.\n */\ndefineSlots<{\n title?: () => unknown\n actions?: () => unknown\n /**\n * The fields of the filter, inside the panel a funnel in the header opens.\n *\n * Three dropdowns standing open in the header is three controls of chrome above the first\n * row, and on a phone that is half the screen before any data. Behind the funnel they cost\n * one button, and what they are set to is said by `applied` instead.\n */\n filters?: () => unknown\n /**\n * What the filters are set to, as chips the reader can take off — the strip between the\n * header and the rows.\n *\n * The table gives the place and the spacing; the chips are the caller's, because only the\n * caller knows what \"rubric: News\" is called and what taking it off means. Nothing is drawn\n * while the strip holds no elements.\n */\n applied?: () => unknown\n empty?: () => unknown\n footer?: () => unknown\n loading?: () => unknown\n expanded?: (props: { row: T; index: number }) => unknown\n /** Buttons along the top of a card, where a row has no room for a column of them. */\n 'card-actions'?: (props: { row: T; index: number }) => unknown\n [key: `header-${string}`]: ((props: { column: TableColumn<T> }) => unknown) | undefined\n [key: `cell-${string}`]:\n | ((props: { row: T; value: unknown; index: number; column: TableColumn<T> }) => unknown)\n | undefined\n [key: `summary-${string}`]:\n ((props: { row: TableSummaryRow; value: unknown }) => unknown) | undefined\n}>()\n\nconst slots = useSlots()\n\nconst hasHeader = computed<boolean>(() =>\n Boolean(\n props.title ||\n props.searchable ||\n slots.title ||\n slots.actions ||\n slots.filters ||\n slots.applied,\n ),\n)\n\n/*\n * Whether a row does anything when it is clicked, so the pointer can say so.\n *\n * Read off the vnode rather than taken as a prop: the caller already says it by listening, and\n * a second way to say the same thing is a second thing to get wrong.\n *\n * Except when the answer changes while the table is on screen. `instance.vnode` is not\n * reactive, so the inference runs once, at the first render, and a list that swaps its rows for\n * ones that lead nowhere — a bin, an archive — would keep the pointer and the highlight it no\n * longer earns. Such a list says so with the prop instead.\n */\nconst instance = getCurrentInstance()\nconst clickable = computed(() => props.clickable ?? Boolean(instance?.vnode.props?.onRowClick))\n\n/**\n * A row leads somewhere, or it does not lead anywhere at all.\n *\n * Only an explicit `false` stops it, and then it stops everything: a row that looked inert and\n * still opened something would be the same lie as one that looked clickable and did nothing\n * (§13). The inference above is about how a row looks — a table nobody happens to be listening\n * to has withdrawn no promise, and its click is emitted into the air as it always was.\n */\nfunction onRowClick(row: T, index: number, event: MouseEvent): void {\n if (props.clickable === false) return\n\n emit('row-click', row, index, event)\n}\n\nconst asCards = computed(\n () => props.cardsBelow > 0 && width.value > 0 && width.value < props.cardsBelow,\n)\n\n/**\n * What a card shows.\n *\n * Not `visibleColumns`: `hideBelow` is about columns that will not fit beside each other, and a\n * card stacks them — there is room. Only `hideOnCards` applies here.\n */\nconst cardColumns = computed(() =>\n props.columns.filter((column) => !column.hidden && !column.hideOnCards),\n)\n\nconst classes = computed(() => [\n 'wx-table',\n `wx-table--${props.size}`,\n {\n 'wx-table--cards': asCards.value,\n 'wx-table--flush': props.flush,\n 'wx-table--clickable': clickable.value,\n 'wx-table--stripe': props.stripe,\n 'wx-table--bordered': props.bordered,\n 'wx-table--hover': props.hover,\n 'wx-table--sticky': props.maxHeight !== undefined,\n 'is-head-shifted': headShift.value > 0,\n 'wx-table--has-header': hasHeader.value,\n 'has-more-left': moreLeft.value,\n 'has-more-right': moreRight.value,\n 'is-loading': props.loading,\n },\n])\n\n/* Set only while it is moved: the cells keep no transform of their own at rest. */\nconst headShiftStyle = computed(() =>\n headShift.value > 0 ? { '--wx-table-head-shift': `${headShift.value}px` } : undefined,\n)\n\nconst scrollStyle = computed(() =>\n props.maxHeight === undefined ? undefined : { maxHeight: length(props.maxHeight) },\n)\n\nfunction length(value: string | number): string {\n return typeof value === 'number' ? `${value}px` : value\n}\n\n/** Only a declared width can say where the column behind a pinned one begins. */\nfunction widthOf(column: TableColumn<T>): number {\n if (typeof column.width === 'number') return column.width\n if (typeof column.width === 'string') {\n const parsed = Number.parseFloat(column.width)\n return Number.isFinite(parsed) ? parsed : 0\n }\n return 0\n}\n\n/**\n * The column's own widths, for the `<col>` that carries them.\n *\n * `width` only. A `<col>` takes four properties and `min-width` is not one of them: declared\n * there it computes, shows up in devtools and does nothing at all — measured, a column with\n * `min-width: 130px` and no width came out 0 wide. The floor goes on the heading instead, which\n * is an ordinary cell and honours it.\n */\nfunction colStyle(column: TableColumn<T>) {\n return { width: column.width === undefined ? undefined : length(column.width) }\n}\n\n/** The floor, on the one element that respects it. */\nfunction minStyle(column: TableColumn<T>) {\n return column.minWidth === undefined ? undefined : { minWidth: length(column.minWidth) }\n}\n\n/* ------------------------------------------------------------- measurement --- */\n\nconst scroller = ref<HTMLElement | null>(null)\nconst headRow = ref<HTMLElement | null>(null)\n\n/**\n * The widths the browser actually handed the columns, in the order they sit in — the\n * utility columns first, then the declared ones.\n *\n * A declared width is what the caller *asked* for, and it is honoured only while\n * there is room. In `auto` layout a table that has to scroll squeezes every column\n * proportionally, so the declared numbers stop being true exactly when pinning\n * starts to matter — and a pinned column parked at a declared offset then leaves a\n * gap for the scrolling ones to show through.\n */\nconst laidOut = ref<number[]>([])\n\nfunction measureColumns() {\n const cells = headRow.value?.children\n if (!cells) return\n\n const next = [...cells].map((cell) => (cell as HTMLElement).getBoundingClientRect().width)\n const same =\n next.length === laidOut.value.length &&\n next.every((width, index) => Math.abs(width - laidOut.value[index]) < 0.5)\n\n if (!same) laidOut.value = next\n}\n\n/** How far the columns have slid, which is what the edge shadows are about. */\nconst moreLeft = ref(false)\nconst moreRight = ref(false)\n\nfunction readScroll() {\n const el = scroller.value\n if (!el) return\n moreLeft.value = el.scrollLeft > 1\n moreRight.value = el.scrollLeft + el.clientWidth < el.scrollWidth - 1\n}\n\nfunction remeasure() {\n measureColumns()\n readScroll()\n followPage()\n}\n\n/* ------------------------------------------------------------ header on the page --- */\n\n/**\n * How far the heading row is moved down to stay in sight while the page — not the table —\n * scrolls past the rows.\n *\n * `position: sticky` cannot do it here: the box that scrolls the columns sideways is a scroll\n * container on both axes (`overflow-x: auto` turns `overflow-y` into `auto` as well), so a sticky\n * heading sticks to that box, which never scrolls up and down, and leaves with the rows. Making\n * the box not scroll would take sideways scrolling and the pinned columns away. So the cells are\n * moved instead, by exactly as far as the top of whatever scrolls the page has passed the top of\n * the table, and no further than the last row.\n */\nconst headShift = ref(0)\nconst tableEl = ref<HTMLElement | null>(null)\nlet scrollBoundary: HTMLElement | null = null\n\n/** The nearest ancestor that scrolls up and down — a drawer, a pane; null is the window. */\nfunction findScrollBoundary(from: HTMLElement): HTMLElement | null {\n for (let el = from.parentElement; el && el !== document.body; el = el.parentElement) {\n const overflow = getComputedStyle(el).overflowY\n if (overflow === 'auto' || overflow === 'scroll' || overflow === 'overlay') return el\n }\n return null\n}\n\nfunction followPage() {\n const table = tableEl.value\n const box = scroller.value\n const head = headRow.value?.parentElement\n const offset = typeof props.stickyHeader === 'number' ? props.stickyHeader : 0\n\n // With a height of its own the table scrolls its rows under a heading that sticks by CSS.\n const off =\n props.stickyHeader === false ||\n props.maxHeight !== undefined ||\n !table ||\n !box ||\n !head ||\n box.scrollHeight > box.clientHeight + 1\n\n if (off) {\n headShift.value = 0\n return\n }\n\n const top = (scrollBoundary?.getBoundingClientRect().top ?? 0) + offset\n const rect = table.getBoundingClientRect()\n const foot = table.querySelector<HTMLElement>(':scope > tfoot')\n const room = rect.height - head.offsetHeight - (foot?.offsetHeight ?? 0)\n const shift = Math.min(Math.max(top - rect.top, 0), Math.max(room, 0))\n\n if (shift !== headShift.value) headShift.value = shift\n}\n\nlet observer: ResizeObserver | null = null\n\nonMounted(() => {\n if (root.value) scrollBoundary = findScrollBoundary(root.value)\n // Capture: a scroll does not bubble, and the one that matters is an ancestor's.\n window.addEventListener('scroll', followPage, { capture: true, passive: true })\n window.addEventListener('resize', followPage, { passive: true })\n remeasure()\n if (typeof ResizeObserver === 'undefined' || !scroller.value) return\n observer = new ResizeObserver(remeasure)\n observer.observe(scroller.value)\n})\n\nonBeforeUnmount(() => {\n window.removeEventListener('scroll', followPage, { capture: true })\n window.removeEventListener('resize', followPage)\n observer?.disconnect()\n observer = null\n})\n\n/* Rows and columns both change what the browser gives each column. */\nwatch([() => rows.value.length, () => visibleColumns.value.length], async () => {\n await nextTick()\n remeasure()\n})\n\n/** What the browser gave the column at this position, or what was asked for. */\nfunction laidOutWidth(index: number, asked: number) {\n const measured = laidOut.value[index]\n return measured === undefined || measured === 0 ? asked : measured\n}\n\n/**\n * Where every pinned column comes to rest, measured from its edge. The utility columns\n * are pinned too whenever anything else is: a checkbox that slides under a frozen name\n * column is worse than no freezing at all.\n */\nconst offsets = computed(() => {\n const map = new Map<string, { side: 'left' | 'right'; offset: number; edge: boolean }>()\n const utilities = utilityCount.value\n\n let left = 0\n for (let index = 0; index < utilities; index += 1) {\n left += laidOutWidth(index, UTILITY_WIDTH)\n }\n\n const lefts = visibleColumns.value\n .map((column, index) => ({ column, index }))\n .filter((entry) => entry.column.fixed === 'left')\n\n lefts.forEach((entry, order) => {\n map.set(entry.column.key, { side: 'left', offset: left, edge: order === lefts.length - 1 })\n left += laidOutWidth(utilities + entry.index, widthOf(entry.column))\n })\n\n const rights = visibleColumns.value\n .map((column, index) => ({ column, index }))\n .filter((entry) => entry.column.fixed === 'right')\n\n let right = 0\n for (let order = rights.length - 1; order >= 0; order -= 1) {\n const entry = rights[order]\n map.set(entry.column.key, { side: 'right', offset: right, edge: order === 0 })\n right += laidOutWidth(utilities + entry.index, widthOf(entry.column))\n }\n\n return map\n})\n\nconst hasLeftFixed = computed(() => visibleColumns.value.some((column) => column.fixed === 'left'))\n\nconst hasFixed = computed(() => offsets.value.size > 0)\n\n/**\n * The resting place goes out as a custom property rather than as `left` itself. An\n * inline `left` would outrank every stylesheet rule, and the pinning has to be able to\n * switch itself off in CSS when the table is too narrow to afford it.\n */\nfunction fixedStyle(column: TableColumn<T>) {\n const pin = offsets.value.get(column.key)\n if (!pin) return undefined\n return { [`--wx-pin-${pin.side}`]: `${pin.offset}px` }\n}\n\nfunction fixedClass(column: TableColumn<T>) {\n const pin = offsets.value.get(column.key)\n if (!pin) return undefined\n return [`is-fixed-${pin.side}`, { 'is-fixed-edge': pin.edge }]\n}\n\n/** The utility columns ride along at the left edge once anything is pinned. */\nfunction utilityStyle(slot: 'expand' | 'select') {\n if (!hasFixed.value) return undefined\n const before = slot === 'select' && props.expandable ? laidOutWidth(0, UTILITY_WIDTH) : 0\n return { '--wx-pin-left': `${before}px` }\n}\n\nconst utilityClass = computed(() =>\n hasFixed.value ? ['is-fixed-left', { 'is-fixed-edge': !hasLeftFixed.value }] : undefined,\n)\n\n/** A dotted key walks into the row, so an eager-loaded relation reads as `user.name`. */\nfunction read(row: T, path: string): unknown {\n if (!path.includes('.')) return (row as TableRow)[path]\n return path.split('.').reduce<unknown>((value, part) => {\n if (value === null || typeof value !== 'object') return undefined\n return (value as TableRow)[part]\n }, row)\n}\n\nfunction cellText(column: TableColumn<T>, row: T, index: number): string {\n const value = read(row, column.key)\n if (column.formatter) return column.formatter(value, row, index)\n return value === null || value === undefined ? '' : String(value)\n}\n\nfunction keyOf(row: T, index: number): RowKey {\n if (typeof props.rowKey === 'function') return props.rowKey(row, index)\n const value = read(row, props.rowKey)\n return typeof value === 'string' || typeof value === 'number' ? value : index\n}\n\nfunction canSelect(row: T): boolean {\n return props.selectableIf ? props.selectableIf(row) : true\n}\n\nfunction canExpand(row: T): boolean {\n return props.expandableIf ? props.expandableIf(row) : true\n}\n\nconst selectableRows = computed(() => rows.value.filter(canSelect))\n\nconst selectableKeys = computed(() =>\n selectableRows.value.map((row) => keyOf(row, rows.value.indexOf(row))),\n)\n\nconst selectedCount = computed(\n () => selectableKeys.value.filter((key) => selected.value.includes(key)).length,\n)\n\nconst allSelected = computed(\n () => selectableKeys.value.length > 0 && selectedCount.value === selectableKeys.value.length,\n)\n\nconst someSelected = computed(() => selectedCount.value > 0 && !allSelected.value)\n\nfunction rowsFor(keys: RowKey[]): T[] {\n return rows.value.filter((row, index) => keys.includes(keyOf(row, index)))\n}\n\nfunction announce(keys: RowKey[]) {\n selected.value = keys\n emit('selection-change', keys, rowsFor(keys))\n}\n\n/**\n * The header checkbox works on this page only. Keys picked on other pages stay put —\n * clearing someone's selection because they paged forward would be a surprise.\n */\nfunction toggleAll(checked: boolean) {\n const page = selectableKeys.value\n if (checked) announce([...selected.value, ...page.filter((key) => !selected.value.includes(key))])\n else announce(selected.value.filter((key) => !page.includes(key)))\n}\n\nfunction toggleRow(row: T, index: number, checked: boolean) {\n const key = keyOf(row, index)\n if (checked) {\n if (!selected.value.includes(key)) announce([...selected.value, key])\n } else {\n announce(selected.value.filter((item) => item !== key))\n }\n}\n\nfunction isSelected(row: T, index: number): boolean {\n return selected.value.includes(keyOf(row, index))\n}\n\nfunction isExpanded(row: T, index: number): boolean {\n return expanded.value.includes(keyOf(row, index))\n}\n\nfunction toggleExpand(row: T, index: number) {\n if (!canExpand(row)) return\n const key = keyOf(row, index)\n const keys = expanded.value.includes(key)\n ? expanded.value.filter((item) => item !== key)\n : [...expanded.value, key]\n\n expanded.value = keys\n emit('expand-change', keys, rowsFor(keys))\n}\n\n/**\n * Sorting is reported, never applied: the rows on screen are one page out of a query,\n * and reordering them here would only shuffle the page. Three states, because a column\n * has to be able to give the ordering back.\n */\n/*\n * A tree has an order of its own, and it is the one on screen. Sorting the rows would\n * either scatter the branches or quietly sort inside each of them — the first is wrong\n * and the second is a control that does almost nothing. So in tree mode the heading is\n * a heading.\n */\nconst sortableIn = (column: TableColumn<T>) => Boolean(column.sortable) && !isTree.value\n\nfunction onSort(column: TableColumn<T>) {\n if (!sortableIn(column)) return\n const current = sort.value\n let next: TableSort | null\n if (current?.key !== column.key) next = { key: column.key, order: 'asc' }\n else if (current.order === 'asc') next = { key: column.key, order: 'desc' }\n else next = null\n\n sort.value = next\n page.value = 1\n emit('sort-change', next)\n}\n\nfunction ariaSort(column: TableColumn<T>) {\n if (!sortableIn(column)) return undefined\n if (sort.value?.key !== column.key) return 'none'\n return sort.value.order === 'asc' ? 'ascending' : 'descending'\n}\n\nfunction sortState(column: TableColumn<T>) {\n return sort.value?.key === column.key ? sort.value.order : null\n}\n\nfunction alignClass(column: TableColumn<T>) {\n return column.align && column.align !== 'left' ? `wx-table__cell--${column.align}` : undefined\n}\n\nlet timer: ReturnType<typeof setTimeout> | undefined\n\n/**\n * The field answers at once; the backend hears about it when the typing settles. The\n * settled term is what the state is built from, so a burst of keystrokes is one change\n * rather than one per letter — and filtering changes what page one is, so the page goes\n * back to the first.\n */\nconst settledSearch = ref(search.value)\n\n/* `WxInput`'s model widened when it learned about languages; this field is never localized. */\nfunction onSearch(value: InputModelValue) {\n search.value = typeof value === 'object' || value === undefined ? '' : String(value)\n}\n\nfunction onSearchChanged(term: string) {\n clearTimeout(timer)\n const settle = () => {\n settledSearch.value = term\n page.value = 1\n emit('search', term)\n }\n if (!props.searchDebounce) settle()\n else timer = setTimeout(settle, props.searchDebounce)\n}\n\nonBeforeUnmount(() => clearTimeout(timer))\n\n/** Everything the backend needs, in one object, so there is one thing to watch. */\nconst state = computed<TableState>(() => ({\n page: page.value,\n perPage: perPage.value,\n sort: sort.value,\n search: settledSearch.value,\n}))\n\nconst STORAGE_PREFIX = 'wx-table:'\n\n/**\n * Reading happens after mount rather than during setup: this renders on a server too,\n * and markup built from one machine's localStorage would not match what the browser\n * then hydrates.\n */\nfunction restore() {\n if (!props.persist) return\n let saved: Partial<TableState> | null = null\n try {\n const raw = window.localStorage.getItem(STORAGE_PREFIX + props.persist)\n saved = raw ? (JSON.parse(raw) as Partial<TableState>) : null\n } catch {\n // Unavailable, full, or holding something we did not write. Defaults will do.\n return\n }\n if (!saved) return\n\n if (typeof saved.page === 'number' && saved.page > 0) page.value = saved.page\n if (typeof saved.perPage === 'number' && saved.perPage > 0) perPage.value = saved.perPage\n if (typeof saved.search === 'string') search.value = saved.search\n if (saved.sort === null) sort.value = null\n else if (saved.sort && typeof saved.sort.key === 'string') {\n sort.value = { key: saved.sort.key, order: saved.sort.order === 'desc' ? 'desc' : 'asc' }\n }\n}\n\nfunction save(value: TableState) {\n if (!props.persist) return\n try {\n window.localStorage.setItem(STORAGE_PREFIX + props.persist, JSON.stringify(value))\n } catch {\n // A private window or a full quota. Remembering is a convenience, not a feature.\n }\n}\n\nonMounted(() => {\n restore()\n settledSearch.value = search.value\n emit('state-change', state.value)\n\n // Both watchers start here, so the restore above counts as the first state rather\n // than as a change — one fetch on load, not two.\n watch(search, onSearchChanged)\n watch(state, (value) => {\n save(value)\n emit('state-change', value)\n })\n})\n\n/** Columns ahead of the first figure belong to the caption. */\nfunction summaryStart(row: TableSummaryRow): number {\n const cells = row.cells ?? {}\n const index = visibleColumns.value.findIndex((column) => column.key in cells)\n return index === -1 ? visibleColumns.value.length : index\n}\n\nfunction summarySpan(row: TableSummaryRow): number {\n return utilityCount.value + summaryStart(row)\n}\n\nfunction summaryColumns(row: TableSummaryRow): TableColumn<T>[] {\n return visibleColumns.value.slice(summaryStart(row))\n}\n\nfunction summaryValue(row: TableSummaryRow, column: TableColumn<T>): unknown {\n return row.cells?.[column.key]\n}\n\nfunction summaryText(row: TableSummaryRow, column: TableColumn<T>): string {\n const value = summaryValue(row, column)\n return value === null || value === undefined ? '' : String(value)\n}\n</script>\n\n<template>\n <div ref=\"root\" :class=\"classes\" :style=\"headShiftStyle\">\n <header v-if=\"hasHeader\" class=\"wx-table__header\">\n <!--\n Only when there is one. An empty box is still a flex item: it took the first line of the\n head to itself and left the row gap above the search — 12px of nothing over every table\n that has no title, and on a phone, where the tools take a line of their own, it was the\n whole of the space above the field.\n -->\n <div v-if=\"title || $slots.title\" class=\"wx-table__title\">\n <slot name=\"title\">{{ title }}</slot>\n </div>\n\n <!-- What the filters are set to, in the head rather than under it: the row already has\n the room, and a strip of its own costs a line above every filtered list. -->\n <div v-if=\"$slots.applied\" class=\"wx-table__applied\">\n <slot name=\"applied\" />\n </div>\n\n <div class=\"wx-table__tools\">\n <slot name=\"actions\" />\n\n <!--\n The funnel. The panel hangs off the indicator rather than off the button, because the\n trigger has to be one element and `WxAction` carries its tooltip beside itself — its\n root is a fragment (CLAUDE.md §4).\n -->\n <wx-popover\n v-if=\"$slots.filters\"\n :title=\"filtersLabel\"\n :width=\"filtersWidth\"\n side=\"bottom\"\n align=\"end\"\n >\n <template #trigger>\n <wx-indicator\n class=\"wx-table__filter\"\n :value=\"filtersCount\"\n :hidden=\"filtersCount === 0\"\n type=\"primary\"\n :label=\"filtersLabel\"\n >\n <wx-action icon=\"filter\" :size=\"size\" :title=\"filtersLabel\" />\n </wx-indicator>\n </template>\n\n <div class=\"wx-table__filter-fields\">\n <slot name=\"filters\" />\n </div>\n </wx-popover>\n\n <div v-if=\"searchable\" class=\"wx-table__search\">\n <wx-input\n type=\"search\"\n :model-value=\"search\"\n :placeholder=\"searchPlaceholder\"\n :size=\"size\"\n clearable\n :aria-label=\"searchPlaceholder\"\n @update:model-value=\"onSearch\"\n />\n </div>\n </div>\n </header>\n\n <!--\n Below `cardsBelow` the columns become a card each. The cells are the same cells — the\n same `cell-<key>` slots, the same formatters — so a screen written for the table needs\n nothing added to survive a phone.\n -->\n <div v-if=\"asCards\" class=\"wx-table__cards\">\n <div\n v-for=\"(row, index) in rows\"\n :key=\"keyOf(row, index)\"\n class=\"wx-table__card\"\n :class=\"[rowClass?.(row, index), { 'is-selected': selectable && isSelected(row, index) }]\"\n @click=\"onRowClick(row, index, $event)\"\n >\n <!-- The checkbox where a list puts one, the actions where a thumb reaches them. -->\n <div v-if=\"selectable || $slots['card-actions']\" class=\"wx-table__card-top\" @click.stop>\n <wx-checkbox\n v-if=\"selectable\"\n :model-value=\"isSelected(row, index)\"\n :disabled=\"!canSelect(row)\"\n :aria-label=\"selectRowLabel\"\n @update:model-value=\"(checked: boolean) => toggleRow(row, index, checked)\"\n />\n <div class=\"wx-table__card-tools\">\n <slot name=\"card-actions\" :row=\"row\" :index=\"index\" />\n </div>\n </div>\n\n <div v-for=\"column in cardColumns\" :key=\"column.key\" class=\"wx-table__field\">\n <span v-if=\"column.label\" class=\"wx-table__field-label\">{{ column.label }}</span>\n <div class=\"wx-table__field-value\" :class=\"column.cellClass\">\n <slot\n :name=\"`cell-${column.key}`\"\n :row=\"row\"\n :value=\"read(row, column.key)\"\n :index=\"index\"\n :column=\"column\"\n >\n {{ cellText(column, row, index) }}\n </slot>\n </div>\n </div>\n </div>\n\n <div v-if=\"rows.length === 0\" class=\"wx-table__cards-empty\">\n <slot name=\"empty\">{{ emptyText }}</slot>\n </div>\n\n <div v-if=\"showPagination\" class=\"wx-table__cards-footer\">\n <slot name=\"footer\">\n <wx-pagination\n v-model:page=\"page\"\n v-model:per-page=\"perPage\"\n :paginator=\"paginator\"\n :per-page-options=\"perPageOptions\"\n :size=\"size\"\n :disabled=\"loading\"\n />\n </slot>\n </div>\n </div>\n\n <div v-else ref=\"scroller\" class=\"wx-table__scroll\" :style=\"scrollStyle\" @scroll=\"readScroll\">\n <table\n ref=\"tableEl\"\n class=\"wx-table__table\"\n :class=\"{ 'wx-table__table--fixed': layout === 'fixed' }\"\n :aria-label=\"ariaLabel\"\n :aria-busy=\"loading || undefined\"\n >\n <colgroup>\n <col v-if=\"expandable\" :style=\"{ width: `${UTILITY_WIDTH}px` }\" />\n <col v-if=\"selectable\" :style=\"{ width: `${UTILITY_WIDTH}px` }\" />\n <col v-for=\"column in visibleColumns\" :key=\"column.key\" :style=\"colStyle(column)\" />\n </colgroup>\n\n <thead class=\"wx-table__head\">\n <!-- The row the pin offsets are measured off: one cell per column, always. -->\n <tr ref=\"headRow\">\n <th\n v-if=\"expandable\"\n scope=\"col\"\n class=\"wx-table__cell wx-table__cell--utility\"\n :class=\"utilityClass\"\n :style=\"utilityStyle('expand')\"\n >\n <span class=\"wx-table__sr-only\">Expand</span>\n </th>\n\n <th\n v-if=\"selectable\"\n scope=\"col\"\n class=\"wx-table__cell wx-table__cell--utility\"\n :class=\"utilityClass\"\n :style=\"utilityStyle('select')\"\n >\n <wx-checkbox\n :model-value=\"allSelected\"\n :indeterminate=\"someSelected\"\n :disabled=\"!selectableKeys.length\"\n :aria-label=\"selectAllLabel\"\n @update:model-value=\"toggleAll\"\n />\n </th>\n\n <th\n v-for=\"column in visibleColumns\"\n :key=\"column.key\"\n scope=\"col\"\n class=\"wx-table__cell\"\n :class=\"[alignClass(column), fixedClass(column), column.headerClass]\"\n :style=\"[fixedStyle(column), minStyle(column)]\"\n :aria-sort=\"ariaSort(column)\"\n >\n <button\n v-if=\"sortableIn(column)\"\n class=\"wx-table__sort\"\n type=\"button\"\n @click=\"onSort(column)\"\n >\n <slot :name=\"`header-${column.key}`\" :column=\"column\">\n {{ column.label ?? column.key }}\n </slot>\n <svg\n class=\"wx-table__sort-icon\"\n :class=\"sortState(column) ? `is-${sortState(column)}` : undefined\"\n viewBox=\"0 0 8 12\"\n aria-hidden=\"true\"\n >\n <path class=\"wx-table__sort-up\" d=\"M4 1 7 5 1 5Z\" />\n <path class=\"wx-table__sort-down\" d=\"M4 11 1 7 7 7Z\" />\n </svg>\n </button>\n\n <slot v-else :name=\"`header-${column.key}`\" :column=\"column\">\n {{ column.label ?? column.key }}\n </slot>\n </th>\n </tr>\n </thead>\n\n <tbody class=\"wx-table__body\">\n <template v-for=\"(row, index) in rows\" :key=\"keyOf(row, index)\">\n <tr\n class=\"wx-table__row\"\n :class=\"[\n rowClass?.(row, index),\n {\n 'is-striped': index % 2 === 1,\n 'is-selected': selectable && isSelected(row, index),\n 'is-expanded': expandable && isExpanded(row, index),\n 'is-dragging': dragKey !== null && dragKey === treeAt(index)?.key,\n [`is-drop-${dropZone}`]: dropZone && dropKey === treeAt(index)?.key,\n },\n ]\"\n :draggable=\"treeAt(index) ? canDragRow(treeAt(index)!) : undefined\"\n @click=\"onRowClick(row, index, $event)\"\n @dragstart=\"treeAt(index) && onRowDragStart(treeAt(index)!, $event)\"\n @dragover=\"treeAt(index) && onRowDragOver(treeAt(index)!, $event)\"\n @drop.prevent=\"treeAt(index) && onRowDrop(treeAt(index)!)\"\n @dragend=\"onRowDragEnd\"\n >\n <td\n v-if=\"expandable\"\n class=\"wx-table__cell wx-table__cell--utility\"\n :class=\"utilityClass\"\n :style=\"utilityStyle('expand')\"\n @click.stop\n >\n <button\n v-if=\"canExpand(row)\"\n class=\"wx-table__expander\"\n type=\"button\"\n :aria-expanded=\"isExpanded(row, index)\"\n :aria-label=\"isExpanded(row, index) ? 'Collapse row' : 'Expand row'\"\n @click=\"toggleExpand(row, index)\"\n >\n <svg viewBox=\"0 0 12 12\" aria-hidden=\"true\">\n <path d=\"M4.5 2 8.5 6l-4 4\" />\n </svg>\n </button>\n </td>\n\n <td\n v-if=\"selectable\"\n class=\"wx-table__cell wx-table__cell--utility\"\n :class=\"utilityClass\"\n :style=\"utilityStyle('select')\"\n @click.stop\n >\n <wx-checkbox\n :model-value=\"isSelected(row, index)\"\n :disabled=\"!canSelect(row)\"\n :aria-label=\"selectRowLabel\"\n @update:model-value=\"(checked: boolean) => toggleRow(row, index, checked)\"\n />\n </td>\n\n <td\n v-for=\"column in visibleColumns\"\n :key=\"column.key\"\n class=\"wx-table__cell\"\n :class=\"[alignClass(column), fixedClass(column), column.cellClass]\"\n :style=\"fixedStyle(column)\"\n >\n <!--\n The tree lives in the first column, ahead of whatever that column\n draws: indentation for the level, and a disclosure for a branch.\n -->\n <span\n v-if=\"treeAt(index) && column.key === visibleColumns[0]?.key\"\n class=\"wx-table__tree\"\n :style=\"{\n paddingInlineStart: `${treeAt(index)!.depth * (treeOptions.indent ?? 20)}px`,\n }\"\n >\n <button\n v-if=\"treeAt(index)!.expandable\"\n class=\"wx-table__tree-toggle\"\n type=\"button\"\n :aria-expanded=\"treeAt(index)!.expanded\"\n :aria-label=\"treeAt(index)!.expanded ? 'Collapse branch' : 'Expand branch'\"\n @click.stop=\"toggleBranch(treeAt(index)!)\"\n >\n <wx-icon\n :name=\"treeAt(index)!.loading ? 'loader' : 'chevron-right'\"\n :spin=\"treeAt(index)!.loading\"\n />\n </button>\n <span v-else class=\"wx-table__tree-toggle is-leaf\" />\n </span>\n\n <slot\n :name=\"`cell-${column.key}`\"\n :row=\"row\"\n :value=\"read(row, column.key)\"\n :index=\"index\"\n :column=\"column\"\n >\n {{ cellText(column, row, index) }}\n </slot>\n </td>\n </tr>\n\n <tr v-if=\"expandable && isExpanded(row, index)\" class=\"wx-table__row--expansion\">\n <td class=\"wx-table__cell wx-table__expansion\" :colspan=\"columnCount\">\n <div class=\"wx-table__expansion-body\">\n <slot name=\"expanded\" :row=\"row\" :index=\"index\" />\n </div>\n </td>\n </tr>\n </template>\n\n <tr v-if=\"!rows.length && !loading\" class=\"wx-table__row wx-table__row--empty\">\n <td class=\"wx-table__cell wx-table__empty\" :colspan=\"columnCount\">\n <slot name=\"empty\">{{ emptyText }}</slot>\n </td>\n </tr>\n </tbody>\n\n <tfoot v-if=\"summary.length || $slots.footer || showPagination\" class=\"wx-table__foot\">\n <tr\n v-for=\"(line, lineIndex) in summary\"\n :key=\"lineIndex\"\n class=\"wx-table__summary\"\n :class=\"[line.class, { 'is-strong': line.strong }]\"\n >\n <td\n v-if=\"summarySpan(line) > 0\"\n class=\"wx-table__cell wx-table__summary-label\"\n :colspan=\"summarySpan(line)\"\n >\n {{ line.label }}\n </td>\n\n <td\n v-for=\"column in summaryColumns(line)\"\n :key=\"column.key\"\n class=\"wx-table__cell\"\n :class=\"alignClass(column)\"\n >\n <slot :name=\"`summary-${column.key}`\" :row=\"line\" :value=\"summaryValue(line, column)\">\n {{ summaryText(line, column) }}\n </slot>\n </td>\n </tr>\n\n <tr v-if=\"$slots.footer || showPagination\" class=\"wx-table__footer-row\">\n <td class=\"wx-table__cell\" :colspan=\"columnCount\">\n <slot name=\"footer\">\n <wx-pagination\n v-model:page=\"page\"\n v-model:per-page=\"perPage\"\n :paginator=\"paginator\"\n :per-page-options=\"perPageOptions\"\n :size=\"size\"\n :disabled=\"loading\"\n />\n </slot>\n </td>\n </tr>\n </tfoot>\n </table>\n </div>\n\n <div v-if=\"loading\" class=\"wx-table__loading\">\n <slot name=\"loading\">\n <span class=\"wx-table__spinner\" aria-hidden=\"true\" />\n <span class=\"wx-table__loading-text\">{{ loadingText }}</span>\n </slot>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-table {\n position: relative;\n z-index: 0;\n box-sizing: border-box;\n /*\n * A column, so that a table given less height than it needs scrolls its own rows instead of\n * spilling out of whatever holds it. Left as a block it grew to its full height and the box\n * around it clipped the overflow — a list of six cards inside a pane 610px tall drew 1793px\n * of them and could not be scrolled by anything, because nothing in the chain had a scroller.\n * Unconstrained — a table on an ordinary page — the height stays `auto` and this changes\n * nothing: the column is as tall as its rows and the page scrolls, as before.\n */\n display: flex;\n flex-direction: column;\n min-height: 0;\n /*\n * A flex or grid item will not shrink below its content unless told to, and the\n * content here is a table that can be twice the width of the page. Without this the\n * inner scroller never scrolls and the whole document does instead.\n */\n min-width: 0;\n /*\n * Pinning asks about the table's own width, so the table is the thing being measured.\n * Containment means the width can no longer come from the contents, so it is stated:\n * inside a flex row the element would otherwise measure zero.\n */\n width: 100%;\n max-width: 100%;\n container-type: inline-size;\n background: var(--wx-bg-surface);\n border-radius: var(--wx-radius-md);\n color: var(--wx-text-default);\n\n --wx-table-padding-y: var(--wx-space-10);\n --wx-table-padding-x: var(--wx-space-16);\n /* What a pinned cell paints itself with; every row state restates it. */\n --wx-table-row-bg: var(--wx-bg-surface);\n}\n\n.wx-table--sm {\n --wx-table-padding-y: var(--wx-space-6);\n --wx-table-padding-x: var(--wx-space-12);\n}\n\n.wx-table--lg {\n --wx-table-padding-y: var(--wx-space-14);\n}\n\n.wx-table__header {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-12);\n padding: var(--wx-space-12) var(--wx-table-padding-x);\n}\n\n.wx-table__title {\n min-width: 0;\n color: var(--wx-text-strong);\n font-size: var(--wx-font-size-lg);\n font-weight: var(--wx-font-weight-semibold);\n line-height: var(--wx-font-line-height-tight);\n}\n\n/* Wraps: a filter and a search field are each wider than a phone can spare, and an input\n will not shrink below its own intrinsic width — it overflows sideways instead. */\n.wx-table__tools {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: flex-end;\n gap: var(--wx-space-8);\n margin-left: auto;\n}\n\n.wx-table__search {\n width: var(--wx-table-search-width, 240px);\n max-width: 100%;\n}\n\n/* The funnel keeps its size whatever the row it is in does. */\n.wx-table__filter {\n flex: none;\n}\n\n/*\n * As tall as the search field beside it, not as tall as an icon button: the two stand in one\n * row and are read as one control, and 36 next to 42 reads as a mistake.\n *\n * Declared on the button rather than on the wrapper. `.wx-action--md` declares this variable on\n * its own element, and a value inherited from an ancestor never beats one declared on the\n * element that reads it (CLAUDE.md §4) — and through `:deep()` because the button is another\n * component's, so a scoped rule would be looking for this component's attribute on it.\n */\n.wx-table__filter :deep(.wx-action) {\n --wx-action-size: var(--wx-size-control-md);\n}\n\n.wx-table--sm .wx-table__filter :deep(.wx-action) {\n --wx-action-size: var(--wx-size-control-sm);\n}\n\n.wx-table--lg .wx-table__filter :deep(.wx-action) {\n --wx-action-size: var(--wx-size-control-lg);\n}\n\n/* The panel is a column of fields, spaced the way a form is. */\n.wx-table__filter-fields {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n}\n\n/*\n * The chips take the room the head has spare — between the title and the tools — and wrap into\n * it rather than pushing the search field off the row.\n */\n.wx-table__applied {\n display: flex;\n flex: 1 1 auto;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-8);\n min-width: 0;\n}\n\n/*\n * Nothing in it, nothing drawn. `:empty` cannot say this: a `v-if` that rendered nothing\n * leaves a comment node behind, and a comment is a child — `:has(*)` asks about elements,\n * which is the question being asked.\n */\n.wx-table__applied:not(:has(*)) {\n display: none;\n}\n\n/* Once the rows are cards there is no width to share: the filters become a column of their own. */\n.wx-table--cards .wx-table__tools {\n width: 100%;\n}\n\n/* Whatever the caller put in `#actions` takes a line of its own: on a phone there is no width\n to share, and a button too narrow to hold its word is not a button. */\n.wx-table--cards .wx-table__tools > :not(.wx-table__search):not(.wx-table__filter) {\n flex: 1 1 100%;\n}\n\n/*\n * The funnel and the search are the exception, and they keep one line between them: a button\n * with a field beside it is read as one control, and split over two lines it is two — on a\n * phone that is a second of the five lines the head is allowed.\n */\n.wx-table--cards .wx-table__search {\n flex: 1 1 auto;\n width: auto;\n min-width: 0;\n}\n\n/*\n * Flush means the box around it does the spacing — for the head as much as for the rows.\n *\n * It used to keep the cells' own step as well, so that a search box with a border would not\n * touch the edge of whatever holds it. Inside a card it never does: the card's own padding is\n * already there, and the second inset only stood the head 16px further in than the row of\n * headings under it. Measured: the search ended at 1278 where the table ended at 1294.\n *\n * What is left is the space under it, and that is the panel's step rather than the table's —\n * the head and the rows are two things in a card, and everything else in one is spaced by it.\n */\n.wx-table--flush:not(.wx-table--cards) .wx-table__header {\n padding: 0 0 var(--wx-gap, var(--wx-space-16));\n}\n\n/* What scrolls when the table is squeezed; the head and the pagination keep their height. */\n.wx-table__scroll {\n overflow: auto;\n border-radius: inherit;\n min-height: 0;\n}\n\n.wx-table__header,\n.wx-table__cards-footer {\n flex: none;\n}\n\n/*\n * A rounded corner belongs to the outside of the card, and once a title or a search\n * field sits above the rows, the top of the rows is no longer the outside. Left\n * rounded, the heading strip curves away from two square corners and leaves a white\n * wedge in each — small on a wide table, and the first thing you see on a narrow one.\n */\n.wx-table--has-header .wx-table__scroll {\n border-start-start-radius: 0;\n border-start-end-radius: 0;\n}\n\n/*\n * Explicit resets rather than an assumption that nothing else styles a table. VitePress\n * turns every table into a scrolling block; Bootstrap and Tailwind's preflight have\n * opinions of their own. Left alone, a host stylesheet takes the layout away from the\n * table, the stickiness away from the header and the stripes away from the rows —\n * quietly, and only once the library is embedded somewhere real.\n */\n.wx-table__table {\n display: table;\n width: 100%;\n margin: 0;\n overflow: visible;\n border: 0;\n border-collapse: collapse;\n border-spacing: 0;\n font-size: var(--wx-font-size-md);\n}\n\n.wx-table__table thead {\n display: table-header-group;\n}\n\n.wx-table__table tbody {\n display: table-row-group;\n}\n\n.wx-table__table tfoot {\n display: table-footer-group;\n}\n\n.wx-table__table tr {\n display: table-row;\n background: none;\n border: 0;\n}\n\n/*\n * A row's colour reaches the eye by two routes: the row paints it behind cells that are\n * transparent, and a pinned cell paints it itself. They therefore have to change at the\n * same speed, and that speed has to be stated — VitePress fades a `tr` over half a\n * second, which left the pinned columns snapping to the hover colour while the rest of\n * the row was still on its way there.\n *\n * The shadow goes with it: it is the same colour, covering the seam beside the cell.\n */\n.wx-table__row,\n.wx-table__cell.is-fixed-left,\n.wx-table__cell.is-fixed-right {\n transition:\n background-color var(--wx-duration-fast) var(--wx-easing-standard),\n box-shadow var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-table__row,\n .wx-table__cell.is-fixed-left,\n .wx-table__cell.is-fixed-right {\n transition: none;\n }\n}\n\n.wx-table__table th,\n.wx-table__table td {\n display: table-cell;\n border: 0;\n}\n\n.wx-table__table--fixed {\n table-layout: fixed;\n}\n\n.wx-table--sm .wx-table__table {\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-table--lg .wx-table__table {\n font-size: var(--wx-font-size-lg);\n}\n\n.wx-table__cell {\n box-sizing: border-box;\n padding: var(--wx-table-padding-y) var(--wx-table-padding-x);\n text-align: left;\n vertical-align: middle;\n /*\n * A cell keeps what it holds inside its own column.\n *\n * `table-layout: fixed` gives a column the width it was declared and nothing else, so a value\n * wider than that — a date in a language with long month names, a badge with a longer word —\n * used to be painted straight across the column beside it. Measured on the panel: a date cell\n * 130px wide with 152px of text, its tail sitting under the status badge. Cut at the edge is\n * not pretty, but it is the column saying it is too narrow rather than the next one appearing\n * to hold rubbish.\n */\n overflow: hidden;\n}\n\n.wx-table__cell--center {\n text-align: center;\n}\n\n.wx-table__cell--right {\n text-align: right;\n}\n\n/*\n * The control is the whole content of a utility cell, and an inline-level box would sit\n * on a text baseline — three pixels above the middle of the row, which is exactly the\n * kind of misalignment that reads as sloppiness rather than as a bug.\n */\n.wx-table__cell--utility {\n width: 44px;\n padding-right: 0;\n line-height: 0;\n}\n\n.wx-table__cell--utility :deep(.wx-checkbox) {\n display: flex;\n}\n\n.wx-table__sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n\n.wx-table__head .wx-table__cell {\n --wx-table-row-bg: var(--wx-bg-subtle);\n\n background: var(--wx-bg-subtle);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n font-weight: var(--wx-font-weight-semibold);\n white-space: nowrap;\n}\n\n/* Sticky needs a painted background of its own, or the rows show through. */\n.wx-table--sticky .wx-table__head .wx-table__cell {\n position: sticky;\n top: 0;\n z-index: 2;\n}\n\n/*\n * The heading row following the page (`followPage`): moved, not stuck, and painted over the rows\n * it now lies on — later in the document, they would otherwise cover it. A pinned heading keeps\n * its `sticky` for the sideways scroll and the higher layer it already has.\n */\n.wx-table.is-head-shifted .wx-table__head .wx-table__cell {\n transform: translateY(var(--wx-table-head-shift, 0px));\n /* Lying on a row now, not above the first one: lifted, so it reads as over the rows. A line\n would not do — in the dark theme the border and the heading share one grey. */\n box-shadow: var(--wx-shadow-sm);\n}\n\n.wx-table.is-head-shifted .wx-table__head .wx-table__cell:not(.is-fixed-left, .is-fixed-right) {\n position: relative;\n z-index: 2;\n}\n\n.wx-table--sticky .wx-table__foot .wx-table__cell {\n position: sticky;\n bottom: 0;\n z-index: 2;\n background: var(--wx-bg-surface);\n}\n\n/* A pinned column paints over the scrolling ones, and the header over both. The colour\n it paints with is whatever the row it belongs to is wearing. */\n.wx-table__cell.is-fixed-left,\n.wx-table__cell.is-fixed-right {\n position: sticky;\n z-index: 1;\n background: var(--wx-table-row-bg);\n}\n\n.wx-table__cell.is-fixed-left {\n left: var(--wx-pin-left, 0px);\n}\n\n.wx-table__cell.is-fixed-right {\n right: var(--wx-pin-right, 0px);\n}\n\n.wx-table__head .wx-table__cell.is-fixed-left,\n.wx-table__head .wx-table__cell.is-fixed-right,\n.wx-table--sticky .wx-table__foot .wx-table__cell.is-fixed-left,\n.wx-table--sticky .wx-table__foot .wx-table__cell.is-fixed-right {\n z-index: 3;\n}\n\n/*\n * A scrollport rarely begins on a whole pixel — at any display scale but 100% it begins\n * on a fraction of one — so the pinned cell is rasterised with its edge pixel only\n * partly covered, and a hairline of the scrolling column shows through it.\n *\n * The cover is a strip of its own rather than a box shadow: Firefox declines to paint a\n * shadow on a cell in a collapsed-border table, which is where the sliver was still\n * turning up. Two pixels wide and straddling the edge, so whichever pixel the boundary\n * falls in is covered outright instead of blended.\n */\n.wx-table__cell.is-fixed-left::before,\n.wx-table__cell.is-fixed-right::before {\n content: '';\n position: absolute;\n top: 0;\n bottom: 0;\n width: 2px;\n background: var(--wx-table-row-bg);\n pointer-events: none;\n}\n\n.wx-table__cell.is-fixed-left::before {\n left: -1px;\n}\n\n/*\n * Flush with the edge rather than a pixel past it. The rightmost pinned cell ends\n * where the table does, so a strip hanging over that edge is a pixel of scrollable\n * width — enough for a horizontal scrollbar to appear under a table that fits.\n */\n.wx-table__cell.is-fixed-right::before {\n right: 0;\n}\n\n/*\n * The edge of the frozen block, so it reads as floating over what slides beneath —\n * and only while something is sliding beneath it. A shadow on a table with nothing\n * hidden either side is a line drawn across the middle of it for no reason.\n */\n.wx-table.has-more-left .wx-table__cell.is-fixed-left.is-fixed-edge {\n box-shadow: 6px 0 6px -6px rgb(0 0 0 / 0.18);\n}\n\n.wx-table.has-more-right .wx-table__cell.is-fixed-right.is-fixed-edge {\n box-shadow: -6px 0 6px -6px rgb(0 0 0 / 0.18);\n}\n\n/*\n * Pinning is a luxury of width. On a phone the frozen columns take most of the screen\n * and the ones the reader came for have nowhere to scroll into view, so the table gives\n * up freezing and simply scrolls as a whole.\n *\n * The question is asked of the table rather than of the window: the same thing happens\n * to a table in a narrow panel on a wide desktop. The offsets are custom properties for\n * exactly this reason — an inline `left` could not be talked out of it.\n */\n@container (max-width: 600px) {\n .wx-table__cell.is-fixed-left,\n .wx-table__cell.is-fixed-right,\n .wx-table__cell.is-fixed-left.is-fixed-edge,\n .wx-table__cell.is-fixed-right.is-fixed-edge {\n left: auto;\n right: auto;\n z-index: auto;\n box-shadow: none;\n }\n\n .wx-table__cell.is-fixed-left::before,\n .wx-table__cell.is-fixed-right::before {\n display: none;\n }\n}\n\n.wx-table__body .wx-table__cell {\n border-top: 1px solid var(--wx-border-muted);\n}\n\n.wx-table--bordered .wx-table__cell + .wx-table__cell {\n border-left: 1px solid var(--wx-border-muted);\n}\n\n/* Striped by row index, not by position: an expansion row is a sibling too, and\n counting it would flip the pattern from wherever a row was opened. Each state names\n its colour once; the pinned cells read it back out of the variable. */\n.wx-table--stripe .wx-table__row.is-striped {\n --wx-table-row-bg: var(--wx-bg-subtle);\n\n background: var(--wx-bg-subtle);\n}\n\n/*\n * A tone softer than `--wx-bg-fill`, and that is the whole reason it is not that token: the\n * `···` at the end of the row is filled with `--wx-bg-fill` at rest, so a row that took the\n * same colour swallowed the one control it carries — the button was there, and hovering the\n * row was what made it disappear.\n */\n.wx-table--hover .wx-table__row:hover {\n --wx-table-row-bg: var(--wx-bg-subtle);\n\n background: var(--wx-bg-subtle);\n}\n\n/* A striped row is already that colour, so it takes the next one up — nothing to swallow\n there, the buttons of a striped table sit on grey either way. */\n.wx-table--stripe.wx-table--hover .wx-table__row.is-striped:hover {\n --wx-table-row-bg: var(--wx-bg-fill);\n\n background: var(--wx-bg-fill);\n}\n\n.wx-table__row.is-selected {\n --wx-table-row-bg: var(--wx-color-primary-soft);\n\n background: var(--wx-color-primary-soft);\n}\n\n.wx-table__expander {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n padding: 0;\n background: none;\n border: none;\n border-radius: var(--wx-radius-xs);\n color: var(--wx-text-muted);\n cursor: pointer;\n}\n\n.wx-table__expander:hover {\n background: var(--wx-bg-fill);\n color: var(--wx-text-default);\n}\n\n.wx-table__expander:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n/* ---------------------------------------------------------------- tree mode */\n\n/*\n * Inline rather than a flex row: a cell in a table is laid out by the table, and a\n * `display: flex` on it would take the column out of the very grid the pinned columns\n * are measured against.\n */\n.wx-table__tree {\n display: inline-flex;\n align-items: center;\n vertical-align: middle;\n}\n\n.wx-table__tree-toggle {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n margin-inline-end: var(--wx-space-4);\n padding: 0;\n background: none;\n border: none;\n border-radius: var(--wx-radius-xs);\n color: var(--wx-text-muted);\n cursor: pointer;\n}\n\n.wx-table__tree-toggle:hover {\n background: var(--wx-bg-fill);\n color: var(--wx-text-default);\n}\n\n.wx-table__tree-toggle:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-table__tree-toggle.is-leaf {\n cursor: default;\n visibility: hidden;\n}\n\n.wx-table__tree-toggle :deep(svg) {\n transition: transform 0.15s ease;\n}\n\n.wx-table__tree-toggle[aria-expanded='true'] :deep(svg) {\n transform: rotate(90deg);\n}\n\n.wx-table__row.is-dragging {\n opacity: 0.4;\n}\n\n/*\n * The landing is drawn on the cells rather than on the row: a `<tr>` cannot be given a\n * border that survives a sticky column, and an absolutely positioned line would need a\n * positioned row, which is the corner table layout is least sure about.\n */\n.wx-table__row.is-drop-before > .wx-table__cell {\n box-shadow: inset 0 2px 0 0 var(--wx-color-primary);\n}\n\n.wx-table__row.is-drop-after > .wx-table__cell {\n box-shadow: inset 0 -2px 0 0 var(--wx-color-primary);\n}\n\n.wx-table__row.is-drop-inside > .wx-table__cell {\n background: var(--wx-color-primary-soft);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-table__tree-toggle :deep(svg) {\n transition: none;\n }\n}\n\n.wx-table__expander svg {\n width: 12px;\n height: 12px;\n fill: none;\n stroke: currentColor;\n stroke-width: 1.5;\n stroke-linecap: round;\n stroke-linejoin: round;\n transition: transform var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-table__row.is-expanded .wx-table__expander svg {\n transform: rotate(90deg);\n}\n\n.wx-table__expansion {\n background: var(--wx-bg-subtle);\n}\n\n/*\n * What a row opens into is as wide as the table's window, not as the table: when the columns\n * scroll sideways, a card spanning all of them would put its right half out of view. It keeps to\n * the visible width (the root is the inline-size container) and stays put while the columns\n * scroll under it.\n */\n.wx-table__expansion-body {\n position: sticky;\n inset-inline-start: var(--wx-table-padding-x);\n box-sizing: border-box;\n max-width: calc(100cqi - 2 * var(--wx-table-padding-x));\n}\n\n.wx-table__sort {\n display: inline-flex;\n align-items: center;\n gap: var(--wx-space-6);\n padding: 0;\n background: none;\n border: none;\n color: inherit;\n font: inherit;\n cursor: pointer;\n}\n\n.wx-table__sort:hover {\n color: var(--wx-text-default);\n}\n\n.wx-table__sort:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n border-radius: var(--wx-radius-xs);\n}\n\n.wx-table__sort-icon {\n flex: 0 0 auto;\n width: 8px;\n height: 12px;\n}\n\n.wx-table__sort-icon path {\n fill: var(--wx-border-strong);\n}\n\n.wx-table__sort-icon.is-asc .wx-table__sort-up,\n.wx-table__sort-icon.is-desc .wx-table__sort-down {\n fill: var(--wx-color-primary);\n}\n\n.wx-table__empty {\n padding: var(--wx-space-24) var(--wx-table-padding-x);\n color: var(--wx-text-muted);\n text-align: center;\n}\n\n.wx-table__foot .wx-table__cell {\n border-top: 1px solid var(--wx-border-muted);\n}\n\n.wx-table__summary .wx-table__cell {\n color: var(--wx-text-muted);\n}\n\n.wx-table__summary-label {\n text-align: right;\n}\n\n.wx-table__summary.is-strong .wx-table__cell {\n color: var(--wx-text-strong);\n font-weight: var(--wx-font-weight-semibold);\n}\n\n/* The rows stay readable underneath: a page that is being refreshed still says what it said. */\n.wx-table__loading {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--wx-space-8);\n background: color-mix(in srgb, var(--wx-bg-surface) 70%, transparent);\n border-radius: inherit;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-table__spinner {\n width: 16px;\n height: 16px;\n border: 2px solid var(--wx-border-default);\n border-top-color: var(--wx-color-primary);\n border-radius: var(--wx-radius-full);\n animation: wx-table-spin var(--wx-duration-slow) linear infinite;\n}\n\n@keyframes wx-table-spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-table__spinner {\n animation-duration: 3s;\n }\n}\n/* --- cards --------------------------------------------------------------- */\n\n.wx-table__cards {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n padding: var(--wx-space-8);\n /* The same as the row scroller: squeezed, the list scrolls rather than being cut off. */\n overflow-y: auto;\n min-height: 0;\n}\n\n/*\n * Flush in card mode: the column reaches every edge of the box around it, because that box is\n * what keeps the air. Its own step above and below would be that air twice — measured, the last\n * card stood 16 from the card's edge where the first stood 8 from the search.\n */\n.wx-table--flush .wx-table__cards {\n padding: 0;\n}\n\n/*\n * And so is the head, for the same reason: its 12 on top of the card's 8 made the space above\n * the search 20 where the space beside it was 8. What is left is the step under it, which is\n * the same one everything else in a card is spaced by.\n */\n.wx-table--flush.wx-table--cards .wx-table__header {\n padding: 0 0 var(--wx-gap, var(--wx-space-8));\n}\n\n/*\n * Under the search, the step between cards and not the head's own: in card mode the search is\n * one more box in the same column, and a column reads as a column only while the steps down it\n * are equal. The list of cards carries that step as its own top padding.\n */\n.wx-table--cards .wx-table__header {\n padding-block-end: 0;\n}\n\n.wx-table__card {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-6);\n padding: var(--wx-space-10) var(--wx-space-12);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n background: var(--wx-bg-surface);\n}\n\n.wx-table--hover .wx-table__card:hover {\n border-color: var(--wx-border-strong);\n}\n\n.wx-table__card.is-selected {\n border-color: var(--wx-color-primary);\n}\n\n.wx-table__card-top {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n}\n\n/* Pushed to the end, so the checkbox keeps the left and the buttons keep the right. */\n.wx-table__card-tools {\n margin-left: auto;\n}\n\n.wx-table__field {\n display: flex;\n flex-direction: column;\n gap: 1px;\n min-width: 0;\n}\n\n.wx-table__field-label {\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n}\n\n.wx-table__field-value {\n min-width: 0;\n word-break: break-word;\n}\n\n.wx-table__cards-empty {\n padding: var(--wx-space-24) var(--wx-space-12);\n color: var(--wx-text-muted);\n text-align: center;\n}\n\n.wx-table__cards-footer {\n display: flex;\n justify-content: center;\n}\n/* A row that opens something says so before it is clicked. */\n.wx-table--clickable .wx-table__row,\n.wx-table--clickable .wx-table__card {\n cursor: pointer;\n}\n</style>\n","<script setup lang=\"ts\">\nimport {\n computed,\n Fragment,\n nextTick,\n onBeforeUnmount,\n onMounted,\n ref,\n useSlots,\n watch,\n type VNode,\n} from 'vue'\nimport { TabsContent, TabsList, TabsRoot, TabsTrigger } from 'reka-ui'\nimport WxBadge from '../Badge/Badge.vue'\nimport WxDropdown from '../Dropdown/Dropdown.vue'\nimport WxDropdownItem from '../DropdownItem/DropdownItem.vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport WxTab from '../Tab/Tab.vue'\nimport { useElementWidth } from '../../composables/useElementWidth'\nimport type { IconName } from '../Icon/types'\nimport type { TabDescriptor, TabsEmits, TabsProps, TabValue } from './types'\n\ndefineOptions({ name: 'WxTabs' })\n\nconst props = withDefaults(defineProps<TabsProps>(), {\n items: undefined,\n collapseBelow: 0,\n variant: 'line',\n size: 'md',\n orientation: 'horizontal',\n align: 'start',\n activationMode: 'automatic',\n keepAlive: false,\n loop: true,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<TabsEmits>()\n\ndefineSlots<{\n /** The `WxTab`s. */\n default?: () => unknown\n /** Sits at the end of the strip — a button, a filter, a count. */\n extra?: () => unknown\n}>()\n\nconst model = defineModel<TabValue | undefined>({ default: undefined })\n\nconst slots = useSlots()\n\n/** What the last render found, for the code that runs afterwards and cannot rescan. */\nlet rendered: TabDescriptor[] = []\n\n/**\n * The strip is built from the `WxTab`s in the slot, so a tab and its panel are written\n * in one place. The scan runs during render rather than in a computed: slot output is\n * not reactive state, and a cached copy would keep showing yesterday's labels.\n *\n * Given `items`, there is nothing to scan: the strip is the list, and the slot is the one\n * panel under it.\n */\nfunction readTabs(): TabDescriptor[] {\n rendered = props.items\n ? props.items.map((item) => ({ ...item, disabled: item.disabled === true }))\n : collect((slots.default?.() ?? []) as VNode[])\n scheduleSelect()\n return rendered\n}\n\nfunction collect(nodes: VNode[]): TabDescriptor[] {\n const found: TabDescriptor[] = []\n\n for (const node of nodes) {\n // `v-for` and `<template>` wrap what they render in a fragment.\n if (node.type === Fragment) {\n found.push(...collect((node.children ?? []) as VNode[]))\n continue\n }\n if (node.type !== WxTab) continue\n\n const tabProps = (node.props ?? {}) as Record<string, unknown>\n // A component's slots arrive as the vnode's children.\n const tabSlots = node.children as { label?: () => unknown } | null\n\n found.push({\n value: tabProps.value as TabValue,\n label: tabProps.label as string | undefined,\n icon: tabProps.icon as IconName | undefined,\n badge: tabProps.badge as string | number | undefined,\n // A bare `disabled` in a template is an empty string, not `true`.\n disabled: tabProps.disabled === '' || tabProps.disabled === true,\n labelSlot: typeof tabSlots?.label === 'function' ? tabSlots.label : undefined,\n })\n }\n\n return found\n}\n\n/**\n * Nothing selected shows an empty panel, so the first usable tab opens by itself. The\n * check is worth repeating: tabs often arrive from a request, and the tab that was open\n * can go away with the array it came from.\n */\nfunction selectFirst() {\n /* Folded into a switch there is no strip to scan, so the list is asked directly. */\n const tabs: TabDescriptor[] = props.items\n ? props.items.map((item) => ({ ...item, disabled: item.disabled === true }))\n : rendered\n\n if (tabs.length === 0) return\n if (tabs.some((tab) => tab.value === model.value)) return\n\n model.value = (tabs.find((tab) => !tab.disabled) ?? tabs[0]!).value\n}\n\nlet selectQueued = false\n\n/**\n * The check is asked for from the render and answered after it, because writing state\n * mid-render is how render loops start.\n *\n * It hangs off the scan rather than off `onUpdated` deliberately. Slot content belongs\n * to whoever wrote it: when the tabs come from a `v-for` in the parent, Vue patches the\n * new tabs straight into this component's output without re-rendering it, so no update\n * hook of ours would ever run — but the strip is rebuilt, and that is this function.\n */\nfunction scheduleSelect() {\n if (selectQueued) return\n\n selectQueued = true\n nextTick(() => {\n selectQueued = false\n selectFirst()\n })\n}\n\nwatch(model, (value) => {\n if (value !== undefined) emit('change', value)\n})\n\n/* ---------------------------------------------------------------------------\n * The strip on a small screen\n *\n * Tabs outgrow a phone long before they outgrow a desktop, so the strip scrolls\n * sideways rather than wrapping into a second row that pushes the panel down. Three\n * things follow. The active tab is scrolled into view whenever it changes, because it\n * is often changed from somewhere else — a wizard step, a route. The end that has more\n * behind it is faded, so the strip reads as scrollable without spending any width on\n * saying so. And the arrows are for a mouse only: a finger just swipes.\n * ------------------------------------------------------------------------- */\n\nconst scroller = ref<HTMLElement | null>(null)\nconst overflowStart = ref(false)\nconst overflowEnd = ref(false)\n\nconst scrollable = computed(() => props.orientation === 'horizontal')\n\nfunction measure() {\n const el = scroller.value\n if (!el || !scrollable.value) {\n overflowStart.value = false\n overflowEnd.value = false\n return\n }\n\n /* A pixel of slack: fractional widths never land exactly on the edge. */\n const max = el.scrollWidth - el.clientWidth\n overflowStart.value = el.scrollLeft > 1\n overflowEnd.value = el.scrollLeft < max - 1\n}\n\nfunction step(direction: 1 | -1) {\n const el = scroller.value\n if (!el) return\n\n /* Most of a screenful, so a tab or two stays behind as an anchor. */\n el.scrollLeft += direction * Math.max(el.clientWidth * 0.75, 120)\n measure()\n}\n\n/**\n * `instant` is for the first placement: a strip that opens on its eighth tab should\n * already be there, not slide there while the page is still settling.\n */\nfunction revealActive(instant = false) {\n const el = scroller.value\n if (!el || !scrollable.value) return\n\n const active = el.querySelector<HTMLElement>('[data-state=\"active\"]')\n if (!active) return\n\n /* `offsetLeft` is read against the scroller, which is positioned for exactly that. */\n const centred = active.offsetLeft - (el.clientWidth - active.offsetWidth) / 2\n\n if (instant) el.style.scrollBehavior = 'auto'\n /* Past the end it clamps by itself, which is what should happen for the last tab. */\n el.scrollLeft = Math.max(0, centred)\n if (instant) el.style.scrollBehavior = ''\n\n measure()\n}\n\nlet observer: ResizeObserver | undefined\n\nfunction observe() {\n observer?.disconnect()\n\n /* The strip overflows for two reasons: the container shrank, or the tabs changed. */\n observer = new ResizeObserver(() => measure())\n if (scroller.value) observer.observe(scroller.value)\n if (scroller.value?.firstElementChild) observer.observe(scroller.value.firstElementChild)\n}\n\nonMounted(() => {\n selectFirst()\n observe()\n measure()\n revealActive(true)\n})\n\nonBeforeUnmount(() => observer?.disconnect())\n\n/* A list that arrives from a request can drop the view that was open. */\nwatch(\n () => props.items,\n () => scheduleSelect(),\n)\n\n/* ---------------------------------------------------------------------------\n * The strip as one switch\n *\n * A strip is worth scrolling while it is navigation somebody reads along; the views of a\n * list are not that. \"All / Drafts / Published / Edited / Bin\" is one question, and on a\n * phone it is asked the way a question is asked — with the answer showing and the rest a\n * tap away. Not three dots: three dots are actions, and this chooses what is on screen.\n * ------------------------------------------------------------------------- */\n\nconst layout = ref<HTMLElement | null>(null)\nconst ownWidth = useElementWidth(layout)\n\nconst folded = computed(\n () =>\n props.items !== undefined &&\n props.collapseBelow > 0 &&\n ownWidth.value > 0 &&\n ownWidth.value < props.collapseBelow,\n)\n\n/** The view the switch is labelled with. */\nconst current = computed(() => props.items?.find((item) => item.value === model.value))\n\n/* Unfolding builds a new strip, and the old observer was watching an element that is gone. */\nwatch(folded, async () => {\n await nextTick()\n observe()\n measure()\n revealActive(true)\n})\n\nwatch(model, async () => {\n await nextTick()\n revealActive()\n})\n\nconst classes = computed(() => [\n 'wx-tabs',\n `wx-tabs--${props.variant}`,\n `wx-tabs--${props.size}`,\n `wx-tabs--${props.orientation}`,\n `wx-tabs--align-${props.align}`,\n { 'is-folded': folded.value },\n])\n\ndefineExpose({ measure, revealActive })\n</script>\n\n<template>\n <tabs-root\n v-model=\"model\"\n :class=\"classes\"\n :orientation=\"orientation\"\n :activation-mode=\"activationMode\"\n :unmount-on-hide=\"!keepAlive\"\n >\n <!--\n The root is the container the layout asks about, and a container query cannot\n style the container itself — so the strip and the panels are laid out one level in.\n -->\n <div ref=\"layout\" class=\"wx-tabs__layout\">\n <div class=\"wx-tabs__bar\">\n <!--\n Folded up, the whole strip is one control that says which view is open. The list\n behind it is the same list, so a view is still one tap away.\n -->\n <wx-dropdown v-if=\"folded\" class=\"wx-tabs__switch\" align=\"start\" match-trigger-width>\n <template #trigger>\n <button class=\"wx-tabs__switch-trigger\" type=\"button\" :aria-label=\"ariaLabel\">\n <wx-icon v-if=\"current?.icon\" class=\"wx-tabs__icon\" :name=\"current.icon\" />\n <span class=\"wx-tabs__label\">{{ current?.label ?? current?.value ?? '' }}</span>\n <wx-badge v-if=\"current?.badge !== undefined\" size=\"sm\" round>\n {{ current.badge }}\n </wx-badge>\n <wx-icon class=\"wx-tabs__switch-chevron\" name=\"chevron-down\" />\n </button>\n </template>\n\n <wx-dropdown-item\n v-for=\"item in items\"\n :key=\"item.value\"\n :icon=\"item.icon\"\n :active=\"item.value === model\"\n :disabled=\"item.disabled\"\n @click=\"model = item.value\"\n >\n {{ item.label ?? item.value }}\n </wx-dropdown-item>\n </wx-dropdown>\n\n <button\n v-if=\"!folded && (overflowStart || overflowEnd)\"\n class=\"wx-tabs__arrow\"\n type=\"button\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n :disabled=\"!overflowStart\"\n @click=\"step(-1)\"\n >\n <wx-icon name=\"chevron-left\" />\n </button>\n\n <div\n v-if=\"!folded\"\n ref=\"scroller\"\n class=\"wx-tabs__scroller\"\n :class=\"{ 'is-overflow-start': overflowStart, 'is-overflow-end': overflowEnd }\"\n @scroll.passive=\"measure\"\n >\n <tabs-list class=\"wx-tabs__list\" :loop=\"loop\" :aria-label=\"ariaLabel\">\n <tabs-trigger\n v-for=\"tab in readTabs()\"\n :key=\"tab.value\"\n class=\"wx-tabs__tab\"\n :value=\"tab.value\"\n :disabled=\"tab.disabled\"\n >\n <wx-icon v-if=\"tab.icon\" class=\"wx-tabs__icon\" :name=\"tab.icon\" />\n <span class=\"wx-tabs__label\">\n <!-- A slot function renders as a functional component, in its own scope. -->\n <component :is=\"tab.labelSlot\" v-if=\"tab.labelSlot\" />\n <template v-else>{{ tab.label ?? tab.value }}</template>\n </span>\n <wx-badge v-if=\"tab.badge !== undefined\" class=\"wx-tabs__badge\" size=\"sm\" round>\n {{ tab.badge }}\n </wx-badge>\n </tabs-trigger>\n </tabs-list>\n </div>\n\n <button\n v-if=\"!folded && (overflowStart || overflowEnd)\"\n class=\"wx-tabs__arrow\"\n type=\"button\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n :disabled=\"!overflowEnd\"\n @click=\"step(1)\"\n >\n <wx-icon name=\"chevron-right\" />\n </button>\n\n <div v-if=\"$slots.extra\" class=\"wx-tabs__extra\">\n <slot name=\"extra\" />\n </div>\n </div>\n\n <div class=\"wx-tabs__panels\">\n <!--\n One panel, bound to whatever is open: the tab changes what is asked for, not what\n draws the answer. A table under it keeps its search, its page and its scroll, which\n is the whole reason a list switches views this way rather than by swapping panels.\n -->\n <tabs-content v-if=\"items\" class=\"wx-tabs__panel\" :value=\"model ?? ''\">\n <slot />\n </tabs-content>\n <slot v-else />\n </div>\n </div>\n </tabs-root>\n</template>\n\n<style scoped>\n.wx-tabs {\n --wx-tabs-gap: var(--wx-space-4);\n --wx-tabs-fade: 24px;\n\n display: block;\n box-sizing: border-box;\n min-width: 0;\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n /* The strip reacts to the width it was given, not to the window's. */\n container-type: inline-size;\n}\n\n.wx-tabs__layout {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.wx-tabs__bar {\n display: flex;\n align-items: center;\n gap: var(--wx-space-4);\n min-width: 0;\n}\n\n.wx-tabs__scroller {\n /* Positioned so a tab's `offsetLeft` is measured against the strip it scrolls in. */\n position: relative;\n flex: 1 1 auto;\n min-width: 0;\n overflow-x: auto;\n /* A swipe along the strip must not become a page swipe or a browser back gesture. */\n overscroll-behavior-inline: contain;\n scroll-behavior: smooth;\n scrollbar-width: none;\n}\n\n.wx-tabs__scroller::-webkit-scrollbar {\n display: none;\n}\n\n/*\n * The fade says \"there is more this way\" and costs no width, which is the point on a\n * phone. Both ends share one mask, so a strip cut off at both ends fades at both.\n */\n.wx-tabs__scroller.is-overflow-start,\n.wx-tabs__scroller.is-overflow-end {\n mask-image: linear-gradient(\n to right,\n transparent 0,\n #000 var(--wx-tabs-fade-start, 0px),\n #000 calc(100% - var(--wx-tabs-fade-end, 0px)),\n transparent 100%\n );\n}\n\n.wx-tabs__scroller.is-overflow-start {\n --wx-tabs-fade-start: var(--wx-tabs-fade);\n}\n\n.wx-tabs__scroller.is-overflow-end {\n --wx-tabs-fade-end: var(--wx-tabs-fade);\n}\n\n.wx-tabs__list {\n display: flex;\n gap: var(--wx-tabs-gap);\n /* Narrower than the scroller, the list still has to span it for the rule under it. */\n width: max-content;\n min-width: 100%;\n /*\n * With the padding counted inside that 100%. A segmented strip pads its track by four on\n * each side, and on the default box those eight pixels are added to the full width the\n * `min-width` just asked for — so a strip with three tabs and room to spare overflowed its\n * scroller by exactly its own padding, faded at the end and grew a pair of arrows for a\n * journey of eight pixels.\n */\n box-sizing: border-box;\n}\n\n.wx-tabs__tab {\n display: inline-flex;\n align-items: center;\n flex: 0 0 auto;\n gap: var(--wx-space-6);\n box-sizing: border-box;\n margin: 0;\n padding: var(--wx-space-10) var(--wx-space-12);\n background: none;\n border: none;\n border-radius: var(--wx-radius-xs);\n color: var(--wx-text-muted);\n font-family: inherit;\n font-size: var(--wx-font-size-sm);\n font-weight: var(--wx-font-weight-medium);\n line-height: var(--wx-font-line-height-tight);\n white-space: nowrap;\n cursor: pointer;\n transition:\n color var(--wx-duration-fast) var(--wx-easing-standard),\n background var(--wx-duration-fast) var(--wx-easing-standard),\n box-shadow var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n/*\n * Given room, the tabs are page-level navigation and read as such. The question is\n * put to the strip rather than to the window: tabs in a narrow panel on a wide\n * desktop are still tabs in a narrow panel. The compact scale keeps its own size —\n * the rule below is more specific, so it wins wherever it applies.\n */\n@container (min-width: 600px) {\n .wx-tabs__tab {\n font-size: var(--wx-font-size-md);\n }\n}\n\n.wx-tabs--sm .wx-tabs__tab {\n padding: var(--wx-space-6) var(--wx-space-10);\n font-size: var(--wx-font-size-xs);\n}\n\n.wx-tabs__tab:hover:not(:disabled) {\n color: var(--wx-text-default);\n}\n\n.wx-tabs__tab:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-tabs__tab:disabled {\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n.wx-tabs__tab[data-state='active'] {\n color: var(--wx-color-primary);\n}\n\n.wx-tabs__icon {\n flex: 0 0 auto;\n font-size: var(--wx-font-size-md);\n}\n\n.wx-tabs__badge {\n flex: 0 0 auto;\n}\n\n.wx-tabs__arrow {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 24px;\n height: 24px;\n padding: 0;\n background: none;\n border: none;\n border-radius: var(--wx-radius-full);\n color: var(--wx-text-muted);\n cursor: pointer;\n}\n\n.wx-tabs__arrow:hover:not(:disabled) {\n background: var(--wx-bg-fill);\n color: var(--wx-text-default);\n}\n\n.wx-tabs__arrow:disabled {\n color: var(--wx-text-disabled);\n cursor: default;\n}\n\n.wx-tabs__extra {\n display: flex;\n align-items: center;\n flex: 0 0 auto;\n gap: var(--wx-space-6);\n padding-left: var(--wx-space-8);\n}\n\n/* The air between the strip and what it switches — the panel's step, like everything else. */\n.wx-tabs__panels {\n min-width: 0;\n padding-top: var(--wx-gap, var(--wx-space-16));\n}\n\n/*\n * The one panel of a strip built from `items`. A column with the panel's own step, the same\n * as `WxTab` has: what stands in it is cards, and cards carry no margins of their own.\n */\n.wx-tabs__panel {\n display: flex;\n flex-direction: column;\n gap: var(--wx-gap, var(--wx-space-16));\n min-width: 0;\n}\n\n.wx-tabs__panel:focus-visible {\n outline: none;\n}\n\n/* Folded up: one control, as wide as the strip it replaced. */\n.wx-tabs__switch {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.wx-tabs__switch-trigger {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n box-sizing: border-box;\n width: 100%;\n min-height: 44px;\n padding: var(--wx-space-8) var(--wx-space-12);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-control);\n color: var(--wx-text-strong);\n font-family: inherit;\n font-size: var(--wx-font-size-sm);\n font-weight: var(--wx-font-weight-medium);\n line-height: var(--wx-font-line-height-tight);\n text-align: start;\n cursor: pointer;\n}\n\n.wx-tabs__switch-trigger:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-tabs__switch-chevron {\n flex: 0 0 auto;\n margin-inline-start: auto;\n color: var(--wx-text-muted);\n}\n\n/* The rule under the strip belongs to the strip; a single control is not one. */\n.wx-tabs.is-folded .wx-tabs__bar {\n border-bottom: none;\n}\n\n/* Line — the default: a rule under the strip with the active tab standing on it. */\n.wx-tabs--line .wx-tabs__bar {\n border-bottom: 1px solid var(--wx-border-default);\n}\n\n.wx-tabs--line .wx-tabs__tab {\n border-radius: var(--wx-radius-xs) var(--wx-radius-xs) 0 0;\n box-shadow: inset 0 -2px 0 transparent;\n}\n\n.wx-tabs--line .wx-tabs__tab[data-state='active'] {\n box-shadow: inset 0 -2px 0 var(--wx-color-primary);\n}\n\n.wx-tabs--line .wx-tabs__tab:focus-visible {\n box-shadow: var(--wx-ring-focus);\n}\n\n/* Pill — a segmented control: the list is the track, the active tab the thumb. */\n.wx-tabs--pill .wx-tabs__list {\n gap: var(--wx-space-2);\n padding: var(--wx-space-4);\n background: var(--wx-bg-muted);\n border-radius: var(--wx-radius-sm);\n}\n\n/*\n * A segmented control is a control, not a place in the panel — so its proportions are a\n * button's and not a heading's.\n *\n * Two things follow. It is wider than it is tall: the room goes sideways, where the words\n * are, rather than above and below them, and a pill as tall as it was reads as a stack of\n * buttons rather than as one switch. And it keeps the size of a label at every width — the\n * strip below grows to 16px in a wide container, which is right for tabs somebody navigates\n * by and monstrous for three pills inside a card.\n */\n.wx-tabs--pill .wx-tabs__tab {\n border-radius: var(--wx-radius-xs);\n padding: var(--wx-space-6) var(--wx-space-16);\n font-size: var(--wx-font-size-sm);\n}\n\n/* The compact scale, in the same proportion. */\n.wx-tabs--pill.wx-tabs--sm .wx-tabs__tab {\n padding: var(--wx-space-4) var(--wx-space-12);\n font-size: var(--wx-font-size-xs);\n}\n\n.wx-tabs--pill .wx-tabs__tab[data-state='active'] {\n background: var(--wx-bg-surface);\n color: var(--wx-text-strong);\n box-shadow: var(--wx-shadow-card);\n}\n\n/* Card — folder tabs: the active one is a sheet that has risen through the rule. */\n.wx-tabs--card .wx-tabs__bar {\n border-bottom: 1px solid var(--wx-border-default);\n}\n\n.wx-tabs--card .wx-tabs__list {\n gap: 0;\n}\n\n.wx-tabs--card .wx-tabs__tab {\n margin-bottom: -1px;\n border: 1px solid transparent;\n border-radius: var(--wx-radius-xs) var(--wx-radius-xs) 0 0;\n}\n\n.wx-tabs--card .wx-tabs__tab[data-state='active'] {\n background: var(--wx-bg-surface);\n border-color: var(--wx-border-default);\n border-bottom-color: var(--wx-bg-surface);\n}\n\n/* Alignment only means anything while the tabs still fit. */\n.wx-tabs--align-center .wx-tabs__list {\n justify-content: center;\n}\n\n.wx-tabs--align-end .wx-tabs__list {\n justify-content: flex-end;\n}\n\n.wx-tabs--align-stretch .wx-tabs__list {\n width: 100%;\n}\n\n.wx-tabs--align-stretch .wx-tabs__tab {\n flex: 1 1 0;\n justify-content: center;\n}\n\n/* A column of tabs beside the panel. */\n.wx-tabs--vertical .wx-tabs__layout {\n flex-direction: row;\n align-items: flex-start;\n gap: var(--wx-gap, var(--wx-space-16));\n}\n\n.wx-tabs--vertical .wx-tabs__bar {\n flex: 0 0 auto;\n flex-direction: column;\n align-items: stretch;\n}\n\n.wx-tabs--vertical .wx-tabs__scroller {\n overflow-x: visible;\n}\n\n.wx-tabs--vertical .wx-tabs__list {\n flex-direction: column;\n width: auto;\n min-width: 0;\n}\n\n.wx-tabs--vertical .wx-tabs__tab {\n justify-content: flex-start;\n}\n\n.wx-tabs--vertical .wx-tabs__panels {\n flex: 1 1 auto;\n padding-top: 0;\n}\n\n.wx-tabs--vertical.wx-tabs--line .wx-tabs__bar {\n border-right: 1px solid var(--wx-border-default);\n border-bottom: none;\n}\n\n.wx-tabs--vertical.wx-tabs--line .wx-tabs__tab {\n border-radius: var(--wx-radius-xs) 0 0 var(--wx-radius-xs);\n box-shadow: inset -2px 0 0 transparent;\n}\n\n.wx-tabs--vertical.wx-tabs--line .wx-tabs__tab[data-state='active'] {\n box-shadow: inset -2px 0 0 var(--wx-color-primary);\n}\n\n/*\n * A column of tabs and a panel do not both fit across a phone. Below the width where\n * that stops working the column lies back down into an ordinary scrolling strip and\n * the panel takes the full width. The question is put to the tabs rather than to the\n * window: the same squeeze happens inside a narrow drawer on a wide monitor.\n */\n@container (max-width: 480px) {\n .wx-tabs--vertical .wx-tabs__layout {\n flex-direction: column;\n gap: 0;\n }\n\n .wx-tabs--vertical .wx-tabs__bar {\n flex-direction: row;\n align-items: center;\n }\n\n .wx-tabs--vertical .wx-tabs__scroller {\n overflow-x: auto;\n }\n\n .wx-tabs--vertical .wx-tabs__list {\n flex-direction: row;\n width: max-content;\n min-width: 100%;\n }\n\n .wx-tabs--vertical .wx-tabs__panels {\n padding-top: var(--wx-gap, var(--wx-space-16));\n }\n\n .wx-tabs--vertical.wx-tabs--line .wx-tabs__bar {\n border-right: none;\n border-bottom: 1px solid var(--wx-border-default);\n }\n\n .wx-tabs--vertical.wx-tabs--line .wx-tabs__tab {\n border-radius: var(--wx-radius-xs) var(--wx-radius-xs) 0 0;\n box-shadow: inset 0 -2px 0 transparent;\n }\n\n .wx-tabs--vertical.wx-tabs--line .wx-tabs__tab[data-state='active'] {\n box-shadow: inset 0 -2px 0 var(--wx-color-primary);\n }\n}\n\n/* A finger needs a target it can hit, and has no use for the arrows — it swipes. */\n@media (pointer: coarse) {\n .wx-tabs__tab {\n min-height: 44px;\n }\n\n /*\n * A pill is wider than a tab and it is hit sideways: at 44 tall and its own width the\n * segmented strip on a phone stood as a row of blocks, which is what a switch must not look\n * like. It keeps the height the panel gives its other controls there instead — the room a\n * finger needs it takes across.\n */\n .wx-tabs--pill .wx-tabs__tab {\n min-height: 36px;\n }\n\n .wx-tabs__arrow {\n display: none;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-tabs__scroller {\n scroll-behavior: auto;\n }\n\n .wx-tabs__tab {\n transition: none;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { useFormField } from '../../composables/useFormField'\nimport type { TagsInputEmits, TagsInputProps } from './types'\nimport { useControlAttrs } from '../../composables/useControlAttrs'\n\ndefineOptions({ name: 'WxTagsInput', inheritAttrs: false })\n\n/* `class` and `style` belong to the control; the rest belongs to its input. */\nconst { rootAttrs, controlAttrs } = useControlAttrs()\n\nconst props = withDefaults(defineProps<TagsInputProps>(), {\n suggestions: () => [],\n placeholder: undefined,\n emptyText: 'Nothing found',\n max: undefined,\n duplicates: false,\n allowCreate: true,\n disabled: undefined,\n size: undefined,\n status: undefined,\n id: undefined,\n name: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<TagsInputEmits>()\n\nconst model = defineModel<string[]>({ default: () => [] })\n\nconst field = useFormField(props)\nconst inputRef = ref<HTMLInputElement | null>(null)\nconst text = ref('')\nconst open = ref(false)\nconst highlighted = ref(-1)\n/** The tag Backspace has marked; the next Backspace removes it. */\nconst armed = ref(-1)\n\nconst tags = computed(() => model.value ?? [])\n\nconst suggestions = computed(() =>\n props.suggestions.filter((suggestion) => !tags.value.includes(suggestion)),\n)\n\nconst showList = computed(() => open.value && suggestions.value.length > 0)\n\nconst full = computed(() => props.max !== undefined && tags.value.length >= props.max)\n\nconst classes = computed(() => [\n 'wx-tags-input',\n `wx-tags-input--${field.size.value}`,\n {\n [`wx-tags-input--${field.status.value}`]: field.status.value !== 'default',\n 'is-open': showList.value,\n 'is-disabled': field.disabled.value,\n },\n])\n\nwatch(suggestions, () => {\n highlighted.value = -1\n})\n\nfunction commit(next: string[]) {\n model.value = next\n emit('change', next)\n}\n\nfunction add(tag: string) {\n const value = tag.trim()\n if (!value || full.value) return\n if (!props.duplicates && tags.value.includes(value)) {\n text.value = ''\n return\n }\n commit([...tags.value, value])\n text.value = ''\n open.value = false\n armed.value = -1\n}\n\nfunction remove(index: number) {\n commit(tags.value.filter((_, position) => position !== index))\n armed.value = -1\n}\n\nfunction onInput(event: Event) {\n const value = (event.target as HTMLInputElement).value\n text.value = value\n armed.value = -1\n highlighted.value = -1\n if (value) open.value = true\n emit('search', value)\n}\n\n/**\n * Backspace on an empty field marks the last tag first and removes it on the second\n * press — deleting something the user cannot see would be worse than one extra key.\n */\nfunction onKeydown(event: KeyboardEvent) {\n if (event.key === 'Escape') {\n open.value = false\n armed.value = -1\n return\n }\n\n if (event.key === 'Backspace' && text.value === '' && tags.value.length > 0) {\n event.preventDefault()\n if (armed.value === tags.value.length - 1) remove(armed.value)\n else armed.value = tags.value.length - 1\n return\n }\n\n if (event.key === 'ArrowDown' && showList.value) {\n event.preventDefault()\n highlighted.value = (highlighted.value + 1) % suggestions.value.length\n return\n }\n\n if (event.key === 'ArrowUp' && showList.value) {\n event.preventDefault()\n highlighted.value =\n highlighted.value <= 0 ? suggestions.value.length - 1 : highlighted.value - 1\n return\n }\n\n if (event.key === 'Enter') {\n event.preventDefault()\n if (showList.value && highlighted.value >= 0) add(suggestions.value[highlighted.value])\n else if (props.allowCreate) add(text.value)\n }\n}\n\nfunction onBlur() {\n armed.value = -1\n // Let a click on a suggestion land before the list disappears.\n window.setTimeout(() => {\n open.value = false\n }, 120)\n}\n\ndefineExpose({ focus: () => inputRef.value?.focus() })\n</script>\n\n<template>\n <div :class=\"classes\" v-bind=\"rootAttrs\">\n <div class=\"wx-tags-input__anchor\" @click=\"inputRef?.focus()\">\n <span\n v-for=\"(tag, index) in tags\"\n :key=\"tag\"\n class=\"wx-tags-input__tag\"\n :class=\"{ 'is-armed': index === armed }\"\n >\n {{ tag }}\n <button\n v-if=\"!field.disabled.value\"\n class=\"wx-tags-input__remove\"\n type=\"button\"\n tabindex=\"-1\"\n :aria-label=\"`Remove ${tag}`\"\n @click.stop=\"remove(index)\"\n >\n ✕\n </button>\n </span>\n\n <input\n :id=\"field.id.value\"\n ref=\"inputRef\"\n v-bind=\"controlAttrs\"\n class=\"wx-tags-input__field\"\n type=\"text\"\n role=\"combobox\"\n autocomplete=\"off\"\n :value=\"text\"\n :placeholder=\"placeholder\"\n :disabled=\"field.disabled.value\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"field.describedBy.value\"\n :aria-invalid=\"field.status.value === 'error' || undefined\"\n :aria-expanded=\"showList\"\n @input=\"onInput\"\n @keydown=\"onKeydown\"\n @focus=\"open = true\"\n @blur=\"onBlur\"\n />\n\n <ul v-if=\"showList\" class=\"wx-tags-input__list\" role=\"listbox\">\n <li\n v-for=\"(suggestion, index) in suggestions\"\n :key=\"suggestion\"\n class=\"wx-tags-input__option\"\n :class=\"{ 'is-highlighted': index === highlighted }\"\n role=\"option\"\n :aria-selected=\"index === highlighted\"\n @mousedown.prevent=\"add(suggestion)\"\n @mousemove=\"highlighted = index\"\n >\n {{ suggestion }}\n </li>\n </ul>\n </div>\n\n <select v-if=\"name\" class=\"wx-sr-only\" :name=\"name\" multiple tabindex=\"-1\" aria-hidden=\"true\">\n <option v-for=\"tag in tags\" :key=\"tag\" :value=\"tag\" selected>{{ tag }}</option>\n </select>\n </div>\n</template>\n\n<style scoped>\n.wx-tags-input {\n display: block;\n width: 100%;\n}\n\n.wx-tags-input__anchor {\n position: relative;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-4);\n box-sizing: border-box;\n min-height: var(--wx-size-control-md);\n padding: var(--wx-space-4) var(--wx-space-10);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-control);\n color: var(--wx-text-default);\n font-size: var(--wx-font-size-control-md);\n cursor: text;\n transition: border-color var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-tags-input--sm .wx-tags-input__anchor {\n min-height: var(--wx-size-control-sm);\n font-size: var(--wx-font-size-control-sm);\n}\n\n.wx-tags-input--lg .wx-tags-input__anchor {\n min-height: var(--wx-size-control-lg);\n font-size: var(--wx-font-size-control-lg);\n}\n\n.wx-tags-input__anchor:hover {\n border-color: var(--wx-border-strong);\n}\n\n.wx-tags-input__anchor:focus-within {\n border-color: var(--wx-border-focus);\n}\n\n.wx-tags-input--error .wx-tags-input__anchor {\n border-color: var(--wx-color-danger);\n}\n\n.wx-tags-input--success .wx-tags-input__anchor {\n border-color: var(--wx-color-success);\n}\n\n.wx-tags-input--warning .wx-tags-input__anchor {\n border-color: var(--wx-color-warning);\n}\n\n.wx-tags-input.is-disabled .wx-tags-input__anchor {\n background: var(--wx-bg-disabled);\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n.wx-tags-input__tag {\n display: inline-flex;\n align-items: center;\n gap: var(--wx-space-4);\n padding: 2px var(--wx-space-6);\n background: var(--wx-bg-fill);\n border-radius: var(--wx-radius-xs);\n font-size: var(--wx-font-size-sm);\n line-height: var(--wx-font-line-height-tight);\n}\n\n.wx-tags-input__tag.is-armed {\n background: var(--wx-color-danger-soft);\n color: var(--wx-color-danger);\n}\n\n.wx-tags-input__remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n background: transparent;\n border: none;\n color: currentcolor;\n font-size: var(--wx-font-size-xs);\n line-height: 1;\n opacity: 0.65;\n cursor: pointer;\n}\n\n.wx-tags-input__remove:hover {\n opacity: 1;\n}\n\n.wx-tags-input__field {\n flex: 1 1 80px;\n min-width: 0;\n padding: 0;\n background: transparent;\n border: none;\n outline: none;\n color: inherit;\n font-family: inherit;\n font-size: inherit;\n}\n\n.wx-tags-input__field::placeholder {\n color: var(--wx-text-placeholder);\n}\n\n.wx-tags-input__list {\n position: absolute;\n top: calc(100% + var(--wx-space-4));\n left: 0;\n right: 0;\n /* One layer for every floating panel, so the one opened last is the one on top. */\n z-index: var(--wx-z-index-popover);\n max-height: 220px;\n margin: 0;\n padding: var(--wx-space-4);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-sm);\n box-shadow: var(--wx-shadow-popover);\n list-style: none;\n overflow-y: auto;\n}\n\n.wx-tags-input__option {\n padding: var(--wx-space-6) var(--wx-space-10);\n border-radius: var(--wx-radius-xs);\n cursor: pointer;\n}\n\n.wx-tags-input__option.is-highlighted {\n background: var(--wx-bg-fill);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { TextProps } from './types'\n\ndefineOptions({ name: 'WxText' })\n\nconst props = withDefaults(defineProps<TextProps>(), {\n as: 'span',\n size: 'md',\n weight: 'regular',\n tone: 'default',\n align: undefined,\n truncate: false,\n italic: false,\n mono: false,\n})\n\nconst clampLines = computed(() => (typeof props.truncate === 'number' ? props.truncate : undefined))\n\nconst classes = computed(() => [\n 'wx-text',\n `wx-text--${props.size}`,\n `wx-text--${props.weight}`,\n `wx-text--tone-${props.tone}`,\n {\n [`wx-text--align-${props.align}`]: Boolean(props.align),\n 'wx-text--italic': props.italic,\n 'wx-text--mono': props.mono,\n 'wx-text--truncate': props.truncate === true,\n 'wx-text--clamp': clampLines.value !== undefined,\n },\n])\n\nconst style = computed(() =>\n clampLines.value === undefined ? undefined : { '--wx-text-lines': clampLines.value },\n)\n</script>\n\n<template>\n <component :is=\"as\" :class=\"classes\" :style=\"style\">\n <slot />\n </component>\n</template>\n\n<style scoped>\n.wx-text {\n margin: 0;\n font-family: var(--wx-font-family-sans);\n line-height: var(--wx-font-line-height-normal);\n color: var(--wx-text-color, var(--wx-text-default));\n}\n\n/* sizes */\n.wx-text--xs {\n font-size: var(--wx-font-size-xs);\n}\n\n.wx-text--sm {\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-text--md {\n font-size: var(--wx-font-size-md);\n}\n\n.wx-text--lg {\n font-size: var(--wx-font-size-lg);\n}\n\n.wx-text--xl {\n font-size: var(--wx-font-size-xl);\n}\n\n/* weights */\n.wx-text--regular {\n font-weight: var(--wx-font-weight-regular);\n}\n\n.wx-text--medium {\n font-weight: var(--wx-font-weight-medium);\n}\n\n.wx-text--semibold {\n font-weight: var(--wx-font-weight-semibold);\n}\n\n.wx-text--bold {\n font-weight: var(--wx-font-weight-bold);\n}\n\n/* tones */\n.wx-text--tone-default {\n --wx-text-color: var(--wx-text-default);\n}\n\n.wx-text--tone-strong {\n --wx-text-color: var(--wx-text-strong);\n}\n\n.wx-text--tone-muted {\n --wx-text-color: var(--wx-text-muted);\n}\n\n.wx-text--tone-placeholder {\n --wx-text-color: var(--wx-text-placeholder);\n}\n\n.wx-text--tone-primary {\n --wx-text-color: var(--wx-color-primary);\n}\n\n.wx-text--tone-success {\n --wx-text-color: var(--wx-color-success-active);\n}\n\n.wx-text--tone-warning {\n --wx-text-color: var(--wx-color-warning-active);\n}\n\n.wx-text--tone-danger {\n --wx-text-color: var(--wx-color-danger);\n}\n\n.wx-text--tone-info {\n --wx-text-color: var(--wx-color-info-active);\n}\n\n.wx-text--tone-inverse {\n --wx-text-color: var(--wx-text-inverse);\n}\n\n/* alignment */\n.wx-text--align-start {\n text-align: start;\n}\n\n.wx-text--align-center {\n text-align: center;\n}\n\n.wx-text--align-end {\n text-align: end;\n}\n\n.wx-text--align-justify {\n text-align: justify;\n}\n\n.wx-text--italic {\n font-style: italic;\n}\n\n.wx-text--mono {\n font-family: var(--wx-font-family-mono);\n font-variant-numeric: tabular-nums;\n}\n\n/* Truncation needs a block box: an inline span ignores overflow. */\n.wx-text--truncate {\n display: block;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wx-text--clamp {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: var(--wx-text-lines, 2);\n line-clamp: var(--wx-text-lines, 2);\n overflow: hidden;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport { useFormField } from '../../composables/useFormField'\nimport { useLocalized } from '../../composables/useLocalized'\nimport LocalePicker from '../Locales/LocalePicker.vue'\nimport WxTokenButton from '../../internal/TokenButton.vue'\nimport WxTokenMenu from '../../internal/TokenMenu.vue'\nimport {\n fieldAnchor,\n textRect,\n tokenAnchor,\n tokenSegments,\n tokenText,\n useTokenMenu,\n type TokenOption,\n type TokenRange,\n} from '../../composables/useTokens'\nimport type { TextareaEmits, TextareaModelValue, TextareaProps } from './types'\nimport { useControlAttrs } from '../../composables/useControlAttrs'\n\ndefineOptions({ name: 'WxTextarea', inheritAttrs: false })\n\n/* `class` and `style` belong to the control; the rest belongs to its input. */\nconst { rootAttrs, controlAttrs } = useControlAttrs()\n\nconst props = withDefaults(defineProps<TextareaProps>(), {\n size: undefined,\n status: undefined,\n id: undefined,\n placeholder: undefined,\n disabled: undefined,\n readonly: false,\n rows: 3,\n autosize: false,\n maxlength: undefined,\n showCount: false,\n resize: 'vertical',\n ariaLabel: undefined,\n localized: false,\n tokens: undefined,\n tokensTitle: 'Placeholders',\n tokensLabel: 'Insert a placeholder',\n})\n\nconst emit = defineEmits<TextareaEmits>()\n\nconst model = defineModel<TextareaModelValue>({ default: '' })\n\nconst field = useFormField(props)\nconst textareaRef = ref<HTMLTextAreaElement | null>(null)\nconst focused = ref(false)\n\nconst locales = useLocalized(props, model)\n\n/** The language on screen, or nothing at all when the field is plain. */\nconst editing = computed(() => (locales.on.value ? locales.active.value : undefined))\n\nconst currentValue = computed(() => locales.read(editing.value))\n\n/* The languages not on screen, carried along — see the same note in `WxInput`. */\nconst carried = computed(() =>\n locales.on.value\n ? locales.list.value\n .filter((locale) => locale.code !== locales.active.value)\n .map((locale) => ({ code: locale.code, value: locales.read(locale.code) }))\n : [],\n)\n\nconst counter = computed(() =>\n props.showCount && props.maxlength ? `${currentValue.value.length}/${props.maxlength}` : null,\n)\n\nconst autosizeOptions = computed(() =>\n props.autosize === true ? {} : props.autosize === false ? null : props.autosize,\n)\n\nconst classes = computed(() => [\n 'wx-textarea',\n `wx-textarea--${field.size.value}`,\n {\n [`wx-textarea--${field.status.value}`]: field.status.value !== 'default',\n 'is-focused': focused.value,\n 'is-disabled': field.disabled.value,\n 'is-readonly': props.readonly,\n 'is-autosize': Boolean(autosizeOptions.value),\n 'is-localized': locales.on.value,\n 'has-tokens': hasTokens.value,\n 'is-tokenized': tokenized.value,\n },\n])\n\n/** Grows the field to fit its content, clamped by minRows / maxRows. */\nfunction syncHeight() {\n const options = autosizeOptions.value\n const el = textareaRef.value\n if (!options || !el) return\n\n el.style.height = 'auto'\n const styles = getComputedStyle(el)\n const lineHeight = Number.parseFloat(styles.lineHeight) || 20\n const vertical =\n Number.parseFloat(styles.paddingTop) +\n Number.parseFloat(styles.paddingBottom) +\n Number.parseFloat(styles.borderTopWidth) +\n Number.parseFloat(styles.borderBottomWidth)\n\n let height = el.scrollHeight\n if (options.minRows) height = Math.max(height, options.minRows * lineHeight + vertical)\n if (options.maxRows) height = Math.min(height, options.maxRows * lineHeight + vertical)\n\n el.style.height = `${height}px`\n el.style.overflowY = options.maxRows && el.scrollHeight > height ? 'auto' : 'hidden'\n}\n\nonMounted(() => nextTick(syncHeight))\nwatch([currentValue, autosizeOptions], () => nextTick(syncHeight))\n\nconst rootRef = ref<HTMLElement | null>(null)\nconst mirrorRef = ref<HTMLElement | null>(null)\n\nconst tokens = useTokenMenu(() => props.tokens)\nconst hasTokens = computed(() => tokens.all.value.length > 0)\nconst listId = computed(() => `${field.id.value}-tokens`)\n\n/*\n * The text again, behind the same box, with the placeholders as chips — the same mirror as in\n * `WxInput`, wrapped instead of scrolled sideways. The zero-width space at its end gives a\n * trailing newline the empty line the textarea shows for it, so both scroll the same height.\n */\nconst segments = computed(() =>\n hasTokens.value ? tokenSegments(String(currentValue.value), tokens.known.value) : [],\n)\nconst tokenized = computed(() => segments.value.some((segment) => segment.token !== null))\n\nfunction syncMirror(): void {\n const textarea = textareaRef.value\n const mirror = mirrorRef.value\n if (!textarea || !mirror) return\n\n // The client box rather than the border box: a scrollbar takes width from the text, and the\n // mirror has to wrap where the textarea wraps.\n mirror.style.width = `${textarea.clientWidth}px`\n mirror.style.height = `${textarea.clientHeight}px`\n mirror.scrollTop = textarea.scrollTop\n mirror.scrollLeft = textarea.scrollLeft\n}\n\n/* Dragged by its corner, grown by autosize, or narrowed with the panel. */\nlet resizing: ResizeObserver | null = null\n\nonMounted(() => {\n void nextTick(syncMirror)\n if (typeof ResizeObserver !== 'undefined' && textareaRef.value) {\n resizing = new ResizeObserver(() => syncMirror())\n resizing.observe(textareaRef.value)\n }\n})\nonBeforeUnmount(() => resizing?.disconnect())\nwatch(segments, () => void nextTick(syncMirror))\n\n/** Under the line being typed, at the bracket; under the field where nothing can be measured. */\nfunction caretAnchor(offset: number) {\n const rect = mirrorRef.value ? textRect(mirrorRef.value, offset) : null\n\n return rect ? tokenAnchor(rect, rootRef.value) : fieldAnchor(rootRef.value, null)\n}\n\nfunction suggestTokens(): void {\n const textarea = textareaRef.value\n if (!hasTokens.value || !textarea) return\n\n const caret = textarea.selectionStart ?? textarea.value.length\n if (caret !== textarea.selectionEnd) return tokens.close()\n\n const before = textarea.value.slice(0, caret)\n tokens.suggest(before, caret, () => caretAnchor(before.lastIndexOf('[')))\n}\n\nfunction insertToken(token: TokenOption, at: TokenRange): void {\n const textarea = textareaRef.value\n const value = String(currentValue.value)\n const text = tokenText(token)\n const next = value.slice(0, at.from) + text + value.slice(at.to)\n\n locales.write(editing.value, next)\n emit('input', next)\n\n if (!textarea) return\n\n textarea.value = next\n textarea.focus()\n textarea.setSelectionRange(at.from + text.length, at.from + text.length)\n void nextTick(syncMirror)\n}\n\n/** The help button: every placeholder, going where the caret is — or at the end, if nowhere. */\nfunction browseTokens(): void {\n const textarea = textareaRef.value\n if (!textarea) return\n if (tokens.open.value && tokens.browsing.value) return tokens.close()\n\n const length = textarea.value.length\n const had = document.activeElement === textarea\n\n textarea.focus()\n if (!had) textarea.setSelectionRange(length, length)\n\n const from = had ? (textarea.selectionStart ?? length) : length\n const to = had ? (textarea.selectionEnd ?? from) : length\n\n tokens.browse({ from, to }, caretAnchor(from))\n}\n\nfunction onKeydown(event: KeyboardEvent): void {\n tokens.keydown(event, insertToken)\n}\n\n/* The caret moved without typing: an open list follows it, or goes. */\nfunction onCaretMove(event: Event): void {\n syncMirror()\n if (!tokens.open.value) return\n if (\n event instanceof KeyboardEvent &&\n !['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)\n )\n return\n suggestTokens()\n}\n\nfunction onInput(event: Event) {\n const value = (event.target as HTMLTextAreaElement).value\n locales.write(editing.value, value)\n emit('input', value)\n suggestTokens()\n syncMirror()\n}\n\nfunction onChange(event: Event) {\n emit('change', (event.target as HTMLTextAreaElement).value)\n}\n\nfunction onFocus(event: FocusEvent) {\n focused.value = true\n emit('focus', event)\n}\n\nfunction onBlur(event: FocusEvent) {\n focused.value = false\n tokens.close()\n emit('blur', event)\n}\n\n/** Same as the input: the caret follows the language into this field. */\nfunction choose(code: string): void {\n locales.active.value = code\n void nextTick(() => textareaRef.value?.focus())\n}\n\ndefineExpose({\n focus: () => textareaRef.value?.focus(),\n blur: () => textareaRef.value?.blur(),\n select: () => textareaRef.value?.select(),\n textarea: textareaRef,\n})\n</script>\n\n<template>\n <div ref=\"rootRef\" :class=\"classes\" v-bind=\"rootAttrs\">\n <textarea\n :id=\"field.id.value\"\n ref=\"textareaRef\"\n v-bind=\"controlAttrs\"\n class=\"wx-textarea__inner\"\n :name=\"locales.nameFor(controlAttrs.name, editing)\"\n :value=\"currentValue\"\n :rows=\"rows\"\n :placeholder=\"placeholder\"\n :disabled=\"field.disabled.value\"\n :readonly=\"readonly\"\n :maxlength=\"maxlength\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"field.describedBy.value\"\n :aria-invalid=\"field.status.value === 'error' || undefined\"\n :style=\"{ resize }\"\n :aria-autocomplete=\"hasTokens ? 'list' : undefined\"\n :aria-controls=\"tokens.open.value ? listId : undefined\"\n :aria-activedescendant=\"tokens.open.value ? `${listId}-${tokens.active.value}` : undefined\"\n @input=\"onInput\"\n @change=\"onChange\"\n @focus=\"onFocus\"\n @blur=\"onBlur\"\n @keydown=\"onKeydown\"\n @keyup=\"onCaretMove\"\n @click=\"onCaretMove\"\n @scroll=\"syncMirror\"\n />\n\n <div\n v-if=\"hasTokens\"\n ref=\"mirrorRef\"\n class=\"wx-textarea__mirror\"\n :class=\"{ 'is-shown': tokenized }\"\n aria-hidden=\"true\"\n >\n <template v-for=\"(segment, index) in segments\" :key=\"index\"\n ><span v-if=\"segment.token\" class=\"wx-token\">{{ segment.text }}</span\n ><template v-else>{{ segment.text }}</template></template\n >​\n </div>\n\n <input\n v-for=\"other in carried\"\n :key=\"other.code\"\n type=\"hidden\"\n :name=\"locales.nameFor(controlAttrs.name, other.code)\"\n :value=\"other.value\"\n />\n\n <span v-if=\"counter\" class=\"wx-textarea__count\">{{ counter }}</span>\n\n <wx-token-button\n v-if=\"hasTokens\"\n :label=\"tokensLabel\"\n :disabled=\"field.disabled.value || readonly\"\n @click=\"browseTokens\"\n />\n\n <wx-token-menu\n v-if=\"hasTokens\"\n :open=\"tokens.open.value\"\n :items=\"tokens.items.value\"\n :active=\"tokens.active.value\"\n :anchor=\"tokens.anchor.value\"\n :list-id=\"listId\"\n :title=\"tokens.browsing.value ? tokensTitle : undefined\"\n :owner=\"rootRef\"\n @choose=\"(token) => tokens.choose(token, insertToken)\"\n @hover=\"(index) => (tokens.active.value = index)\"\n @close=\"tokens.close()\"\n />\n\n <locale-picker\n v-if=\"locales.on.value\"\n :locales=\"locales.list.value\"\n :active=\"locales.active.value\"\n @choose=\"choose\"\n />\n </div>\n</template>\n\n<style scoped>\n.wx-textarea {\n /* Tall, so the chip is pinned near the top rather than centred, and a size smaller. */\n --wx-locale-picker-height: 20px;\n --wx-locale-picker-top: var(--wx-space-6);\n --wx-locale-picker-shift: 0;\n\n position: relative;\n display: block;\n box-sizing: border-box;\n width: 100%;\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-control);\n color: var(--wx-text-default);\n transition:\n border-color var(--wx-duration-normal) var(--wx-easing-standard),\n background-color var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-textarea:hover:not(.is-disabled) {\n border-color: var(--wx-border-strong);\n}\n\n.wx-textarea.is-focused {\n border-color: var(--wx-border-focus);\n}\n\n.wx-textarea--error,\n.wx-textarea--error.is-focused {\n border-color: var(--wx-color-danger);\n}\n\n.wx-textarea--success,\n.wx-textarea--success.is-focused {\n border-color: var(--wx-color-success);\n}\n\n.wx-textarea--warning,\n.wx-textarea--warning.is-focused {\n border-color: var(--wx-color-warning);\n}\n\n.wx-textarea.is-disabled {\n background: var(--wx-bg-disabled);\n color: var(--wx-text-disabled);\n}\n\n.wx-textarea__inner {\n display: block;\n box-sizing: border-box;\n width: 100%;\n margin: 0;\n padding: var(--wx-space-8) var(--wx-space-12);\n background: transparent;\n border: none;\n outline: none;\n color: inherit;\n font-family: inherit;\n font-size: inherit;\n line-height: var(--wx-font-line-height-normal);\n}\n\n.wx-textarea--sm {\n font-size: var(--wx-font-size-control-sm);\n}\n\n.wx-textarea--md {\n font-size: var(--wx-font-size-control-md);\n}\n\n.wx-textarea--lg {\n font-size: var(--wx-font-size-control-lg);\n}\n\n.wx-textarea.is-autosize .wx-textarea__inner {\n resize: none !important;\n overflow-y: hidden;\n}\n\n.wx-textarea__inner::placeholder {\n color: var(--wx-text-placeholder);\n}\n\n.wx-textarea__inner:disabled {\n cursor: not-allowed;\n}\n\n/* Room for the language chip in the corner, so the first line does not run under it. */\n.wx-textarea.is-localized .wx-textarea__inner {\n padding-right: var(--wx-space-40);\n}\n\n/*\n * Over the textarea, in its box and with its padding, so every letter lands where the textarea\n * draws it; the size and the scroll are copied over in `syncMirror`. Transparent until there is a\n * chip to draw — it is also what the caret's place is measured on.\n */\n.wx-textarea__mirror {\n position: absolute;\n top: 0;\n left: 0;\n box-sizing: border-box;\n padding: var(--wx-space-8) var(--wx-space-12);\n overflow: hidden;\n color: transparent;\n font: inherit;\n line-height: var(--wx-font-line-height-normal);\n letter-spacing: inherit;\n white-space: pre-wrap;\n overflow-wrap: break-word;\n pointer-events: none;\n}\n\n.wx-textarea__mirror.is-shown {\n color: inherit;\n}\n\n/* Only the letters go: the caret, the selection and the placeholder are still the textarea's. */\n.wx-textarea.is-tokenized .wx-textarea__inner {\n color: transparent;\n caret-color: var(--wx-text-default);\n}\n\n/* The help button takes the top corner, beside the language chip when there is one. */\n.wx-textarea .wx-token-button {\n position: absolute;\n top: var(--wx-space-6);\n right: var(--wx-space-8);\n}\n\n.wx-textarea.is-localized .wx-token-button {\n right: var(--wx-space-40);\n}\n\n.wx-textarea.is-localized .wx-textarea__mirror {\n padding-right: var(--wx-space-40);\n}\n\n.wx-textarea.has-tokens .wx-textarea__inner,\n.wx-textarea.has-tokens .wx-textarea__mirror {\n padding-right: var(--wx-space-40);\n}\n\n.wx-textarea.has-tokens.is-localized .wx-textarea__inner,\n.wx-textarea.has-tokens.is-localized .wx-textarea__mirror {\n padding-right: var(--wx-space-64);\n}\n\n.wx-textarea__count {\n position: absolute;\n right: var(--wx-space-8);\n bottom: var(--wx-space-4);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n font-variant-numeric: tabular-nums;\n pointer-events: none;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport type { IconName } from '../Icon/types'\nimport type { ThemePreference, ThemeSwitchEmits, ThemeSwitchProps } from './types'\n\ndefineOptions({ name: 'WxThemeSwitch' })\n\n/**\n * Light, whatever the machine says, dark.\n *\n * It only reports the choice: applying it is `applyTheme()`'s job, and remembering it belongs\n * to whoever knows where this person's settings live. Three states rather than two because\n * \"follow the machine\" is a real answer and cannot be spelled with a toggle — a two-way\n * switch can only ever guess which side of it means \"I have not decided\".\n */\nconst props = withDefaults(defineProps<ThemeSwitchProps>(), {\n size: 'md',\n block: false,\n disabled: false,\n ariaLabel: 'Theme',\n lightLabel: 'Light',\n darkLabel: 'Dark',\n systemLabel: 'Follow the system',\n})\n\nconst emit = defineEmits<ThemeSwitchEmits>()\n\nconst model = defineModel<ThemePreference>({ default: 'system' })\n\ninterface Choice {\n value: ThemePreference\n icon: IconName\n label: string\n}\n\n// Day, the room's own answer, night — the order somebody would draw it in.\nconst choices = computed<Choice[]>(() => [\n { value: 'light', icon: 'sun', label: props.lightLabel },\n { value: 'system', icon: 'monitor', label: props.systemLabel },\n { value: 'dark', icon: 'moon', label: props.darkLabel },\n])\n\nconst index = computed(() => {\n const found = choices.value.findIndex((choice) => choice.value === model.value)\n\n return found === -1 ? 1 : found\n})\n\nconst buttons = ref<HTMLButtonElement[]>([])\n\nfunction choose(value: ThemePreference): void {\n if (props.disabled || value === model.value) {\n return\n }\n\n model.value = value\n emit('change', value)\n}\n\n/**\n * Arrow keys move the choice. A native radio group does this for free; a row of buttons\n * wearing `role=\"radio\"` has to be told, and without it the keyboard can reach the control\n * and then do nothing with it.\n */\nfunction onKeydown(event: KeyboardEvent): void {\n const step = { ArrowRight: 1, ArrowDown: 1, ArrowLeft: -1, ArrowUp: -1 }[event.key]\n\n if (step === undefined) {\n return\n }\n\n event.preventDefault()\n\n const next = (index.value + step + choices.value.length) % choices.value.length\n\n choose(choices.value[next]!.value)\n buttons.value[next]?.focus()\n}\n</script>\n\n<template>\n <div\n class=\"wx-theme-switch\"\n :class=\"[\n `wx-theme-switch--${size}`,\n { 'wx-theme-switch--block': block, 'is-disabled': disabled },\n ]\"\n :style=\"{ '--wx-theme-switch-index': index }\"\n :data-chosen=\"model\"\n role=\"radiogroup\"\n :aria-label=\"ariaLabel\"\n @keydown=\"onKeydown\"\n >\n <!-- The lit cell, which slides rather than jumps: the picture of a switch being thrown. -->\n <span class=\"wx-theme-switch__thumb\" aria-hidden=\"true\" />\n\n <button\n v-for=\"(choice, position) in choices\"\n :key=\"choice.value\"\n :ref=\"\n (element) => {\n if (element) buttons[position] = element as HTMLButtonElement\n }\n \"\n type=\"button\"\n role=\"radio\"\n class=\"wx-theme-switch__option\"\n :class=\"{ 'is-chosen': choice.value === model }\"\n :aria-checked=\"choice.value === model\"\n :aria-label=\"choice.label\"\n :title=\"choice.label\"\n :disabled=\"disabled\"\n :tabindex=\"choice.value === model ? 0 : -1\"\n @click=\"choose(choice.value)\"\n >\n <wx-icon\n :name=\"choice.icon\"\n class=\"wx-theme-switch__icon\"\n :class=\"`wx-theme-switch__icon--${choice.value}`\"\n />\n </button>\n </div>\n</template>\n\n<style scoped>\n.wx-theme-switch {\n position: relative;\n display: inline-flex;\n box-sizing: border-box;\n padding: 2px;\n background: var(--wx-bg-fill);\n border-radius: var(--wx-radius-full);\n font-family: var(--wx-font-family-sans);\n}\n\n.wx-theme-switch--block {\n display: flex;\n width: 100%;\n}\n\n.wx-theme-switch--sm {\n --wx-theme-switch-cell: calc(var(--wx-size-control-sm) - 4px);\n}\n\n.wx-theme-switch--md {\n --wx-theme-switch-cell: calc(var(--wx-size-control-md) - 4px);\n}\n\n.wx-theme-switch--lg {\n --wx-theme-switch-cell: calc(var(--wx-size-control-lg) - 4px);\n}\n\n.wx-theme-switch__thumb {\n position: absolute;\n inset-block: 2px;\n inset-inline-start: 2px;\n /* Three equal cells inside the track, whatever width the track was given. */\n width: calc((100% - 4px) / 3);\n border-radius: var(--wx-radius-full);\n /*\n * The tint over the surface rather than instead of it: in the dark theme the soft colours\n * are translucent, and laid straight on the track they would leave the thumb the same\n * colour as the groove it is supposed to be lifted out of.\n */\n background:\n linear-gradient(\n var(--wx-theme-switch-tint, transparent),\n var(--wx-theme-switch-tint, transparent)\n ),\n var(--wx-bg-surface);\n box-shadow: var(--wx-shadow-card);\n transform: translateX(calc(var(--wx-theme-switch-index, 1) * 100%));\n transition:\n transform var(--wx-duration-slow) var(--wx-easing-emphasized),\n background var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n/* Right to left the cells are drawn the other way round, and so is the slide. */\n[dir='rtl'] .wx-theme-switch__thumb {\n transform: translateX(calc(var(--wx-theme-switch-index, 1) * -100%));\n}\n\n.wx-theme-switch[data-chosen='light'] {\n --wx-theme-switch-tint: var(--wx-color-warning-soft);\n}\n\n.wx-theme-switch[data-chosen='dark'] {\n --wx-theme-switch-tint: var(--wx-color-primary-soft);\n}\n\n.wx-theme-switch__option {\n position: relative;\n display: inline-flex;\n flex: 1 1 0;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n min-width: var(--wx-theme-switch-cell);\n height: var(--wx-theme-switch-cell);\n padding: 0;\n border: none;\n border-radius: var(--wx-radius-full);\n background: transparent;\n color: var(--wx-text-muted);\n cursor: pointer;\n transition: color var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-theme-switch__option:hover:not(:disabled):not(.is-chosen) {\n color: var(--wx-text-default);\n}\n\n.wx-theme-switch__option:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-theme-switch__option:disabled {\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n.wx-theme-switch__icon {\n /* Drawn over the thumb, which is the element before it in the stack. */\n position: relative;\n flex: 0 0 auto;\n}\n\n/*\n * The chosen picture arrives rather than appears: the sun rises into place, the moon swings\n * in, the screen is set down. It runs on the class being added, so it plays again every time\n * the choice comes back round.\n */\n.is-chosen .wx-theme-switch__icon--light {\n color: var(--wx-color-warning);\n animation: wx-theme-switch-sun var(--wx-duration-slow) var(--wx-easing-emphasized);\n}\n\n.is-chosen .wx-theme-switch__icon--dark {\n color: var(--wx-color-primary);\n animation: wx-theme-switch-moon var(--wx-duration-slow) var(--wx-easing-emphasized);\n}\n\n.is-chosen .wx-theme-switch__icon--system {\n color: var(--wx-text-strong);\n animation: wx-theme-switch-monitor var(--wx-duration-slow) var(--wx-easing-emphasized);\n}\n\n@keyframes wx-theme-switch-sun {\n from {\n transform: rotate(-120deg) scale(0.4);\n }\n\n to {\n transform: none;\n }\n}\n\n@keyframes wx-theme-switch-moon {\n from {\n transform: rotate(45deg) scale(0.4);\n }\n\n to {\n transform: none;\n }\n}\n\n@keyframes wx-theme-switch-monitor {\n from {\n transform: translateY(4px) scale(0.7);\n }\n\n to {\n transform: none;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-theme-switch__thumb,\n .wx-theme-switch__option {\n transition: none;\n }\n\n .is-chosen .wx-theme-switch__icon {\n animation: none;\n }\n}\n</style>\n","import { inject, type ComputedRef, type InjectionKey } from 'vue'\n\nexport type TimelineSize = 'sm' | 'md'\n\n/** What `WxTimeline` hands down to the items inside it. */\nexport interface TimelineContext {\n size: ComputedRef<TimelineSize>\n}\n\nexport const timelineKey: InjectionKey<TimelineContext> = Symbol('wx-timeline')\n\nexport function useTimeline(): TimelineContext | null {\n return inject(timelineKey, null)\n}\n","<script setup lang=\"ts\">\nimport { computed, provide } from 'vue'\nimport { timelineKey } from '../../composables/useTimeline'\nimport type { TimelineProps } from './types'\n\ndefineOptions({ name: 'WxTimeline' })\n\nconst props = withDefaults(defineProps<TimelineProps>(), {\n size: 'md',\n})\n\nprovide(timelineKey, { size: computed(() => props.size) })\n</script>\n\n<template>\n <ul class=\"wx-timeline\" :class=\"`wx-timeline--${size}`\">\n <slot />\n </ul>\n</template>\n\n<style scoped>\n.wx-timeline {\n --wx-timeline-dot: 12px;\n --wx-timeline-gap: var(--wx-space-18);\n\n margin: 0;\n padding: 0;\n list-style: none;\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n}\n\n.wx-timeline--sm {\n --wx-timeline-dot: 9px;\n --wx-timeline-gap: var(--wx-space-12);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, useSlots } from 'vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport { useTimeline } from '../../composables/useTimeline'\nimport type { TimelineItemProps } from './types'\n\ndefineOptions({ name: 'WxTimelineItem' })\n\nconst props = withDefaults(defineProps<TimelineItemProps>(), {\n timestamp: undefined,\n datetime: undefined,\n timestampPlacement: 'top',\n title: undefined,\n type: 'default',\n hollow: false,\n icon: undefined,\n hideLine: false,\n})\n\nconst timeline = useTimeline()\nconst slots = useSlots()\n\nconst hasMark = computed(() => Boolean(props.icon || slots.dot))\n\nconst classes = computed(() => [\n 'wx-timeline-item',\n `wx-timeline-item--${timeline?.size.value ?? 'md'}`,\n {\n 'wx-timeline-item--no-line': props.hideLine,\n // A mark needs a bigger dot to sit in; the line and the indent follow it.\n 'wx-timeline-item--mark': hasMark.value,\n },\n])\n\nconst dotClasses = computed(() => [\n 'wx-timeline-item__dot',\n `wx-timeline-item__dot--${props.type}`,\n { 'wx-timeline-item__dot--hollow': props.hollow },\n])\n</script>\n\n<template>\n <li :class=\"classes\">\n <span class=\"wx-timeline-item__line\" aria-hidden=\"true\" />\n\n <span :class=\"dotClasses\" aria-hidden=\"true\">\n <slot name=\"dot\">\n <wx-icon v-if=\"icon\" :name=\"icon\" />\n </slot>\n </span>\n\n <div class=\"wx-timeline-item__content\">\n <time\n v-if=\"timestamp && timestampPlacement === 'top'\"\n class=\"wx-timeline-item__timestamp\"\n :datetime=\"datetime\"\n >\n {{ timestamp }}\n </time>\n\n <p v-if=\"title || $slots.title\" class=\"wx-timeline-item__title\">\n <slot name=\"title\">{{ title }}</slot>\n </p>\n\n <div v-if=\"$slots.default\" class=\"wx-timeline-item__body\">\n <slot />\n </div>\n\n <time\n v-if=\"timestamp && timestampPlacement === 'bottom'\"\n class=\"wx-timeline-item__timestamp wx-timeline-item__timestamp--bottom\"\n :datetime=\"datetime\"\n >\n {{ timestamp }}\n </time>\n </div>\n </li>\n</template>\n\n<style scoped>\n/*\n * Everything hangs off one vertical axis: the dot is centred on it, the line runs\n * down it, and the text starts a fixed gap to its right. Changing the dot size —\n * a small marker, or a 24px circle holding an icon — never moves the text.\n */\n.wx-timeline-item {\n --wx-timeline-axis: 12px;\n --wx-timeline-mark: var(--wx-timeline-dot, 12px);\n --wx-timeline-mark-top: 3px;\n\n position: relative;\n padding-left: calc(var(--wx-timeline-axis) + var(--wx-space-16));\n padding-bottom: var(--wx-timeline-gap, var(--wx-space-18));\n}\n\n.wx-timeline-item--sm {\n --wx-timeline-axis: 10px;\n}\n\n.wx-timeline-item--mark {\n --wx-timeline-mark: 24px;\n --wx-timeline-mark-top: 0px;\n}\n\n/* The last entry ends at its content: no trailing stub of line under it. */\n.wx-timeline-item:last-child {\n padding-bottom: 0;\n}\n\n.wx-timeline-item__line {\n position: absolute;\n top: calc(var(--wx-timeline-mark-top) + var(--wx-timeline-mark) + 4px);\n bottom: 0;\n left: calc(var(--wx-timeline-axis) - 0.5px);\n width: 1px;\n background: var(--wx-border-default);\n}\n\n.wx-timeline-item:last-child .wx-timeline-item__line,\n.wx-timeline-item--no-line .wx-timeline-item__line {\n display: none;\n}\n\n.wx-timeline-item__dot {\n position: absolute;\n top: var(--wx-timeline-mark-top);\n left: calc(var(--wx-timeline-axis) - var(--wx-timeline-mark) / 2);\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n width: var(--wx-timeline-mark);\n height: var(--wx-timeline-mark);\n background: var(--wx-timeline-dot-color, var(--wx-border-strong));\n border-radius: var(--wx-radius-full);\n color: var(--wx-timeline-dot-contrast, var(--wx-text-inverse));\n font-size: 14px;\n}\n\n.wx-timeline-item__dot--hollow {\n background: var(--wx-bg-surface);\n border: 2px solid var(--wx-timeline-dot-color, var(--wx-border-strong));\n color: var(--wx-timeline-dot-color, var(--wx-border-strong));\n}\n\n.wx-timeline-item__dot--default {\n --wx-timeline-dot-color: var(--wx-border-strong);\n --wx-timeline-dot-contrast: var(--wx-text-inverse);\n}\n\n.wx-timeline-item__dot--primary {\n --wx-timeline-dot-color: var(--wx-color-primary);\n --wx-timeline-dot-contrast: var(--wx-color-primary-contrast);\n}\n\n.wx-timeline-item__dot--success {\n --wx-timeline-dot-color: var(--wx-color-success);\n --wx-timeline-dot-contrast: var(--wx-color-success-contrast);\n}\n\n.wx-timeline-item__dot--warning {\n --wx-timeline-dot-color: var(--wx-color-warning);\n --wx-timeline-dot-contrast: var(--wx-color-warning-contrast);\n}\n\n.wx-timeline-item__dot--danger {\n --wx-timeline-dot-color: var(--wx-color-danger);\n --wx-timeline-dot-contrast: var(--wx-color-danger-contrast);\n}\n\n.wx-timeline-item__dot--info {\n --wx-timeline-dot-color: var(--wx-color-info);\n --wx-timeline-dot-contrast: var(--wx-color-info-contrast);\n}\n\n.wx-timeline-item__content {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.wx-timeline-item__timestamp {\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n line-height: var(--wx-font-line-height-normal);\n}\n\n.wx-timeline-item__timestamp--bottom {\n margin-top: var(--wx-space-4);\n}\n\n.wx-timeline-item__title {\n margin: 0;\n color: var(--wx-text-strong);\n font-size: var(--wx-font-size-md);\n font-weight: var(--wx-font-weight-semibold);\n line-height: var(--wx-font-line-height-tight);\n}\n\n.wx-timeline-item--sm .wx-timeline-item__title {\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-timeline-item__body {\n color: var(--wx-text-default);\n font-size: var(--wx-font-size-sm);\n line-height: var(--wx-font-line-height-normal);\n}\n</style>\n","<script setup lang=\"ts\">\nimport WxDatePicker from '../DatePicker/DatePicker.vue'\nimport type { DatePickerModelValue, DatePickerProps } from '../DatePicker/types'\n\ndefineOptions({ name: 'WxTimePicker' })\n\n/**\n * Every prop defaults to `undefined` on purpose. Vue casts an absent boolean prop\n * to `false`, and this preset forwards its whole prop object — without these the\n * preset would hand `WxDatePicker` an explicit `false` for `is24`, `clearable`,\n * `autoApply` and `teleport`, overriding that component's own defaults. Passing\n * `undefined` lets each default apply as if the prop had never been written.\n */\nwithDefaults(defineProps<Omit<DatePickerProps, 'type'>>(), {\n valueFormat: undefined,\n format: undefined,\n placeholder: undefined,\n clearable: undefined,\n minDate: undefined,\n maxDate: undefined,\n seconds: undefined,\n minutesIncrement: undefined,\n is24: undefined,\n locale: undefined,\n weekStart: undefined,\n autoApply: undefined,\n textInput: undefined,\n teleport: undefined,\n disabled: undefined,\n readonly: undefined,\n size: undefined,\n status: undefined,\n id: undefined,\n name: undefined,\n ariaLabel: undefined,\n})\n\n/*\n * Every slot is passed straight through to the picker underneath, so this component's\n * slots are whatever the caller hands it. Saying so explicitly is what keeps the\n * declaration honest: left to infer, the slot type is read off a template that\n * enumerates the slots themselves, and TypeScript answers that circle by emitting\n * `any`.\n */\ndefineSlots<Record<string, (props: Record<string, unknown>) => unknown>>()\n\nconst model = defineModel<DatePickerModelValue>({ default: null })\n</script>\n\n<template>\n <wx-date-picker v-model=\"model\" type=\"time\" v-bind=\"$props\">\n <template v-for=\"(_, name) in $slots\" #[name]=\"slotProps\">\n <slot :name=\"name\" v-bind=\"slotProps ?? {}\" />\n </template>\n </wx-date-picker>\n</template>\n","import { reactive, readonly, type DeepReadonly } from 'vue'\nimport type { IconName } from '../components/Icon/types'\n\nexport type ToastType = 'default' | 'success' | 'warning' | 'danger' | 'info'\n\nexport interface ToastAction {\n label: string\n onClick: () => void\n}\n\nexport interface ToastOptions {\n /** A headline. Without one the toast is a single line — a message rather than a card. */\n title?: string\n /** The message. This is what a one-line toast says. */\n description?: string\n type?: ToastType\n /**\n * How long it stays, in milliseconds. `0` keeps it until it is dismissed, which is\n * what an error the reader has to act on wants.\n */\n duration?: number\n /** Adds a ×. On by default for anything that does not leave on its own. */\n closable?: boolean\n /** Glyph to draw instead of the one the type picks; `false` drops it. */\n icon?: IconName | false\n /** One thing to do about it: Undo, Retry, View. */\n action?: ToastAction\n}\n\nexport interface ToastRecord extends ToastOptions {\n id: number\n /** Bound to the panel; set to false to start it leaving. */\n open: boolean\n}\n\nexport interface ToastHandle {\n id: number\n dismiss: () => void\n}\n\n/**\n * The queue, outside any component.\n *\n * That is the point of it: a toast is usually raised from somewhere with no view of\n * its own — an HTTP interceptor, a store, a catch block — and asking those places to\n * find a component instance first is how a notification system ends up being passed\n * down through props. One queue per bundle, one `WxToaster` on the page to show it.\n */\nconst queue = reactive<ToastRecord[]>([])\n\nlet nextId = 0\n\n/*\n * How long a toast is given to leave before its record is dropped. It is a timer\n * rather than an `animationend`, because a reader who has asked for reduced motion\n * gets no animation and would otherwise be left with a queue that never empties.\n */\nconst LEAVING_MS = 220\n\n/** What the `WxToaster` renders. Nothing else should be writing to it. */\nexport function toastQueue(): DeepReadonly<ToastRecord[]> {\n return readonly(queue) as DeepReadonly<ToastRecord[]>\n}\n\n/** Starts a toast leaving. It is taken off the queue once it has gone. */\nexport function dismissToast(id: number) {\n const found = queue.find((toast) => toast.id === id)\n if (!found || !found.open) return\n\n found.open = false\n setTimeout(() => removeToast(id), LEAVING_MS)\n}\n\n/** Takes a toast off the queue for good — called when its animation has finished. */\nexport function removeToast(id: number) {\n const index = queue.findIndex((toast) => toast.id === id)\n if (index !== -1) queue.splice(index, 1)\n}\n\n/** Clears everything on screen at once. */\nexport function clearToasts() {\n for (const toast of [...queue]) dismissToast(toast.id)\n}\n\nfunction raise(options: ToastOptions): ToastHandle {\n const id = (nextId += 1)\n\n queue.push({\n type: 'default',\n duration: 5000,\n closable: true,\n ...options,\n id,\n open: true,\n })\n\n return { id, dismiss: () => dismissToast(id) }\n}\n\n/** A toast is either a message or an options bag; both reach the same queue. */\nfunction normalise(input: string | ToastOptions, extra: ToastOptions = {}): ToastOptions {\n return typeof input === 'string' ? { description: input, ...extra } : { ...input, ...extra }\n}\n\nexport interface ToastApi {\n (message: string | ToastOptions, options?: ToastOptions): ToastHandle\n success: (message: string | ToastOptions, options?: ToastOptions) => ToastHandle\n warning: (message: string | ToastOptions, options?: ToastOptions) => ToastHandle\n danger: (message: string | ToastOptions, options?: ToastOptions) => ToastHandle\n info: (message: string | ToastOptions, options?: ToastOptions) => ToastHandle\n dismiss: (id: number) => void\n clear: () => void\n}\n\nconst api = ((message: string | ToastOptions, options: ToastOptions = {}) =>\n raise(normalise(message, options))) as ToastApi\n\napi.success = (message, options = {}) => raise(normalise(message, { type: 'success', ...options }))\napi.warning = (message, options = {}) => raise(normalise(message, { type: 'warning', ...options }))\napi.danger = (message, options = {}) =>\n /* An error that vanishes on its own is an error nobody read. */\n raise(normalise(message, { type: 'danger', duration: 0, ...options }))\napi.info = (message, options = {}) => raise(normalise(message, { type: 'info', ...options }))\napi.dismiss = dismissToast\napi.clear = clearToasts\n\n/**\n * Raises a toast from anywhere.\n *\n * ```ts\n * const toast = useToast()\n * toast.success('Saved')\n * toast.danger({ title: 'Could not save', description: response.message })\n * ```\n *\n * The same object is importable as `toast` for code that is not in a component at\n * all — an interceptor, say. Put one `<wx-toaster />` on the page to show them.\n */\nexport function useToast(): ToastApi {\n return api\n}\n\nexport { api as toast }\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport {\n ToastAction,\n ToastClose,\n ToastDescription,\n ToastProvider,\n ToastRoot,\n ToastTitle,\n ToastViewport,\n} from 'reka-ui'\nimport WxIcon from '../Icon/Icon.vue'\nimport type { IconName } from '../Icon/types'\nimport { dismissToast, toastQueue, type ToastType } from '../../composables/useToast'\nimport type { ToasterProps } from './types'\n\ndefineOptions({ name: 'WxToaster' })\n\n/*\n * The one component that shows the queue. Put it once, at the root of the app: it\n * renders nothing of its own until something is raised, and having two of them means\n * every toast appears twice.\n */\nconst props = withDefaults(defineProps<ToasterProps>(), {\n placement: 'bottom-end',\n width: 380,\n label: 'Notifications',\n max: 5,\n hotkey: () => ['F8'],\n})\n\nconst GLYPH: Record<ToastType, IconName> = {\n default: 'info',\n success: 'check-circle',\n warning: 'warning',\n danger: 'close-circle',\n info: 'info',\n}\n\n/*\n * `setTimeout` turns `Infinity` into zero, so a toast asked to stay forever would\n * leave at once. The largest delay a timer actually honours is the way to say never.\n */\nconst FOREVER = 2_147_483_647\n\nconst queue = toastQueue()\n\n/* The oldest are shown; anything past the limit waits for room. */\nconst shown = computed(() => (props.max > 0 ? queue.slice(0, props.max) : queue))\n\nconst width = computed(() => (typeof props.width === 'number' ? `${props.width}px` : props.width))\n\nfunction iconOf(type: ToastType | undefined, icon: IconName | false | undefined) {\n if (icon === false) return undefined\n return icon ?? GLYPH[type ?? 'default']\n}\n</script>\n\n<template>\n <toast-provider :label=\"label\" :swipe-direction=\"placement.endsWith('start') ? 'left' : 'right'\">\n <toast-root\n v-for=\"item in shown\"\n :key=\"item.id\"\n class=\"wx-toast\"\n :class=\"`wx-toast--${item.type ?? 'default'}`\"\n :open=\"item.open\"\n :duration=\"item.duration === 0 ? FOREVER : item.duration\"\n :style=\"{ '--wx-toast-width': width }\"\n :aria-live=\"item.type === 'danger' ? 'assertive' : 'polite'\"\n @update:open=\"(open: boolean) => !open && dismissToast(item.id)\"\n @escape-key-down=\"dismissToast(item.id)\"\n >\n <div class=\"wx-toast__body\">\n <wx-icon\n v-if=\"iconOf(item.type, item.icon)\"\n class=\"wx-toast__icon\"\n :name=\"iconOf(item.type, item.icon)!\"\n />\n\n <div class=\"wx-toast__text\">\n <toast-title v-if=\"item.title\" class=\"wx-toast__title\">{{ item.title }}</toast-title>\n <toast-description v-if=\"item.description\" class=\"wx-toast__description\">\n {{ item.description }}\n </toast-description>\n </div>\n\n <toast-action\n v-if=\"item.action\"\n class=\"wx-toast__action\"\n :alt-text=\"item.action.label\"\n @click=\"item.action.onClick()\"\n >\n {{ item.action.label }}\n </toast-action>\n\n <toast-close v-if=\"item.closable\" class=\"wx-toast__close\" aria-label=\"Dismiss\">\n <wx-icon name=\"close\" />\n </toast-close>\n </div>\n </toast-root>\n\n <toast-viewport\n class=\"wx-toaster\"\n :class=\"`wx-toaster--${placement}`\"\n :hotkey=\"hotkey\"\n :label=\"label\"\n />\n </toast-provider>\n</template>\n\n<style>\n/* Teleported by Reka, so the styles cannot be scoped to the component. */\n.wx-toaster {\n position: fixed;\n z-index: var(--wx-z-index-toast);\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n box-sizing: border-box;\n max-width: 100vw;\n margin: 0;\n padding: var(--wx-space-16);\n list-style: none;\n /* The region is a hole in the page: only the toasts in it take a click. */\n pointer-events: none;\n}\n\n.wx-toaster > * {\n pointer-events: auto;\n}\n\n.wx-toaster--top-start {\n top: 0;\n inset-inline-start: 0;\n}\n\n.wx-toaster--top-center {\n top: 0;\n left: 50%;\n transform: translateX(-50%);\n}\n\n.wx-toaster--top-end {\n top: 0;\n inset-inline-end: 0;\n}\n\n.wx-toaster--bottom-start {\n bottom: 0;\n inset-inline-start: 0;\n flex-direction: column-reverse;\n}\n\n.wx-toaster--bottom-center {\n bottom: 0;\n left: 50%;\n transform: translateX(-50%);\n flex-direction: column-reverse;\n}\n\n.wx-toaster--bottom-end {\n bottom: 0;\n inset-inline-end: 0;\n flex-direction: column-reverse;\n}\n\n.wx-toast {\n --wx-toast-accent: var(--wx-text-muted);\n\n box-sizing: border-box;\n width: var(--wx-toast-width, 380px);\n max-width: calc(100vw - var(--wx-space-32));\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-sm);\n box-shadow: var(--wx-shadow-popover);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n}\n\n.wx-toast--success {\n --wx-toast-accent: var(--wx-color-success-active);\n}\n\n.wx-toast--warning {\n --wx-toast-accent: var(--wx-color-warning-active);\n}\n\n.wx-toast--danger {\n --wx-toast-accent: var(--wx-color-danger);\n}\n\n.wx-toast--info {\n --wx-toast-accent: var(--wx-color-info-active);\n}\n\n.wx-toast__body {\n display: flex;\n align-items: flex-start;\n gap: var(--wx-space-8);\n padding: var(--wx-space-12);\n}\n\n.wx-toast__icon {\n flex: 0 0 auto;\n margin-top: 1px;\n color: var(--wx-toast-accent);\n}\n\n.wx-toast__text {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.wx-toast__title {\n margin: 0;\n font-size: var(--wx-font-size-sm);\n font-weight: var(--wx-font-weight-semibold);\n line-height: var(--wx-font-line-height-tight);\n}\n\n.wx-toast__description {\n margin: 0;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n line-height: var(--wx-font-line-height-normal);\n}\n\n/* With a title above it the message is the second line, and indents under it. */\n.wx-toast__title + .wx-toast__description {\n margin-top: 2px;\n}\n\n.wx-toast__action {\n flex: 0 0 auto;\n align-self: center;\n padding: var(--wx-space-4) var(--wx-space-8);\n background: transparent;\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-xs);\n color: var(--wx-text-default);\n font: inherit;\n font-size: var(--wx-font-size-xs);\n font-weight: var(--wx-font-weight-medium);\n cursor: pointer;\n}\n\n.wx-toast__action:hover {\n background: var(--wx-bg-fill);\n}\n\n.wx-toast__close {\n display: inline-flex;\n flex: 0 0 auto;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n padding: 0;\n background: transparent;\n border: none;\n border-radius: var(--wx-radius-xs);\n color: var(--wx-text-muted);\n cursor: pointer;\n}\n\n.wx-toast__close:hover {\n background: var(--wx-bg-fill);\n color: var(--wx-text-default);\n}\n\n.wx-toast__close:focus-visible,\n.wx-toast__action:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-toast[data-state='open'] .wx-toast__body {\n animation: wx-toast-in var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-toast[data-state='closed'] .wx-toast__body {\n animation: wx-toast-out var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-toast[data-swipe='move'] {\n transform: translateX(var(--reka-toast-swipe-move-x));\n}\n\n.wx-toast[data-swipe='end'] {\n animation: wx-toast-out var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n@keyframes wx-toast-in {\n from {\n opacity: 0;\n transform: translateY(8px);\n }\n\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes wx-toast-out {\n from {\n opacity: 1;\n }\n\n to {\n opacity: 0;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-toast .wx-toast__body {\n animation: none;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, reactive, ref } from 'vue'\nimport WxButton from '../Button/Button.vue'\nimport WxCheckbox from '../Checkbox/Checkbox.vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport WxInput from '../Input/Input.vue'\nimport { cssLength } from '../../composables/useOverlayPanel'\nimport type {\n TransferEmits,\n TransferItem,\n TransferProps,\n TransferSide,\n TransferValue,\n} from './types'\n\ndefineOptions({ name: 'WxTransfer' })\n\nconst props = withDefaults(defineProps<TransferProps>(), {\n items: () => [],\n titles: () => ['Available', 'Selected'],\n searchable: false,\n searchPlaceholder: 'Search',\n height: 260,\n emptyText: 'Nothing here',\n size: 'md',\n disabled: false,\n toRightLabel: 'Move to the right',\n toLeftLabel: 'Move to the left',\n})\n\nconst emit = defineEmits<TransferEmits>()\n\ndefineSlots<{\n /** One row, on either side. */\n item?: (props: { item: TransferItem; side: TransferSide }) => unknown\n /** Shown in a panel with nothing in it. */\n empty?: (props: { side: TransferSide }) => unknown\n}>()\n\n/** The values on the right. The left is everything else, which is why it is not a prop. */\nconst model = defineModel<TransferValue[]>({ default: () => [] })\n\nconst sides = ['left', 'right'] as const\n\nconst query = reactive<Record<TransferSide, string>>({ left: '', right: '' })\n\nconst ticked = reactive<Record<TransferSide, TransferValue[]>>({ left: [], right: [] })\n\nconst announcement = ref('')\n\nconst byValue = computed(() => new Map(props.items.map((item) => [item.value, item])))\n\nconst chosen = computed(() => new Set(model.value))\n\n/*\n * The right panel is in the model's order rather than the catalogue's: the model is an array, the\n * order in it is the order it will be saved in, and a panel that showed it in some other order\n * would be quietly lying about what is being saved.\n */\nconst panels = computed<Record<TransferSide, TransferItem[]>>(() => ({\n left: props.items.filter((item) => !chosen.value.has(item.value)),\n right: model.value\n .map((value) => byValue.value.get(value))\n .filter((item): item is TransferItem => Boolean(item)),\n}))\n\nfunction matches(item: TransferItem, text: string) {\n const needle = text.trim().toLowerCase()\n if (!needle) return true\n return `${item.label ?? ''} ${item.description ?? ''} ${item.value}`\n .toLowerCase()\n .includes(needle)\n}\n\nconst visible = computed<Record<TransferSide, TransferItem[]>>(() => ({\n left: panels.value.left.filter((item) => matches(item, query.left)),\n right: panels.value.right.filter((item) => matches(item, query.right)),\n}))\n\nconst tickedSet = computed<Record<TransferSide, Set<TransferValue>>>(() => ({\n left: new Set(ticked.left),\n right: new Set(ticked.right),\n}))\n\nfunction movable(side: TransferSide) {\n return panels.value[side].filter(\n (item) => !item.disabled && tickedSet.value[side].has(item.value),\n )\n}\n\nfunction pickable(side: TransferSide) {\n return visible.value[side].filter((item) => !item.disabled)\n}\n\nfunction allTicked(side: TransferSide) {\n const rows = pickable(side)\n return rows.length > 0 && rows.every((item) => tickedSet.value[side].has(item.value))\n}\n\nfunction someTicked(side: TransferSide) {\n return !allTicked(side) && pickable(side).some((item) => tickedSet.value[side].has(item.value))\n}\n\nfunction labelOf(item: TransferItem) {\n return item.label ?? String(item.value)\n}\n\nfunction tick(side: TransferSide, value: TransferValue, on: boolean) {\n ticked[side] = on ? [...ticked[side], value] : ticked[side].filter((held) => held !== value)\n}\n\n/** The heading's checkbox takes the rows a search has left showing, and only those. */\nfunction tickAll(side: TransferSide, on: boolean) {\n const rows = pickable(side).map((item) => item.value)\n const shown = new Set(rows)\n ticked[side] = on\n ? [...ticked[side].filter((value) => !shown.has(value)), ...rows]\n : ticked[side].filter((value) => !shown.has(value))\n}\n\nfunction send(side: TransferSide, values: TransferValue[]) {\n if (!values.length) return\n\n const moving = new Set(values)\n model.value =\n side === 'right'\n ? [...model.value, ...values]\n : model.value.filter((value) => !moving.has(value))\n\n /* What has moved is no longer ticked: it is somewhere else now, and unticked there. */\n const from: TransferSide = side === 'right' ? 'left' : 'right'\n ticked[from] = ticked[from].filter((value) => !moving.has(value))\n\n emit('change', { values, to: side })\n announcement.value = `${values.length} moved to ${props.titles[side === 'right' ? 1 : 0]}.`\n}\n\nfunction move(to: TransferSide) {\n if (props.disabled) return\n send(\n to,\n movable(to === 'right' ? 'left' : 'right').map((item) => item.value),\n )\n}\n\n/** A double-click is the shortcut for one row, and the reason the buttons are not the only way. */\nfunction moveOne(side: TransferSide, item: TransferItem) {\n if (props.disabled || item.disabled) return\n send(side === 'left' ? 'right' : 'left', [item.value])\n}\n\nconst listStyle = computed(() => ({ height: cssLength(props.height) }))\n\nconst classes = computed(() => [\n 'wx-transfer',\n `wx-transfer--${props.size}`,\n { 'is-disabled': props.disabled },\n])\n</script>\n\n<template>\n <div :class=\"classes\">\n <div class=\"wx-transfer__grid\">\n <template v-for=\"(side, index) in sides\" :key=\"side\">\n <section class=\"wx-transfer__panel\">\n <header class=\"wx-transfer__head\">\n <wx-checkbox\n :model-value=\"allTicked(side)\"\n :indeterminate=\"someTicked(side)\"\n :disabled=\"disabled || !pickable(side).length\"\n :size=\"size\"\n :aria-label=\"`Tick everything in ${titles[index]}`\"\n @update:model-value=\"tickAll(side, $event)\"\n />\n <span class=\"wx-transfer__title\">{{ titles[index] }}</span>\n <span class=\"wx-transfer__count\">\n {{ ticked[side].length }}/{{ panels[side].length }}\n </span>\n </header>\n\n <div v-if=\"searchable\" class=\"wx-transfer__search\">\n <wx-input\n v-model=\"query[side]\"\n type=\"search\"\n size=\"sm\"\n clearable\n :disabled=\"disabled\"\n :placeholder=\"searchPlaceholder\"\n :aria-label=\"`Search ${titles[index]}`\"\n />\n </div>\n\n <ul class=\"wx-transfer__list\" :style=\"listStyle\">\n <li\n v-for=\"item in visible[side]\"\n :key=\"item.value\"\n class=\"wx-transfer__item\"\n :class=\"{ 'is-disabled': item.disabled }\"\n @dblclick=\"moveOne(side, item)\"\n >\n <wx-checkbox\n :model-value=\"tickedSet[side].has(item.value)\"\n :disabled=\"disabled || item.disabled\"\n :size=\"size\"\n @update:model-value=\"tick(side, item.value, $event)\"\n >\n <slot name=\"item\" :item=\"item\" :side=\"side\">\n <span class=\"wx-transfer__label\">{{ labelOf(item) }}</span>\n <span v-if=\"item.description\" class=\"wx-transfer__description\">\n {{ item.description }}\n </span>\n </slot>\n </wx-checkbox>\n </li>\n\n <li v-if=\"!visible[side].length\" class=\"wx-transfer__empty\">\n <slot name=\"empty\" :side=\"side\">{{ emptyText }}</slot>\n </li>\n </ul>\n </section>\n\n <div v-if=\"index === 0\" class=\"wx-transfer__controls\">\n <wx-button\n variant=\"outline\"\n :size=\"size\"\n :disabled=\"disabled || !movable('left').length\"\n :aria-label=\"toRightLabel\"\n @click=\"move('right')\"\n >\n <wx-icon name=\"chevron-right\" />\n </wx-button>\n <wx-button\n variant=\"outline\"\n :size=\"size\"\n :disabled=\"disabled || !movable('right').length\"\n :aria-label=\"toLeftLabel\"\n @click=\"move('left')\"\n >\n <wx-icon name=\"chevron-left\" />\n </wx-button>\n </div>\n </template>\n </div>\n\n <!-- What a move says out loud. -->\n <div class=\"wx-transfer__live\" role=\"status\" aria-live=\"polite\">{{ announcement }}</div>\n </div>\n</template>\n\n<style scoped>\n.wx-transfer {\n box-sizing: border-box;\n position: relative;\n /*\n * The container is this element and the grid is inside it, because a container query cannot\n * style the container it is measuring — the columns have to belong to something the query can\n * reach.\n */\n container-type: inline-size;\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n}\n\n.wx-transfer__grid {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n align-items: stretch;\n gap: var(--wx-space-12);\n}\n\n.wx-transfer__panel {\n display: flex;\n flex-direction: column;\n min-width: 0;\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-muted);\n border-radius: var(--wx-radius-md);\n overflow: hidden;\n}\n\n.wx-transfer__head {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n padding: var(--wx-space-8) var(--wx-space-12);\n background: var(--wx-bg-subtle);\n border-bottom: 1px solid var(--wx-border-muted);\n}\n\n.wx-transfer__title {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n color: var(--wx-text-strong);\n font-size: var(--wx-font-size-sm);\n font-weight: var(--wx-font-weight-medium);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wx-transfer__count {\n flex: 0 0 auto;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n font-variant-numeric: tabular-nums;\n}\n\n.wx-transfer__search {\n padding: var(--wx-space-8) var(--wx-space-8) 0;\n}\n\n.wx-transfer__list {\n margin: 0;\n padding: var(--wx-space-8);\n overflow-y: auto;\n list-style: none;\n}\n\n.wx-transfer__item {\n margin: 0;\n padding: var(--wx-space-4) var(--wx-space-6);\n border-radius: var(--wx-radius-xs);\n /* A double-click moves the row, and a selection is not what a double-click should leave. */\n user-select: none;\n}\n\n.wx-transfer__item:hover:not(.is-disabled) {\n background: var(--wx-bg-fill);\n}\n\n.wx-transfer__item.is-disabled {\n opacity: 0.55;\n}\n\n.wx-transfer__label {\n display: block;\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-transfer__description {\n display: block;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n line-height: var(--wx-font-line-height-normal);\n}\n\n.wx-transfer__empty {\n margin: 0;\n padding: var(--wx-space-16) var(--wx-space-8);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n text-align: center;\n}\n\n.wx-transfer__controls {\n display: flex;\n flex-direction: column;\n align-self: center;\n gap: var(--wx-space-8);\n}\n\n/*\n * Side by side is the whole point of this component — two lists you can compare — so it is the\n * panel's own width that decides when there is no longer room for it, not the window's.\n */\n@container (max-width: 520px) {\n .wx-transfer__grid {\n grid-template-columns: 1fr;\n }\n\n .wx-transfer__controls {\n flex-direction: row;\n justify-content: center;\n }\n\n /* The arrows point the way the panels now lie. */\n .wx-transfer__controls :deep(.wx-icon) {\n transform: rotate(90deg);\n }\n}\n\n/* Read out, never drawn. */\n.wx-transfer__live {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n border: 0;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n</style>\n","<script setup lang=\"ts\" generic=\"T extends TreeNode\">\nimport { computed, nextTick, onBeforeUnmount, ref, useTemplateRef } from 'vue'\nimport WxCheckbox from '../Checkbox/Checkbox.vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport {\n useTreeNodes,\n type TreeAccessors,\n type TreeDropZone,\n type TreeKey,\n type TreeRow,\n} from '../../composables/useTreeNodes'\nimport type { TreeEmits, TreeNode, TreeProps } from './types'\n\ndefineOptions({ name: 'WxTree' })\n\nconst props = withDefaults(defineProps<TreeProps<T>>(), {\n nodeKey: 'id',\n labelKey: 'label',\n childrenKey: 'children',\n disabledKey: 'disabled',\n leafKey: 'leaf',\n defaultExpandAll: false,\n accordion: false,\n expandOnClick: false,\n checkable: false,\n checkStrictly: false,\n draggable: false,\n allowDrag: undefined,\n allowDrop: undefined,\n springDelay: 600,\n lazy: false,\n load: undefined,\n filter: undefined,\n showLines: true,\n indent: 16,\n size: 'md',\n emptyText: 'Nothing here yet',\n dragLabel: 'Move',\n expandLabel: 'Expand',\n collapseLabel: 'Collapse',\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<TreeEmits<T>>()\n\ndefineSlots<{\n /** One node's label. Without it the tree reads `labelKey` and highlights the filter. */\n default?: (props: { node: T; depth: number; expanded: boolean; selected: boolean }) => unknown\n /** The end of a row, where the buttons that act on it go. */\n actions?: (props: { node: T; depth: number }) => unknown\n /** Shown in place of an empty tree. */\n empty?: () => unknown\n}>()\n\nconst model = defineModel<T[]>({ default: () => [] })\nconst expandedKeys = defineModel<TreeKey[]>('expanded', { default: () => [] })\nconst selectedKey = defineModel<TreeKey | null>('selected', { default: null })\nconst checkedKeys = defineModel<TreeKey[]>('checked', { default: () => [] })\n\nconst root = useTemplateRef<HTMLElement>('root')\n\n/*\n * Every field is a prop, so the tree reads the records the backend already sends —\n * `{ id, title, children }` — instead of asking the caller to rename them first. The\n * path is the last resort for identity: enough to render and to open, too weak to\n * survive a move, which is why a real key is worth naming.\n */\nconst accessors: TreeAccessors<T> = {\n key: (node, path) => (node[props.nodeKey] ?? node.key ?? path.join('.')) as TreeKey,\n children: (node) => node[props.childrenKey] as T[] | undefined,\n setChildren: (node, children) => {\n ;(node as Record<string, unknown>)[props.childrenKey] = children\n },\n label: (node) => String(node[props.labelKey] ?? ''),\n disabled: (node) => Boolean(node[props.disabledKey]),\n leaf: (node) => Boolean(node[props.leafKey]),\n}\n\nconst tree = useTreeNodes<T>({\n nodes: model,\n accessors,\n expanded: expandedKeys,\n filter: () => props.filter,\n accordion: () => props.accordion,\n lazy: () => props.lazy,\n load: (node) => props.load?.(node) ?? [],\n allowDrop: (drag, drop, zone) => props.allowDrop?.(drag, drop, zone) ?? true,\n})\n\nconst rows = tree.rows\n\nif (props.defaultExpandAll) tree.expandAll()\n\nconst classes = computed(() => [\n 'wx-tree',\n `wx-tree--${props.size}`,\n { 'is-lined': props.showLines, 'is-draggable': props.draggable },\n])\n\n/* ---------------------------------------------------------------------------\n * Selecting and checking\n * ------------------------------------------------------------------------- */\n\nconst checkedSet = computed(() => new Set(checkedKeys.value))\n\n/*\n * A branch is half-checked when something below it is checked and it is not. Working\n * down from the checked keys costs a walk up per checked node; asking every row about\n * its descendants instead would cost a walk down per row, on every render.\n */\nconst halfChecked = computed(() => {\n const out = new Set<TreeKey>()\n if (props.checkStrictly) return out\n for (const key of checkedSet.value) {\n for (const parent of tree.ancestors(key)) {\n if (!checkedSet.value.has(parent.key)) out.add(parent.key)\n }\n }\n return out\n})\n\nfunction select(row: TreeRow<T>) {\n if (row.disabled) return\n\n selectedKey.value = row.key\n emit('select', row.node, row.key)\n\n if (props.expandOnClick && row.expandable) void tree.toggle(row.key)\n}\n\nfunction onClick(row: TreeRow<T>, event: MouseEvent) {\n emit('node-click', row.node, event)\n select(row)\n}\n\nfunction onCheck(row: TreeRow<T>, checked: boolean) {\n const next = new Set(checkedKeys.value)\n const apply = (key: TreeKey, on: boolean) => (on ? next.add(key) : next.delete(key))\n\n apply(row.key, checked)\n\n if (!props.checkStrictly) {\n for (const child of tree.descendants(row.key)) {\n if (!accessors.disabled?.(child.node)) apply(child.key, checked)\n }\n // Upwards, nearest first: a parent is checked exactly when all its children are,\n // and each answer is the input to the question one level higher.\n for (const parent of [...tree.ancestors(row.key)].reverse()) {\n const children = parent.children.map((node) => tree.keyOf(node))\n apply(parent.key, children.length > 0 && children.every((key) => next.has(key)))\n }\n }\n\n checkedKeys.value = [...next]\n emit('check', checkedKeys.value, { node: row.node, checked })\n}\n\nasync function toggle(row: TreeRow<T>) {\n const open = row.expanded\n await tree.toggle(row.key)\n if (open) emit('collapse', row.node)\n else emit('expand', row.node)\n}\n\n/* ---------------------------------------------------------------------------\n * Filter highlighting\n * ------------------------------------------------------------------------- */\n\n/** The label cut into the part before the match, the match, and the rest. */\nfunction parts(row: TreeRow<T>) {\n const label = accessors.label?.(row.node) ?? ''\n const term = props.filter?.trim()\n if (!term || !row.matched) return { before: label, hit: '', after: '' }\n\n const at = label.toLowerCase().indexOf(term.toLowerCase())\n if (at < 0) return { before: label, hit: '', after: '' }\n\n return {\n before: label.slice(0, at),\n hit: label.slice(at, at + term.length),\n after: label.slice(at + term.length),\n }\n}\n\n/* ---------------------------------------------------------------------------\n * Moving\n * ------------------------------------------------------------------------- */\n\nconst announcement = ref('')\n\nconst canDrag = (row: TreeRow<T>) =>\n props.draggable && !row.disabled && (props.allowDrag?.(row.node) ?? true)\n\nfunction commit(\n dragKey: TreeKey,\n dropKey: TreeKey,\n zone: TreeDropZone,\n via: 'pointer' | 'keyboard',\n) {\n const target = tree.entry(dropKey)\n const landed = tree.move(dragKey, dropKey, zone)\n if (!landed || !target) return false\n\n emit('drop', {\n node: landed.node,\n target: target.node,\n zone,\n parent: landed.parent,\n index: landed.index,\n via,\n })\n return true\n}\n\n/* ------------------------------------------------------------------ pointer */\n\nconst dragKey = ref<TreeKey | null>(null)\nconst dropKey = ref<TreeKey | null>(null)\nconst dropZone = ref<TreeDropZone | null>(null)\n\n/** The branch a node is hovering over, and the timer that will open it. */\nlet springKey: TreeKey | null = null\nlet springTimer: ReturnType<typeof setTimeout> | undefined\n\nfunction cancelSpring() {\n if (springTimer) clearTimeout(springTimer)\n springTimer = undefined\n springKey = null\n}\n\n/**\n * Dropping into a branch nobody can see the inside of is a guess. Holding a node over a\n * closed one opens it — and fetches it, where the children are not in yet — so the guess\n * becomes a look, and a move across the tree is one drag rather than three.\n */\nfunction spring(row: TreeRow<T>, zone: TreeDropZone) {\n if (!props.springDelay || zone !== 'inside' || !row.expandable || row.expanded) {\n cancelSpring()\n return\n }\n /* Already counting down on this branch: restarting the clock would never finish. */\n if (springKey === row.key) return\n\n cancelSpring()\n springKey = row.key\n springTimer = setTimeout(() => {\n void tree.expand(row.key)\n emit('expand', row.node)\n cancelSpring()\n }, props.springDelay)\n}\n\nfunction onDragStart(row: TreeRow<T>, event: DragEvent) {\n if (!canDrag(row)) {\n event.preventDefault()\n return\n }\n dragKey.value = row.key\n event.dataTransfer?.setData('text/plain', String(row.key))\n if (event.dataTransfer) event.dataTransfer.effectAllowed = 'move'\n}\n\n/**\n * Which third of the row the pointer is over decides the landing: the edges put the node\n * beside the one under the pointer, the middle puts it inside. A leaf accepts the middle\n * too — that is how a leaf becomes a branch.\n */\nfunction zoneAt(event: DragEvent, element: HTMLElement): TreeDropZone {\n const box = element.getBoundingClientRect()\n const y = (event.clientY - box.top) / box.height\n if (y <= 0.3) return 'before'\n if (y >= 0.7) return 'after'\n return 'inside'\n}\n\nfunction onDragOver(row: TreeRow<T>, event: DragEvent) {\n if (dragKey.value === null) return\n\n const zone = zoneAt(event, event.currentTarget as HTMLElement)\n if (!tree.canDrop(dragKey.value, row.key, zone)) {\n dropKey.value = null\n dropZone.value = null\n cancelSpring()\n return\n }\n\n // Taking the event is what tells the browser this is a valid drop target.\n event.preventDefault()\n if (event.dataTransfer) event.dataTransfer.dropEffect = 'move'\n dropKey.value = row.key\n dropZone.value = zone\n spring(row, zone)\n}\n\nfunction onDrop(row: TreeRow<T>) {\n if (dragKey.value === null || dropZone.value === null || dropKey.value !== row.key) return\n commit(dragKey.value, row.key, dropZone.value, 'pointer')\n onDragEnd()\n}\n\nonBeforeUnmount(cancelSpring)\n\nfunction onDragEnd() {\n cancelSpring()\n dragKey.value = null\n dropKey.value = null\n dropZone.value = null\n}\n\n/* ----------------------------------------------------------------- keyboard */\n\n/**\n * The same four moves without a mouse. `Alt` is what separates them from plain arrow\n * navigation, and the announcement is what a screen reader gets instead of the\n * animation a sighted user sees.\n */\nfunction keyboardMove(row: TreeRow<T>, key: string) {\n if (!canDrag(row)) return false\n\n const siblings = row.siblings\n const at = row.index\n const name = accessors.label?.(row.node) ?? String(row.key)\n\n const say = (text: string) => {\n announcement.value = text\n void refocus(row.key)\n }\n\n if (key === 'ArrowUp' && at > 0) {\n if (!commit(row.key, tree.keyOf(siblings[at - 1]!, [at - 1]), 'before', 'keyboard'))\n return false\n say(`${name} is now ${at} of ${siblings.length}.`)\n return true\n }\n\n if (key === 'ArrowDown' && at < siblings.length - 1) {\n if (!commit(row.key, tree.keyOf(siblings[at + 1]!, [at + 1]), 'after', 'keyboard')) return false\n say(`${name} is now ${at + 2} of ${siblings.length}.`)\n return true\n }\n\n // Right nests under the node above, which is the only place a node can go down a\n // level without choosing between two parents.\n if (key === 'ArrowRight' && at > 0) {\n const parent = siblings[at - 1]!\n if (!commit(row.key, tree.keyOf(parent, [at - 1]), 'inside', 'keyboard')) return false\n say(`${name} is now inside ${accessors.label?.(parent) ?? ''}.`)\n return true\n }\n\n if (key === 'ArrowLeft' && row.parentKey !== null) {\n const parent = tree.entry(row.parentKey)\n if (!parent) return false\n if (!commit(row.key, parent.key, 'after', 'keyboard')) return false\n say(`${name} is now after ${accessors.label?.(parent.node) ?? ''}.`)\n return true\n }\n\n announcement.value = `${name} cannot move there.`\n return false\n}\n\nconst activeKey = ref<TreeKey | null>(null)\n\nconst focusKey = computed(() => {\n const keys = rows.value.map((row) => row.key)\n if (activeKey.value !== null && keys.includes(activeKey.value)) return activeKey.value\n if (selectedKey.value !== null && keys.includes(selectedKey.value)) return selectedKey.value\n return keys[0] ?? null\n})\n\n/*\n * By position rather than by a selector built from the key: a key is whatever the\n * backend calls an id, and building a selector out of it is one slug with a dot in it\n * away from matching nothing.\n */\nasync function refocus(key: TreeKey) {\n activeKey.value = key\n await nextTick()\n const at = rows.value.findIndex((row) => row.key === key)\n if (at < 0) return\n root.value?.querySelectorAll<HTMLElement>('.wx-tree__row')[at]?.focus()\n}\n\nfunction step(from: number) {\n const row = rows.value[from]\n if (row) void refocus(row.key)\n}\n\nasync function onKeydown(row: TreeRow<T>, event: KeyboardEvent) {\n const at = rows.value.indexOf(row)\n\n if (event.altKey && event.key.startsWith('Arrow')) {\n event.preventDefault()\n keyboardMove(row, event.key)\n return\n }\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault()\n step(at + 1)\n break\n case 'ArrowUp':\n event.preventDefault()\n step(at - 1)\n break\n case 'ArrowRight':\n event.preventDefault()\n if (row.expandable && !row.expanded) await toggle(row)\n else step(at + 1)\n break\n case 'ArrowLeft':\n event.preventDefault()\n if (row.expanded) await toggle(row)\n else if (row.parentKey !== null) void refocus(row.parentKey)\n break\n case 'Home':\n event.preventDefault()\n step(0)\n break\n case 'End':\n event.preventDefault()\n step(rows.value.length - 1)\n break\n case 'Enter':\n event.preventDefault()\n select(row)\n break\n case ' ':\n event.preventDefault()\n if (props.checkable) onCheck(row, !checkedSet.value.has(row.key))\n else select(row)\n break\n }\n}\n\ndefineExpose({\n /** Opens every branch on the way to a node. */\n reveal: (key: TreeKey) => tree.reveal(key),\n /**\n * Opens a named path one level at a time, waiting for each lazy level before asking\n * for the next — the way to reach a node the tree has not fetched yet.\n */\n openPath: (keys: TreeKey[]) => tree.openPath(keys),\n expandAll: () => tree.expandAll(),\n collapseAll: () => tree.collapseAll(),\n /** The node itself and everything above it — a breadcrumb of the tree. */\n path: (key: TreeKey) => tree.path(key).map((entry) => entry.node),\n})\n</script>\n\n<template>\n <div\n ref=\"root\"\n :class=\"classes\"\n :style=\"{ '--wx-tree-indent': `${indent}px` }\"\n role=\"tree\"\n :aria-label=\"ariaLabel\"\n :aria-multiselectable=\"checkable || undefined\"\n >\n <div\n v-for=\"row in rows\"\n :key=\"row.key\"\n class=\"wx-tree__row\"\n :class=\"{\n 'is-selected': selectedKey === row.key,\n 'is-disabled': row.disabled,\n 'is-matched': row.matched,\n 'is-dragging': dragKey === row.key,\n [`is-drop-${dropZone}`]: dropKey === row.key && dropZone,\n }\"\n :style=\"{ '--wx-tree-depth': row.depth }\"\n :data-key=\"row.key\"\n role=\"treeitem\"\n :tabindex=\"focusKey === row.key ? 0 : -1\"\n :aria-level=\"row.depth + 1\"\n :aria-posinset=\"row.index + 1\"\n :aria-setsize=\"row.siblings.length\"\n :aria-expanded=\"row.expandable ? row.expanded : undefined\"\n :aria-selected=\"selectedKey === row.key\"\n :aria-checked=\"checkable ? checkedSet.has(row.key) : undefined\"\n :aria-disabled=\"row.disabled || undefined\"\n :draggable=\"canDrag(row)\"\n @click=\"onClick(row, $event)\"\n @keydown=\"onKeydown(row, $event)\"\n @focus=\"activeKey = row.key\"\n @dragstart.stop=\"onDragStart(row, $event)\"\n @dragover=\"onDragOver(row, $event)\"\n @drop.prevent=\"onDrop(row)\"\n @dragend=\"onDragEnd\"\n >\n <!--\n Decorative: the row itself is what a pointer drags and what a keyboard moves, so\n the grip is there to say so rather than to be operated on its own.\n -->\n <span v-if=\"draggable\" class=\"wx-tree__grip\" :title=\"dragLabel\" aria-hidden=\"true\">\n <wx-icon name=\"drag\" />\n </span>\n\n <!-- One per level, so the guides line up with the toggles above them. -->\n <span v-for=\"level in row.depth\" :key=\"level\" class=\"wx-tree__guide\" />\n\n <button\n v-if=\"row.expandable\"\n type=\"button\"\n class=\"wx-tree__toggle\"\n :aria-expanded=\"row.expanded\"\n :aria-label=\"`${row.expanded ? collapseLabel : expandLabel} ${accessors.label?.(row.node)}`\"\n tabindex=\"-1\"\n @click.stop=\"toggle(row)\"\n >\n <wx-icon :name=\"row.loading ? 'loader' : 'chevron-right'\" :spin=\"row.loading\" />\n </button>\n <span v-else class=\"wx-tree__toggle is-leaf\" />\n\n <!--\n The wrapper takes the click: a click on a `<label>` reaches the row as well as\n the input inside it, and a tick is not also a selection.\n -->\n <span v-if=\"checkable\" class=\"wx-tree__check\" @click.stop>\n <wx-checkbox\n :model-value=\"checkedSet.has(row.key)\"\n :indeterminate=\"halfChecked.has(row.key)\"\n :disabled=\"row.disabled\"\n :size=\"size\"\n :aria-label=\"accessors.label?.(row.node)\"\n tabindex=\"-1\"\n @change=\"onCheck(row, $event)\"\n />\n </span>\n\n <span class=\"wx-tree__label\">\n <slot\n :node=\"row.node\"\n :depth=\"row.depth\"\n :expanded=\"row.expanded\"\n :selected=\"selectedKey === row.key\"\n >\n {{ parts(row).before\n }}<mark v-if=\"parts(row).hit\" class=\"wx-tree__hit\">{{ parts(row).hit }}</mark\n >{{ parts(row).after }}\n </slot>\n </span>\n\n <span v-if=\"$slots.actions\" class=\"wx-tree__actions\" @click.stop>\n <slot name=\"actions\" :node=\"row.node\" :depth=\"row.depth\" />\n </span>\n </div>\n\n <div v-if=\"!rows.length\" class=\"wx-tree__empty\">\n <slot name=\"empty\">{{ emptyText }}</slot>\n </div>\n\n <!-- What a keyboard move says out loud. -->\n <div class=\"wx-tree__live\" role=\"status\" aria-live=\"polite\">{{ announcement }}</div>\n </div>\n</template>\n\n<style scoped>\n.wx-tree {\n position: relative;\n box-sizing: border-box;\n /* What a row keeps to its left. A tree that can be dragged parks the grip in it. */\n --wx-tree-pad: var(--wx-space-8);\n color: var(--wx-text-default);\n font-family: var(--wx-font-family-sans);\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-tree.is-draggable {\n --wx-tree-pad: var(--wx-space-16);\n}\n\n.wx-tree__row {\n position: relative;\n display: flex;\n align-items: center;\n gap: var(--wx-space-4);\n min-height: 32px;\n /*\n * Inside the row rather than around the tree, so the highlight still runs edge to\n * edge while what sits in the row keeps its distance from it. The block half is what\n * a row full of buttons needs: the caller's actions are taller than the text, and\n * without it they end up a pixel from the edge of the highlight. A row of plain\n * labels is shorter than `min-height` either way, so nothing is spent where there\n * is nothing to clear.\n */\n padding-block: var(--wx-space-4);\n padding-inline: var(--wx-tree-pad) var(--wx-space-8);\n border-radius: var(--wx-radius-control);\n cursor: pointer;\n user-select: none;\n}\n\n/*\n * A couple of pixels, which is all it takes for a list of names to stop reading as one\n * block of text. Between the rows rather than around them: the gap belongs to the pair,\n * and the tree has no room to give away at its ends.\n */\n.wx-tree__row + .wx-tree__row {\n margin-block-start: var(--wx-space-2);\n}\n\n/*\n * The small size is density, not small print: a node's label is the content, and\n * shrinking the text of a list of names buys a couple of pixels at the cost of the\n * thing being read. What gives is the room around it.\n */\n.wx-tree--sm .wx-tree__row {\n min-height: 26px;\n padding-block: var(--wx-space-2);\n line-height: var(--wx-font-line-height-tight);\n}\n\n.wx-tree__row:hover {\n background: var(--wx-bg-subtle);\n}\n\n.wx-tree__row:focus-visible {\n outline: 2px solid var(--wx-color-primary);\n outline-offset: -2px;\n}\n\n.wx-tree__row.is-selected {\n background: var(--wx-color-primary-soft);\n color: var(--wx-color-primary);\n font-weight: var(--wx-font-weight-medium);\n}\n\n.wx-tree__row.is-disabled {\n color: var(--wx-text-disabled);\n cursor: default;\n}\n\n.wx-tree__row.is-dragging {\n opacity: 0.4;\n}\n\n/*\n * The guide is a level of indentation that also draws the line down from the parent. The\n * border is inside the width, so `indent` is the whole step — a lined tree and a plain one\n * indent by the same amount, and four levels deep the difference is not a rounding error.\n */\n.wx-tree__guide {\n flex: none;\n align-self: stretch;\n box-sizing: border-box;\n width: var(--wx-tree-indent, 16px);\n}\n\n.wx-tree.is-lined .wx-tree__guide {\n border-inline-start: 1px solid var(--wx-border-muted);\n}\n\n.wx-tree__toggle {\n flex: none;\n display: grid;\n place-items: center;\n width: 20px;\n height: 20px;\n padding: 0;\n border: none;\n border-radius: var(--wx-radius-xs);\n background: none;\n color: var(--wx-text-muted);\n cursor: pointer;\n}\n\n.wx-tree__toggle:hover {\n background: var(--wx-bg-fill-hover);\n color: var(--wx-text-default);\n}\n\n.wx-tree__toggle.is-leaf {\n cursor: default;\n visibility: hidden;\n}\n\n.wx-tree__toggle :deep(svg) {\n transition: transform 0.15s ease;\n}\n\n.wx-tree__row[aria-expanded='true'] > .wx-tree__toggle :deep(svg) {\n transform: rotate(90deg);\n}\n\n/*\n * In the row's left margin rather than in its flow. The handle is wanted for the length of\n * one drag and is in the way for the rest of the time — and it was in the way of every\n * level at once, since everything after it moved right by its width. Absolute, it costs the\n * margin the row already has, and it is the margin's own width, so it never lands on the\n * chevron of a node at the top level.\n */\n.wx-tree__grip {\n position: absolute;\n inset-block: 0;\n inset-inline-start: 0;\n display: grid;\n place-items: center;\n width: var(--wx-tree-pad);\n color: var(--wx-text-placeholder);\n cursor: grab;\n opacity: 0;\n}\n\n.wx-tree__row:hover .wx-tree__grip,\n.wx-tree__row:focus-visible .wx-tree__grip {\n opacity: 1;\n}\n\n/* Flex, not block: an inline-flex checkbox in a block sits in a line box, and the\n leading around it makes the wrapper taller than the control it holds. */\n.wx-tree__check {\n flex: none;\n display: flex;\n align-items: center;\n margin-inline-end: var(--wx-space-2);\n}\n\n.wx-tree__label {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wx-tree__hit {\n background: var(--wx-color-warning-soft);\n color: inherit;\n border-radius: var(--wx-radius-none);\n}\n\n.wx-tree__actions {\n flex: none;\n display: flex;\n align-items: center;\n gap: var(--wx-space-2);\n margin-inline-start: var(--wx-space-8);\n opacity: 0;\n}\n\n.wx-tree__row:hover .wx-tree__actions,\n.wx-tree__row:focus-within .wx-tree__actions {\n opacity: 1;\n}\n\n/*\n * Where the node will land. The line starts at the indentation of the target, so that\n * \"before\" and \"after\" read as a position in the list rather than a rule across it.\n */\n.wx-tree__row.is-drop-before::after,\n.wx-tree__row.is-drop-after::after {\n content: '';\n position: absolute;\n inset-inline: calc(var(--wx-tree-pad) + var(--wx-tree-depth, 0) * var(--wx-tree-indent, 16px))\n var(--wx-space-8);\n height: 2px;\n border-radius: var(--wx-radius-full);\n background: var(--wx-color-primary);\n pointer-events: none;\n}\n\n/* Two pixels tall in a two-pixel gap: the line lands between the rows, not across one. */\n.wx-tree__row.is-drop-before::after {\n top: calc(var(--wx-space-2) * -1);\n}\n\n.wx-tree__row.is-drop-after::after {\n bottom: calc(var(--wx-space-2) * -1);\n}\n\n.wx-tree__row.is-drop-inside {\n background: var(--wx-color-primary-soft);\n box-shadow: inset 0 0 0 2px var(--wx-color-primary);\n}\n\n.wx-tree__empty {\n padding: var(--wx-space-16);\n color: var(--wx-text-muted);\n text-align: center;\n}\n\n.wx-tree__live {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-tree__toggle :deep(svg) {\n transition: none;\n }\n}\n</style>\n","<script setup lang=\"ts\" generic=\"T extends TreeNode\">\nimport { computed, nextTick, ref, useTemplateRef, watch } from 'vue'\nimport { PopoverAnchor, PopoverContent, PopoverPortal, PopoverRoot, PopoverTrigger } from 'reka-ui'\nimport WxIcon from '../Icon/Icon.vue'\nimport WxTree from '../Tree/Tree.vue'\nimport { useFormField } from '../../composables/useFormField'\nimport { useControlAttrs } from '../../composables/useControlAttrs'\nimport { useTreeNodes, type TreeAccessors, type TreeKey } from '../../composables/useTreeNodes'\nimport type { TreeNode } from '../Tree/types'\nimport type { TreeSelectEmits, TreeSelectProps, TreeSelectValue } from './types'\n\ndefineOptions({ name: 'WxTreeSelect', inheritAttrs: false })\n\n/* `class` and `style` belong to the control; the rest belongs to its trigger. */\nconst { rootAttrs, controlAttrs } = useControlAttrs()\n\nconst props = withDefaults(defineProps<TreeSelectProps<T>>(), {\n nodes: () => [],\n multiple: false,\n checkStrictly: false,\n nodeKey: 'id',\n labelKey: 'label',\n childrenKey: 'children',\n disabledKey: 'disabled',\n leafKey: 'leaf',\n defaultExpandAll: false,\n lazy: false,\n load: undefined,\n selectedPath: undefined,\n filterable: false,\n filterPlaceholder: 'Search',\n showPath: false,\n separator: ' / ',\n panelHeight: 280,\n clearable: false,\n placeholder: 'Select',\n emptyText: 'Nothing here',\n teleport: true,\n disabled: undefined,\n size: undefined,\n status: undefined,\n id: undefined,\n name: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<TreeSelectEmits<T>>()\n\ndefineSlots<{\n /** One node in the panel. */\n node?: (props: { node: T; depth: number; expanded: boolean; selected: boolean }) => unknown\n /** What the field shows instead of the labels. */\n value?: (props: { nodes: T[] }) => unknown\n}>()\n\nconst model = defineModel<TreeSelectValue>({ default: null })\n\nconst field = useFormField(props)\n\nconst open = ref(false)\nconst term = ref('')\nconst expanded = ref<TreeKey[]>([])\n\n/*\n * The same reading of a node the tree does, so `node-key` and its neighbours mean the\n * same thing on both sides of the panel.\n */\nconst accessors: TreeAccessors<T> = {\n key: (node, path) => (node[props.nodeKey] ?? node.key ?? path.join('.')) as TreeKey,\n children: (node) => node[props.childrenKey] as T[] | undefined,\n setChildren: (node, children) => {\n ;(node as Record<string, unknown>)[props.childrenKey] = children\n },\n label: (node) => String(node[props.labelKey] ?? ''),\n disabled: (node) => Boolean(node[props.disabledKey]),\n leaf: (node) => Boolean(node[props.leafKey]),\n}\n\n/*\n * The field needs what the panel already knows: which node a key names, and the path\n * to it. Nothing here is rearranged, so this instance is only the index — the tree in\n * the panel keeps its own, and they share the one `expanded` ref.\n */\nconst lookup = useTreeNodes<T>({\n nodes: () => props.nodes,\n accessors,\n expanded,\n})\n\n/* ---------------------------------------------------------------------------\n * The value\n * ------------------------------------------------------------------------- */\n\nconst keys = computed<TreeKey[]>(() => {\n if (model.value === null || model.value === undefined) return []\n return Array.isArray(model.value) ? model.value : [model.value]\n})\n\n/** `selectedPath` as the array of paths it always is inside. */\nconst paths = computed<T[][]>(() => {\n const given = props.selectedPath\n if (!given?.length) return []\n return (Array.isArray(given[0]) ? given : [given]) as T[][]\n})\n\n/** The path the caller handed over for a key, when the tree has none of its own. */\nfunction givenPath(key: TreeKey): T[] {\n return (\n (paths.value.find((path) => {\n const last = path.at(-1)\n return last !== undefined && accessors.key(last, []) === key\n }) as T[] | undefined) ?? []\n )\n}\n\n/** The nodes behind the keys, from the tree where it knows them and from the path where it does not. */\nconst selectedNodes = computed<T[]>(() =>\n keys.value\n .map((key) => lookup.entry(key)?.node ?? givenPath(key).at(-1))\n .filter((node): node is T => node !== undefined),\n)\n\n/*\n * A key with no node behind it is still a value. Saying so with the placeholder — the\n * way a field with nothing in it looks — would be the field lying about the model,\n * which is why a lazy tree wants `selected-path`: it is the only thing that can put a\n * name where the key would otherwise show through.\n */\nconst hasValue = computed(() => keys.value.length > 0)\n\nfunction labelOf(key: TreeKey) {\n const known = lookup.path(key).map((step) => step.node)\n const steps = known.length ? known : givenPath(key)\n if (!steps.length) return String(key)\n\n const shown = props.showPath ? steps : steps.slice(-1)\n return shown.map((node) => accessors.label?.(node) ?? '').join(props.separator)\n}\n\n/** A `<form>` posts strings: one key, or several separated by commas. */\nconst formValue = computed(() => keys.value.join(','))\n\nconst showClear = computed(() => props.clearable && hasValue.value && !field.disabled.value)\n\nconst classes = computed(() => [\n 'wx-tree-select',\n `wx-tree-select--${field.size.value}`,\n `wx-tree-select--${field.status.value}`,\n {\n 'is-open': open.value,\n 'is-disabled': field.disabled.value,\n 'is-multiple': props.multiple,\n },\n])\n\nconst panelStyle = computed(() => ({\n maxHeight: typeof props.panelHeight === 'number' ? `${props.panelHeight}px` : props.panelHeight,\n}))\n\n/* ---------------------------------------------------------------------------\n * Choosing\n * ------------------------------------------------------------------------- */\n\nfunction announce(value: TreeSelectValue) {\n model.value = value\n emit('change', value, selectedNodes.value)\n}\n\n/** Single: a node is the answer, so the panel has nothing left to ask. */\nfunction onSelect(_node: T | null, key: TreeKey | null) {\n if (props.multiple || key === null) return\n announce(key)\n open.value = false\n}\n\nfunction onChecked(next: TreeKey[]) {\n if (!props.multiple) return\n announce([...next])\n}\n\nfunction removeTag(key: TreeKey) {\n announce(keys.value.filter((held) => held !== key))\n}\n\nfunction clear() {\n announce(props.multiple ? [] : null)\n emit('clear')\n}\n\n/* ---------------------------------------------------------------------------\n * The panel\n * ------------------------------------------------------------------------- */\n\nconst panel = ref<HTMLElement | null>(null)\n/*\n * Typed by the one thing the field asks of it. `InstanceType` cannot be taken of a\n * generic component, and the whole instance is more than is wanted here anyway.\n */\nconst tree = useTemplateRef<{ openPath: (keys: TreeKey[]) => Promise<boolean> }>('tree')\n\n/*\n * The panel itself takes focus when it opens, which leaves the arrow keys with nothing\n * to act on — the tree listens on its rows. The first arrow hands focus to the row the\n * tree is already pointing at: what is selected, or the first one.\n */\nfunction onPanelKeydown(event: KeyboardEvent) {\n if ((event.target as HTMLElement | null)?.closest('.wx-tree__row')) return\n if (event.key !== 'ArrowDown') return\n\n event.preventDefault()\n panel.value?.querySelector<HTMLElement>('.wx-tree__row[tabindex=\"0\"]')?.focus()\n}\n\n/*\n * Opening the panel on a tree of five hundred nodes and showing the top of it is no\n * help when something is already chosen: the branches leading to it are opened, so the\n * answer to \"where is this\" is on screen before the first scroll.\n */\nwatch(open, async (isOpen) => {\n if (!isOpen) {\n term.value = ''\n emit('close')\n return\n }\n\n for (const key of keys.value) lookup.reveal(key)\n emit('open')\n\n await nextTick()\n\n /* A field with a search field is a field somebody opened in order to type. */\n if (props.filterable) {\n panel.value\n ?.closest('.wx-tree-select__panel')\n ?.querySelector<HTMLElement>('.wx-tree-select__search-input')\n ?.focus()\n }\n\n /*\n * Where the tree is fetched a branch at a time it does not hold the chosen node yet,\n * so `reveal` above had nothing to open. The path the caller gave is walked instead,\n * a level at a time, which is a fetch per level — and then the node is in the tree,\n * open and scrolled to.\n */\n for (const path of paths.value) {\n const ancestors = path.slice(0, -1).map((node) => accessors.key(node, []))\n if (ancestors.length) await tree.value?.openPath(ancestors)\n }\n\n await nextTick()\n panel.value\n ?.querySelector<HTMLElement>('.wx-tree__row.is-selected, .wx-tree__row[aria-checked=\"true\"]')\n ?.scrollIntoView({ block: 'nearest' })\n})\n</script>\n\n<template>\n <popover-root v-model:open=\"open\">\n <div :class=\"classes\" v-bind=\"rootAttrs\">\n <popover-anchor as=\"div\" class=\"wx-tree-select__anchor\">\n <popover-trigger\n :id=\"field.id.value\"\n v-bind=\"controlAttrs\"\n class=\"wx-tree-select__trigger\"\n type=\"button\"\n :disabled=\"field.disabled.value\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"field.describedBy.value\"\n :aria-invalid=\"field.status.value === 'error' || undefined\"\n >\n <span class=\"wx-tree-select__value\">\n <slot v-if=\"hasValue\" name=\"value\" :nodes=\"selectedNodes\">\n <template v-if=\"multiple\">\n <span v-for=\"key in keys\" :key=\"String(key)\" class=\"wx-tree-select__tag\">\n {{ labelOf(key) }}\n <span\n v-if=\"!field.disabled.value\"\n class=\"wx-tree-select__tag-remove\"\n role=\"button\"\n tabindex=\"-1\"\n :aria-label=\"`Remove ${labelOf(key)}`\"\n @click.stop=\"removeTag(key)\"\n >\n <wx-icon name=\"close\" />\n </span>\n </span>\n </template>\n <span v-else class=\"wx-tree-select__single\">{{ labelOf(keys[0]!) }}</span>\n </slot>\n <span v-else class=\"wx-tree-select__placeholder\">{{ placeholder }}</span>\n </span>\n\n <wx-icon class=\"wx-tree-select__arrow\" name=\"chevron-down\" />\n </popover-trigger>\n\n <button\n v-if=\"showClear\"\n class=\"wx-tree-select__clear\"\n type=\"button\"\n tabindex=\"-1\"\n aria-label=\"Clear\"\n @click.stop=\"clear\"\n >\n <wx-icon name=\"close\" />\n </button>\n </popover-anchor>\n\n <input v-if=\"name\" type=\"hidden\" :name=\"name\" :value=\"formValue\" />\n </div>\n\n <popover-portal :disabled=\"!teleport\">\n <!--\n The z-index goes on the content itself, which is where Reka puts the element it\n positions. The panel's own rule cannot carry it: that class lands one element\n further in, on a child that is not the positioned one — and a panel opened from\n inside a dialog would be painted behind it.\n -->\n <popover-content\n class=\"wx-tree-select__panel\"\n align=\"start\"\n :side-offset=\"4\"\n :style=\"{ zIndex: 'var(--wx-z-index-popover)' }\"\n @keydown=\"onPanelKeydown\"\n >\n <label v-if=\"filterable\" class=\"wx-tree-select__search\">\n <wx-icon name=\"search\" />\n <input\n v-model=\"term\"\n class=\"wx-tree-select__search-input\"\n type=\"search\"\n :placeholder=\"filterPlaceholder\"\n autocomplete=\"off\"\n />\n </label>\n\n <div ref=\"panel\" class=\"wx-tree-select__body\" :style=\"panelStyle\">\n <wx-tree\n ref=\"tree\"\n :model-value=\"nodes\"\n v-model:expanded=\"expanded\"\n :selected=\"multiple ? null : (keys[0] ?? null)\"\n :checked=\"multiple ? keys : []\"\n :checkable=\"multiple\"\n :check-strictly=\"checkStrictly\"\n :node-key=\"nodeKey\"\n :label-key=\"labelKey\"\n :children-key=\"childrenKey\"\n :disabled-key=\"disabledKey\"\n :leaf-key=\"leafKey\"\n :default-expand-all=\"defaultExpandAll\"\n :lazy=\"lazy\"\n :load=\"load\"\n :filter=\"term\"\n :size=\"field.size.value === 'lg' ? 'md' : 'sm'\"\n :empty-text=\"emptyText\"\n :aria-label=\"ariaLabel ?? placeholder\"\n @select=\"onSelect\"\n @update:checked=\"onChecked\"\n >\n <template v-if=\"$slots.node\" #default=\"slotProps\">\n <slot name=\"node\" v-bind=\"slotProps\" />\n </template>\n </wx-tree>\n </div>\n </popover-content>\n </popover-portal>\n </popover-root>\n</template>\n\n<style scoped>\n.wx-tree-select {\n display: block;\n width: 100%;\n font-family: var(--wx-font-family-sans);\n}\n\n.wx-tree-select__anchor {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.wx-tree-select__trigger {\n display: flex;\n align-items: center;\n gap: var(--wx-space-6);\n box-sizing: border-box;\n width: 100%;\n min-height: var(--wx-size-control-md);\n padding: var(--wx-space-4) var(--wx-space-6) var(--wx-space-4) var(--wx-space-12);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-control);\n color: var(--wx-text-default);\n font-family: inherit;\n font-size: var(--wx-font-size-control-md);\n font-weight: var(--wx-font-weight-medium);\n text-align: start;\n cursor: pointer;\n transition: border-color var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-tree-select--sm .wx-tree-select__trigger {\n min-height: var(--wx-size-control-sm);\n font-size: var(--wx-font-size-control-sm);\n}\n\n.wx-tree-select--lg .wx-tree-select__trigger {\n min-height: var(--wx-size-control-lg);\n font-size: var(--wx-font-size-control-lg);\n}\n\n.wx-tree-select__trigger:hover {\n border-color: var(--wx-border-strong);\n}\n\n.wx-tree-select.is-open .wx-tree-select__trigger {\n border-color: var(--wx-border-focus);\n}\n\n.wx-tree-select__trigger:focus-visible {\n outline: none;\n border-color: var(--wx-color-primary);\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-tree-select--error .wx-tree-select__trigger,\n.wx-tree-select--error.is-open .wx-tree-select__trigger {\n border-color: var(--wx-color-danger);\n}\n\n.wx-tree-select--success .wx-tree-select__trigger {\n border-color: var(--wx-color-success);\n}\n\n.wx-tree-select--warning .wx-tree-select__trigger {\n border-color: var(--wx-color-warning);\n}\n\n.wx-tree-select.is-disabled .wx-tree-select__trigger {\n background: var(--wx-bg-disabled);\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n.wx-tree-select__value {\n display: flex;\n flex: 1 1 auto;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-4);\n min-width: 0;\n}\n\n.wx-tree-select__single,\n.wx-tree-select__placeholder {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wx-tree-select__placeholder {\n color: var(--wx-text-placeholder);\n font-weight: var(--wx-font-weight-regular);\n}\n\n/* One tag per chosen node, so a selection of eight is a selection of eight. */\n.wx-tree-select__tag {\n display: inline-flex;\n align-items: center;\n gap: var(--wx-space-4);\n max-width: 100%;\n padding: 2px var(--wx-space-6);\n background: var(--wx-bg-fill);\n border-radius: var(--wx-radius-xs);\n font-size: var(--wx-font-size-sm);\n font-weight: var(--wx-font-weight-regular);\n line-height: var(--wx-font-line-height-tight);\n}\n\n.wx-tree-select__tag-remove {\n display: inline-flex;\n align-items: center;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n cursor: pointer;\n}\n\n.wx-tree-select__tag-remove:hover {\n color: var(--wx-text-default);\n}\n\n.wx-tree-select__arrow {\n flex: none;\n color: var(--wx-text-muted);\n transition: transform var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-tree-select.is-open .wx-tree-select__arrow {\n transform: rotate(180deg);\n}\n\n/* Over the arrow, since a cleared field is about to show the arrow again anyway. */\n.wx-tree-select__clear {\n position: absolute;\n inset-inline-end: var(--wx-space-6);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n padding: 0;\n background: var(--wx-bg-surface);\n border: none;\n border-radius: var(--wx-radius-full);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n cursor: pointer;\n}\n\n.wx-tree-select__clear:hover {\n color: var(--wx-text-default);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-tree-select__trigger,\n .wx-tree-select__arrow {\n transition: none;\n }\n}\n</style>\n\n<style>\n/* The panel is teleported, so its styles cannot be scoped to the component. */\n.wx-tree-select__panel {\n box-sizing: border-box;\n /* At least as wide as the field, and free to grow with a deep branch. */\n min-width: var(--reka-popover-trigger-width);\n max-width: min(560px, calc(100vw - var(--wx-space-32)));\n padding: var(--wx-space-4);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-muted);\n border-radius: var(--wx-radius-sm);\n box-shadow: var(--wx-shadow-popover);\n}\n\n.wx-tree-select__search {\n display: flex;\n align-items: center;\n gap: var(--wx-space-6);\n padding: var(--wx-space-4) var(--wx-space-8);\n border-bottom: 1px solid var(--wx-border-muted);\n color: var(--wx-text-muted);\n}\n\n.wx-tree-select__search-input {\n flex: 1 1 auto;\n min-width: 0;\n padding: var(--wx-space-4) 0;\n background: none;\n border: none;\n outline: none;\n color: var(--wx-text-default);\n font-family: inherit;\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-tree-select__search-input::placeholder {\n color: var(--wx-text-placeholder);\n}\n\n.wx-tree-select__body {\n overflow: auto;\n overscroll-behavior: contain;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport WxButton from '../Button/Button.vue'\nimport WxIcon from '../Icon/Icon.vue'\nimport WxProgress from '../Progress/Progress.vue'\nimport type { UploadEmits, UploadFile, UploadProps } from './types'\n\ndefineOptions({ name: 'WxUpload' })\n\n/*\n * It does not upload anything.\n *\n * That is deliberate, and it is the same rule the rest of the library follows: a\n * component that owns the request owns the URL, the headers, the CSRF token, the\n * retry policy and the error shape — none of which it can know. So this collects\n * files, checks them, and shows how each one is getting on; the caller does the\n * sending and writes the progress back through `v-model`.\n */\nconst props = withDefaults(defineProps<UploadProps>(), {\n accept: undefined,\n multiple: true,\n maxSize: undefined,\n max: undefined,\n buttonOnly: false,\n buttonText: 'Choose files',\n hint: 'Drop files here, or click to choose',\n gallery: false,\n disabled: false,\n removable: true,\n beforeAdd: undefined,\n})\n\nconst emit = defineEmits<UploadEmits>()\n\ndefineSlots<{\n /** Replaces the inside of the drop zone. */\n default?: (props: { open: () => void; dragging: boolean }) => unknown\n /** Replaces the row a file is shown as. */\n file?: (props: { file: UploadFile; remove: () => void }) => unknown\n /** Under the zone: a note about formats or sizes. */\n footer?: () => unknown\n}>()\n\nconst files = defineModel<UploadFile[]>({ default: () => [] })\n\nconst input = ref<HTMLInputElement | null>(null)\nconst dragging = ref(false)\n\nlet counter = 0\n\nfunction open() {\n if (props.disabled) return\n input.value?.click()\n}\n\nfunction idFor(file: File) {\n counter += 1\n return `${Date.now().toString(36)}-${counter}-${file.name}`\n}\n\nfunction matchesAccept(file: File) {\n if (!props.accept) return true\n\n return props.accept\n .split(',')\n .map((rule) => rule.trim().toLowerCase())\n .filter(Boolean)\n .some((rule) => {\n if (rule.startsWith('.')) return file.name.toLowerCase().endsWith(rule)\n if (rule.endsWith('/*')) return file.type.startsWith(rule.slice(0, -1))\n return file.type.toLowerCase() === rule\n })\n}\n\nasync function take(incoming: FileList | File[]) {\n if (props.disabled) return\n\n const added: UploadFile[] = []\n\n for (const file of Array.from(incoming)) {\n if (props.max !== undefined && files.value.length + added.length >= props.max) {\n emit('reject', file, 'count')\n continue\n }\n\n if (!matchesAccept(file)) {\n emit('reject', file, 'type')\n continue\n }\n\n if (props.maxSize !== undefined && file.size > props.maxSize) {\n emit('reject', file, 'size')\n continue\n }\n\n if (props.beforeAdd && (await props.beforeAdd(file)) === false) {\n emit('reject', file, 'rejected')\n continue\n }\n\n added.push({\n id: idFor(file),\n name: file.name,\n size: file.size,\n type: file.type,\n status: 'ready',\n progress: 0,\n raw: file,\n })\n }\n\n if (added.length === 0) return\n\n files.value = props.multiple ? [...files.value, ...added] : added.slice(-1)\n emit('add', added)\n}\n\nfunction onPick(event: Event) {\n const element = event.target as HTMLInputElement\n if (element.files) void take(element.files)\n /* Cleared, so choosing the same file twice in a row still fires a change. */\n element.value = ''\n}\n\nfunction onDrop(event: DragEvent) {\n dragging.value = false\n if (event.dataTransfer?.files) void take(event.dataTransfer.files)\n}\n\nfunction remove(file: UploadFile) {\n files.value = files.value.filter((known) => known.id !== file.id)\n emit('remove', file)\n}\n\n/** Sizes as a reader would say them, which is never in bytes past a thousand. */\nfunction readableSize(bytes: number) {\n if (bytes <= 0) return ''\n const units = ['B', 'kB', 'MB', 'GB']\n const power = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1)\n const value = bytes / 1024 ** power\n return `${value.toFixed(power === 0 ? 0 : 1)} ${units[power]}`\n}\n\nconst full = computed(() => props.max !== undefined && files.value.length >= props.max)\n\nconst classes = computed(() => [\n 'wx-upload',\n {\n 'wx-upload--gallery': props.gallery,\n 'is-dragging': dragging.value,\n 'is-disabled': props.disabled,\n },\n])\n</script>\n\n<template>\n <div :class=\"classes\">\n <input\n ref=\"input\"\n class=\"wx-upload__input\"\n type=\"file\"\n :accept=\"accept\"\n :multiple=\"multiple\"\n :disabled=\"disabled\"\n tabindex=\"-1\"\n @change=\"onPick\"\n />\n\n <wx-button v-if=\"buttonOnly\" :disabled=\"disabled || full\" @click=\"open\">\n <template #icon><wx-icon name=\"upload\" /></template>\n {{ buttonText }}\n </wx-button>\n\n <!--\n A button rather than a div with a click handler: this is the control that opens\n the file picker, and a reader who cannot use a pointer has to be able to reach\n it and press it like anything else.\n -->\n <button\n v-else\n type=\"button\"\n class=\"wx-upload__zone\"\n :disabled=\"disabled || full\"\n @click=\"open\"\n @dragenter.prevent=\"dragging = true\"\n @dragover.prevent=\"dragging = true\"\n @dragleave.prevent=\"dragging = false\"\n @drop.prevent=\"onDrop\"\n >\n <slot :open=\"open\" :dragging=\"dragging\">\n <wx-icon class=\"wx-upload__glyph\" name=\"upload\" />\n <span class=\"wx-upload__hint\">{{ hint }}</span>\n </slot>\n </button>\n\n <ul v-if=\"files.length > 0\" class=\"wx-upload__files\">\n <li v-for=\"file in files\" :key=\"file.id\" class=\"wx-upload__file\" :class=\"`is-${file.status}`\">\n <slot name=\"file\" :file=\"file\" :remove=\"() => remove(file)\">\n <wx-icon\n class=\"wx-upload__file-icon\"\n :name=\"file.type.startsWith('image/') ? 'image' : 'file'\"\n />\n\n <div class=\"wx-upload__file-text\">\n <button type=\"button\" class=\"wx-upload__file-name\" @click=\"emit('select', file)\">\n {{ file.name }}\n </button>\n\n <span v-if=\"file.error\" class=\"wx-upload__file-error\">{{ file.error }}</span>\n <span v-else-if=\"file.size\" class=\"wx-upload__file-size\">\n {{ readableSize(file.size) }}\n </span>\n </div>\n\n <wx-progress\n v-if=\"file.status === 'uploading'\"\n class=\"wx-upload__file-progress\"\n size=\"sm\"\n :value=\"file.progress\"\n />\n\n <wx-icon v-else-if=\"file.status === 'done'\" class=\"wx-upload__file-done\" name=\"check\" />\n\n <button\n v-if=\"removable\"\n type=\"button\"\n class=\"wx-upload__file-remove\"\n :aria-label=\"`Remove ${file.name}`\"\n @click=\"remove(file)\"\n >\n <wx-icon name=\"close\" />\n </button>\n </slot>\n </li>\n </ul>\n\n <div v-if=\"$slots.footer\" class=\"wx-upload__footer\">\n <slot name=\"footer\" />\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-upload {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-10);\n box-sizing: border-box;\n font-family: var(--wx-font-family-sans);\n}\n\n/* The real input is never seen; the zone above it is what is pressed. */\n.wx-upload__input {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n\n.wx-upload__zone {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--wx-space-6);\n box-sizing: border-box;\n width: 100%;\n padding: var(--wx-space-24);\n background: var(--wx-bg-subtle);\n border: 1px dashed var(--wx-border-default);\n border-radius: var(--wx-radius-sm);\n color: var(--wx-text-muted);\n font: inherit;\n font-size: var(--wx-font-size-sm);\n cursor: pointer;\n transition:\n border-color var(--wx-duration-fast) var(--wx-easing-standard),\n background var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-upload__zone:hover:not(:disabled),\n.wx-upload.is-dragging .wx-upload__zone {\n background: var(--wx-color-primary-soft);\n border-color: var(--wx-color-primary);\n color: var(--wx-color-primary);\n}\n\n.wx-upload__zone:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-upload__zone:disabled {\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n\n.wx-upload__glyph {\n width: 24px;\n height: 24px;\n}\n\n.wx-upload__files {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-6);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.wx-upload--gallery .wx-upload__files {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));\n gap: var(--wx-space-8);\n}\n\n.wx-upload__file {\n display: flex;\n /* Scoped, so a host stylesheet spacing `li + li` cannot double the gap. */\n margin: 0;\n align-items: center;\n gap: var(--wx-space-8);\n padding: var(--wx-space-6) var(--wx-space-8);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-xs);\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-upload__file.is-error {\n border-color: var(--wx-color-danger);\n}\n\n.wx-upload__file-icon {\n flex: 0 0 auto;\n color: var(--wx-text-muted);\n}\n\n.wx-upload__file-text {\n display: flex;\n flex: 1 1 auto;\n flex-direction: column;\n min-width: 0;\n}\n\n.wx-upload__file-name {\n padding: 0;\n overflow: hidden;\n background: none;\n border: none;\n color: inherit;\n font: inherit;\n text-align: start;\n text-overflow: ellipsis;\n white-space: nowrap;\n cursor: pointer;\n}\n\n.wx-upload__file-name:hover {\n color: var(--wx-color-primary);\n}\n\n.wx-upload__file-size {\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n}\n\n.wx-upload__file-error {\n color: var(--wx-color-danger);\n font-size: var(--wx-font-size-xs);\n}\n\n.wx-upload__file-progress {\n flex: 0 0 96px;\n}\n\n.wx-upload__file-done {\n flex: 0 0 auto;\n color: var(--wx-color-success);\n}\n\n.wx-upload__file-remove {\n display: inline-flex;\n flex: 0 0 auto;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n padding: 0;\n background: none;\n border: none;\n border-radius: var(--wx-radius-xs);\n color: var(--wx-text-muted);\n cursor: pointer;\n}\n\n.wx-upload__file-remove:hover {\n background: var(--wx-bg-fill);\n color: var(--wx-color-danger);\n}\n\n.wx-upload__file-remove:focus-visible,\n.wx-upload__file-name:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-upload__footer {\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wx-upload__zone {\n transition: none;\n }\n}\n</style>\n","import {\n defineComponent,\n getCurrentInstance,\n h,\n inject,\n onErrorCaptured,\n provide,\n ref,\n render,\n type App,\n type AppContext,\n type Component,\n type InjectionKey,\n type Ref,\n} from 'vue'\n\n/** What a component opened from code can do about itself. */\nexport interface ModalHandle<T = unknown> {\n /** `false` in a component that is being used declaratively. */\n isModal: boolean\n /** Bind it to the panel: `<wx-dialog v-model:open=\"open\">`. */\n open: Ref<boolean>\n /** Settles the promise with a value, and closes. */\n resolve: (value: T) => void\n /** Settles it with nothing, and closes. */\n dismiss: () => void\n}\n\nexport interface ModalOptions {\n /** Props for the component. */\n props?: Record<string, unknown>\n /** Slots for it, as render functions. */\n slots?: Record<string, (...args: unknown[]) => unknown>\n /** Events that settle the promise with their payload. Default: `resolve`. */\n resolveOn?: string | string[]\n /** Events that settle it with nothing. Default: `cancel` and `close`. */\n dismissOn?: string | string[]\n /** Where to mount. Default: a div at the end of `<body>`. */\n container?: HTMLElement\n /** The app whose plugins and provides the component should see. */\n appContext?: AppContext\n /** How long the closing animation is given before the node is taken away, in ms. */\n duration?: number\n}\n\nexport interface ModalPromise<T> extends Promise<T | undefined> {\n /** Closes it from outside — a route change, a timeout, a second thought. */\n close: (value?: T) => void\n}\n\nexport const modalKey: InjectionKey<ModalHandle> = Symbol('wx-modal')\n\n/*\n * A component mounted outside the app's own tree knows nothing of it: no plugins, no\n * provides, no global components, no i18n. The way to hand it all of that is to give its\n * vnode the app's context, which is why the plugin remembers the app it was installed\n * into. Anyone importing components one at a time calls `connectModals` instead.\n */\nlet installed: AppContext | undefined\n\nexport function connectModals(app: App) {\n installed = (app as App & { _context: AppContext })._context\n}\n\nfunction contextFor(explicit?: AppContext) {\n return explicit ?? getCurrentInstance()?.appContext ?? installed\n}\n\n/** `select` → `onSelect`, the name Vue gives a listener for that event. */\nfunction handlerFor(event: string) {\n const camel = event.replace(/-(\\w)/g, (_, letter: string) => letter.toUpperCase())\n return `on${camel.charAt(0).toUpperCase()}${camel.slice(1)}`\n}\n\nfunction listOf(names: string | string[] | undefined, fallback: string[]) {\n if (names === undefined) return fallback\n return Array.isArray(names) ? names : [names]\n}\n\n/** Whether the component asks for a prop, so that we only pass one it knows about. */\nfunction declares(component: Component, name: string) {\n const props = (component as { props?: string[] | Record<string, unknown> }).props\n if (Array.isArray(props)) return props.includes(name)\n return Boolean(props && name in props)\n}\n\n/**\n * Mounts a component outside the app and hands back a promise for its answer.\n *\n * ```ts\n * const product = await openModal<Product>(ProductBrowser, {\n * props: { multiple: false },\n * resolveOn: 'select',\n * })\n * ```\n *\n * The promise settles the moment the answer is known and the node is taken away once the\n * closing animation has had its time — so the caller is never waiting on an animation, and\n * the panel is never cut off mid-fade.\n */\nexport function openModal<T = unknown>(\n component: Component,\n options: ModalOptions = {},\n): ModalPromise<T> {\n let settle!: (value: T | undefined) => void\n let fail!: (reason: unknown) => void\n\n const promise = new Promise<T | undefined>((resolve, reject) => {\n settle = resolve\n fail = reject\n })\n\n const container = document.createElement('div')\n container.className = 'wx-modal-host'\n ;(options.container ?? document.body).append(container)\n\n const open = ref(true)\n\n let done = false\n let timer: ReturnType<typeof setTimeout> | undefined\n let gone = false\n\n /*\n * The plain timer functions rather than `window`'s. The panel is taken away a moment\n * after it closes, and that moment can land after whatever set it up has gone — the end\n * of a test, a page being torn down — where reaching through `window` is a reference\n * error rather than a cleanup.\n */\n function unmount() {\n /*\n * An unmount hook that throws comes back here through `onErrorCaptured`, and a second\n * `render(null)` over a half-unmounted tree throws again — one error becomes a stack\n * overflow. Once is enough.\n */\n if (gone) return\n gone = true\n\n clearTimeout(timer)\n render(null, container)\n container.remove()\n }\n\n function finish(value?: T) {\n if (done) return\n done = true\n open.value = false\n settle(value)\n timer = setTimeout(unmount, options.duration ?? 250)\n }\n\n const handle: ModalHandle<T> = {\n isModal: true,\n open,\n resolve: (value: T) => finish(value),\n dismiss: () => finish(undefined),\n }\n\n const listeners: Record<string, unknown> = {}\n for (const event of listOf(options.dismissOn, ['cancel', 'close'])) {\n listeners[handlerFor(event)] = () => finish(undefined)\n }\n for (const event of listOf(options.resolveOn, ['resolve'])) {\n listeners[handlerFor(event)] = (value: T) => finish(value)\n }\n\n /*\n * A host of our own rather than the component itself, for two reasons: it can hold the\n * handle for anything inside to reach, and it re-renders — which is what lets the panel\n * be told to close and play its animation before the whole thing is taken away.\n */\n const host = defineComponent({\n name: 'WxModalHost',\n setup() {\n provide(modalKey, handle as ModalHandle)\n\n /* A modal that throws would otherwise leave the caller awaiting it for ever. */\n onErrorCaptured((error) => {\n if (!done) {\n done = true\n fail(error)\n }\n unmount()\n return false\n })\n\n return () =>\n h(\n component,\n {\n ...options.props,\n ...(declares(component, 'open')\n ? {\n open: open.value,\n 'onUpdate:open': (value: boolean) => {\n if (!value) finish(undefined)\n },\n }\n : {}),\n ...listeners,\n },\n options.slots,\n )\n },\n })\n\n const vnode = h(host)\n vnode.appContext = contextFor(options.appContext) ?? null\n render(vnode, container)\n\n const result = promise as ModalPromise<T>\n result.close = (value?: T) => finish(value)\n return result\n}\n\n/**\n * Wraps a component in a function that opens it — the shape a browser or a picker is\n * reached by everywhere else in an app.\n *\n * ```ts\n * export const productBrowser = createModal<Product, ProductBrowserProps>(ProductBrowser, {\n * resolveOn: 'select',\n * })\n *\n * const product = await productBrowser({ multiple: false })\n * ```\n *\n * `P` is any object — an `interface` of props included, which a `Record<string, unknown>`\n * would have turned away for want of an index signature.\n */\nexport function createModal<T = unknown, P extends object = Record<string, never>>(\n component: Component,\n defaults: ModalOptions = {},\n) {\n return (props?: P, options: ModalOptions = {}): ModalPromise<T> =>\n openModal<T>(component, {\n ...defaults,\n ...options,\n props: { ...defaults.props, ...props, ...options.props } as Record<string, unknown>,\n })\n}\n\n/**\n * The handle straight from the tree, for when `inject` looks elsewhere.\n *\n * While `app.runWithContext()` is running, `inject` reads the app's provides instead of the\n * parent's — and vue-router runs every navigation guard inside it. A modal opened from a guard\n * (`confirm` in `onBeforeRouteLeave`, \"leave without saving?\") is mounted synchronously right\n * there, so its component never saw the host's handle: it got the harmless stand-in below, and\n * its buttons answered nothing. The dialog stayed open and the navigation hung for ever.\n */\nfunction fromHost(): ModalHandle | undefined {\n const parent = getCurrentInstance()?.parent as { provides?: Record<symbol, unknown> } | null\n\n return parent?.provides?.[modalKey as symbol] as ModalHandle | undefined\n}\n\n/**\n * The handle of the modal a component is being shown in. Outside one it answers all the\n * same, with `isModal: false` and calls that do nothing — so a component can be written\n * once and used both ways.\n */\nexport function useModal<T = unknown>(): ModalHandle<T> {\n const handle = inject(modalKey, undefined) ?? fromHost()\n if (handle) return handle as ModalHandle<T>\n\n return {\n isModal: false,\n open: ref(true),\n resolve: () => {},\n dismiss: () => {},\n }\n}\n","import type { App, Component, Plugin } from 'vue'\nimport * as components from './components'\nimport { vWxSelect } from './components/SelectionArea'\nimport { connectModals } from './composables/useModal'\n\nexport interface WebxUiOptions {\n /**\n * Prefix used when registering components globally.\n * Components are declared as `WxButton`, so the default keeps that name.\n */\n prefix?: string\n}\n\n/**\n * Registers every component globally:\n *\n * ```ts\n * import { WebxUI } from '@webx-ui/core'\n * import '@webx-ui/core/style.css'\n *\n * app.use(WebxUI)\n * ```\n *\n * Prefer named imports when bundle size matters — they tree-shake.\n */\nexport const WebxUI: Plugin<[WebxUiOptions?]> = {\n install(app: App, options: WebxUiOptions = {}) {\n const { prefix = 'Wx' } = options\n\n /*\n * The barrel also exports helpers — the icon registry, the countdown formatter —\n * so the `Wx` prefix is what marks a component, and the cast follows that check.\n */\n for (const [name, exported] of Object.entries(components)) {\n if (!name.startsWith('Wx')) continue\n const registeredName = prefix === 'Wx' ? name : `${prefix}${name.slice(2)}`\n app.component(registeredName, exported as Component)\n }\n\n /*\n * The one directive we ship. It belongs to the selection area, and registering it here\n * means a marked-up grid works the moment the plugin is installed, the way the\n * components do.\n */\n app.directive('wx-select', vWxSelect)\n\n /*\n * A component opened from code is mounted outside this app's tree, so it is handed the\n * app's own context to render in — its plugins, its provides, its global components.\n */\n connectModals(app)\n },\n}\n\nexport default WebxUI\n","<script setup lang=\"ts\">\nimport WxButton from '../components/Button/Button.vue'\nimport WxDialog from '../components/Dialog/Dialog.vue'\nimport { useModal } from '../composables/useModal'\nimport type { ButtonType } from '../components/Button/types'\n\ndefineOptions({ name: 'WxConfirmDialog' })\n\nwithDefaults(\n defineProps<{\n title?: string\n message?: string\n confirmText?: string\n cancelText?: string\n tone?: ButtonType\n width?: number | string\n }>(),\n {\n title: 'Are you sure?',\n message: undefined,\n confirmText: 'Confirm',\n cancelText: 'Cancel',\n tone: 'primary',\n width: 420,\n },\n)\n\nconst { open, resolve, dismiss } = useModal<boolean>()\n</script>\n\n<template>\n <wx-dialog\n v-model:open=\"open\"\n :title=\"title\"\n :width=\"width\"\n :close-on-overlay=\"false\"\n role=\"alertdialog\"\n >\n <p v-if=\"message\" class=\"wx-confirm__message\">{{ message }}</p>\n\n <template #footer>\n <wx-button variant=\"outline\" @click=\"dismiss()\">{{ cancelText }}</wx-button>\n <wx-button :type=\"tone\" @click=\"resolve(true)\">{{ confirmText }}</wx-button>\n </template>\n </wx-dialog>\n</template>\n\n<style scoped>\n.wx-confirm__message {\n margin: 0;\n color: var(--wx-text-default);\n font-size: var(--wx-font-size-md);\n line-height: var(--wx-font-line-height-normal);\n}\n</style>\n","import ConfirmDialog from '../internal/ConfirmDialog.vue'\nimport { openModal } from './useModal'\nimport type { ButtonType } from '../components/Button/types'\n\nexport interface ConfirmOptions {\n /** The question, as the heading. Defaults to \"Are you sure?\" */\n title?: string\n /** What is at stake, under the question. */\n message?: string\n confirmText?: string\n cancelText?: string\n /** Colour of the confirming button. `danger` for anything that destroys something. */\n tone?: ButtonType\n width?: number | string\n}\n\n/**\n * Asks, and answers `true` or `false`.\n *\n * ```ts\n * if (await confirm('Delete this product?')) remove(product)\n * ```\n *\n * It never rejects. A question that throws when the answer is no turns every call site\n * into a `try` block, and a forgotten `catch` into an unhandled rejection.\n */\nexport function confirm(\n message?: string | ConfirmOptions,\n options: ConfirmOptions = {},\n): Promise<boolean> {\n const props = typeof message === 'string' ? { message, ...options } : { ...message, ...options }\n\n return openModal<boolean>(ConfirmDialog, { props }).then((answer) => answer === true)\n}\n","<script setup lang=\"ts\">\nimport { ref, useTemplateRef } from 'vue'\nimport WxButton from '../components/Button/Button.vue'\nimport WxDialog from '../components/Dialog/Dialog.vue'\nimport WxImageEditor from '../components/ImageEditor/ImageEditor.vue'\nimport { useModal } from '../composables/useModal'\nimport type { ImageEditorResult } from '../components/ImageEditor/types'\n\ndefineOptions({ name: 'WxImageEditorDialog', inheritAttrs: false })\n\n/*\n * The editor in a panel — all `openImageEditor` is.\n *\n * It is here and not in the editor itself because an editor that always arrived in a\n * dialog could not be put on a page, and a page is where a big one belongs. The buttons\n * are the dialog's, so the editor is asked for `:footer=\"false\"` and driven through its\n * exposed `apply()`.\n *\n * Everything meant for the editor rides through on `$attrs` and is deliberately not\n * declared here. A wrapper that re-declares the props it forwards turns every boolean the\n * caller left alone into `false` — Vue casts an absent Boolean prop rather than leaving it\n * undefined — and the child's own `true` defaults are lost on the way through. That is how\n * the turns and the mirrorings went missing from this panel.\n */\nwithDefaults(\n defineProps<{\n /* Declared because the editor requires it; every other prop rides on $attrs. */\n src: string | Blob\n title?: string\n width?: number | string\n /* The dialog's own buttons, so they are named here and not passed on. */\n saveLabel?: string\n cancelLabel?: string\n }>(),\n {\n title: 'Edit picture',\n width: 760,\n saveLabel: 'Save',\n cancelLabel: 'Cancel',\n },\n)\n\ndefineEmits<{ save: [result: ImageEditorResult] }>()\n\nconst { open, dismiss } = useModal<ImageEditorResult>()\n\nconst editor = useTemplateRef<{ apply: () => Promise<ImageEditorResult | undefined> }>('editor')\nconst busy = ref(false)\n\nasync function save() {\n busy.value = true\n try {\n await editor.value?.apply()\n } finally {\n busy.value = false\n }\n}\n</script>\n\n<template>\n <wx-dialog v-model:open=\"open\" :title=\"title\" :width=\"width\" :close-on-overlay=\"false\">\n <wx-image-editor\n ref=\"editor\"\n v-bind=\"$attrs\"\n :src=\"src\"\n :footer=\"false\"\n @save=\"$emit('save', $event)\"\n />\n\n <template #footer>\n <wx-button variant=\"outline\" :disabled=\"busy\" @click=\"dismiss()\">{{ cancelLabel }}</wx-button>\n <wx-button type=\"primary\" :loading=\"busy\" @click=\"save\">{{ saveLabel }}</wx-button>\n </template>\n </wx-dialog>\n</template>\n","import ImageEditorDialog from '../internal/ImageEditorDialog.vue'\nimport { createModal } from './useModal'\nimport type { ImageEditorModalProps, ImageEditorResult } from '../components/ImageEditor/types'\n\n/**\n * Opens the picture in a panel and answers with what came out of it.\n *\n * ```ts\n * const edited = await openImageEditor({ src: file.url, aspect: 16 / 9 })\n * if (!edited) return\n * await upload(edited.file)\n * ```\n *\n * Nothing is uploaded and nothing is replaced: the answer is a blob, its measurements and\n * the crop it was cut from, and the screen that asked decides where all that goes. Closed\n * without saving — the ✕, escape, Cancel — it answers `undefined`, which is not an error.\n *\n * It is [`createModal`](/guide/modals) over `WxImageEditor` in a dialog, and worth reading\n * as the example: one line names the component, the type of its answer and the event that\n * carries it, and every call site is a single `await`.\n */\nexport const openImageEditor = createModal<ImageEditorResult, ImageEditorModalProps>(\n ImageEditorDialog,\n { resolveOn: 'save' },\n)\n","<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport WxLightbox from '../components/Lightbox/Lightbox.vue'\nimport { useModal } from '../composables/useModal'\nimport type { LightboxSource } from '../components/Lightbox/types'\n\ndefineOptions({ name: 'WxLightboxModal', inheritAttrs: false })\n\n/*\n * The lightbox from code — all `openLightbox` is. Only `items` and `start` are declared; the rest rides\n * through on `$attrs`, so the lightbox's own defaults survive (see `ImageEditorDialog`).\n */\nconst props = withDefaults(defineProps<{ items: LightboxSource[]; start?: number }>(), { start: 0 })\n\nconst { open, dismiss } = useModal<void>()\nconst index = ref(props.start)\n\n/* The host settles on `update:open` of its child, which this wrapper is, not the lightbox. */\nfunction onOpen(value: boolean) {\n if (!value) dismiss()\n}\n</script>\n\n<template>\n <wx-lightbox\n v-bind=\"$attrs\"\n v-model:index=\"index\"\n :items=\"items\"\n :open=\"open\"\n @update:open=\"onOpen\"\n />\n</template>\n","import LightboxModal from '../internal/LightboxModal.vue'\nimport { openModal, type ModalOptions, type ModalPromise } from './useModal'\nimport type { LightboxSource, OpenLightboxOptions } from '../components/Lightbox/types'\n\n/**\n * Opens a gallery over the page, from anywhere:\n *\n * ```ts\n * openLightbox(product.images, 2)\n * openLightbox(['/a.jpg', '/b.jpg'], { start: 1, loop: true })\n * ```\n *\n * It answers nothing — the promise settles, with `undefined`, when the lightbox is closed —\n * and carries `close()` for a gallery that should not outlive something else.\n */\nexport function openLightbox(\n items: LightboxSource[],\n options: number | OpenLightboxOptions = {},\n modal: ModalOptions = {},\n): ModalPromise<void> {\n const props = typeof options === 'number' ? { start: options } : options\n\n return openModal<void>(LightboxModal, {\n ...modal,\n props: { ...modal.props, ...props, items },\n })\n}\n","import { computed, onMounted, ref, watch, type ComputedRef, type Ref } from 'vue'\nimport { useElementWidth } from './useElementWidth'\nimport { usePanelMemory } from './useOverlayPanel'\n\n/** What shape the navigation takes at the width it has been given. */\nexport type ShellLayout = 'sidebar' | 'rail' | 'drawer'\n\nexport interface ResponsiveShellOptions {\n /** Under this width the menu leaves the page for a drawer behind a burger. */\n phone?: number\n /** Under this width the sidebar starts as an icon rail. */\n tablet?: number\n /** Whether it starts as a rail on a screen wide enough for the full sidebar. */\n collapsed?: boolean\n /**\n * Remembers a sidebar that was closed by hand, under this key in `localStorage`.\n * Only the closing is kept: a sidebar left open goes back to following the width,\n * so a desktop opens it and a tablet still starts with the rail.\n */\n persist?: string\n}\n\nexport interface ResponsiveShell {\n /** Width of what is being measured, in pixels. `0` until it has been measured. */\n width: Ref<number>\n layout: ComputedRef<ShellLayout>\n /** Hand this to `WxAside` and `WxMenu` — true for both the rail and the drawer. */\n collapsed: ComputedRef<boolean>\n /** Whether there is room for a sidebar at all. False on a phone. */\n showAside: ComputedRef<boolean>\n drawerOpen: Ref<boolean>\n /**\n * What the one button in the header does: it collapses and expands the sidebar\n * while the sidebar is on the page, and opens the drawer once the menu is gone.\n * The icon follows `layout` — a burger belongs to the drawer alone.\n */\n toggle: () => void\n close: () => void\n}\n\n/** What `persist` keeps: a sidebar that was closed by hand, and nothing else. */\ninterface ShellMemory {\n collapsed: boolean\n}\n\nconst PHONE = 640\nconst TABLET = 1024\n\n/**\n * The rule on its own, so it can be read — and tested — without a browser.\n *\n * `collapsed` is the answer to \"is the sidebar a rail\", and `null` leaves it to the\n * width: a rail from the tablet breakpoint down. Only the phone breakpoint is\n * absolute, because a menu that has nowhere to stand has to leave the page.\n *\n * A width of `0` means nothing has been measured yet: on the server, and on the very\n * first render. The widest shape is the right guess there, since it is the one a\n * desktop gets, and the measurement that follows corrects it before paint.\n */\nexport function shellLayoutFor(\n width: number,\n collapsed: boolean | null,\n options: ResponsiveShellOptions = {},\n): ShellLayout {\n const { phone = PHONE, tablet = TABLET } = options\n\n if (width > 0 && width < phone) return 'drawer'\n\n const rail = collapsed ?? (width > 0 && width < tablet)\n return rail ? 'rail' : 'sidebar'\n}\n\n/**\n * Drives the three shapes an admin sidebar takes — full, icon rail, drawer — from\n * the width of the shell rather than from the viewport's. The two are the same\n * thing on a real page, and they are not inside a preview, a split screen or the\n * demo box on this page, which is the case that catches a viewport media query out.\n *\n * ```ts\n * const shell = useResponsiveShell(shellRef)\n * ```\n *\n * Pass nothing to measure the page itself.\n */\nexport function useResponsiveShell(\n target?: Ref<HTMLElement | null | undefined>,\n options: ResponsiveShellOptions = {},\n): ResponsiveShell {\n const width = useElementWidth(target)\n const drawerOpen = ref(false)\n\n /*\n * What the reader last asked for, or `null` for \"whatever the width suggests\".\n * The two answers are not equal: closing a sidebar is a decision that holds at\n * every width and across reloads, while opening one only says \"not here, not now\"\n * — it is dropped as soon as the screen changes size class, and the width decides\n * again. Otherwise a sidebar opened on a desktop would be waiting on a tablet.\n */\n const preference = ref<boolean | null>(options.collapsed ?? null)\n\n const memory = usePanelMemory<ShellMemory>('wx-shell:', () => options.persist)\n\n const layout = computed(() => shellLayoutFor(width.value, preference.value, options))\n const collapsed = computed(() => layout.value !== 'sidebar')\n const showAside = computed(() => layout.value !== 'drawer')\n\n onMounted(() => {\n /* Read after mounting: the server has no storage, and the markup must match. */\n if (memory.read()?.collapsed) preference.value = true\n })\n\n /** Which size class the screen is in — what an open sidebar is remembered against. */\n const sizeClass = computed<ShellLayout>(() => shellLayoutFor(width.value, null, options))\n\n watch(sizeClass, () => {\n /* The screen changed class, so \"open, here\" has been answered and is let go. */\n if (preference.value === false) preference.value = null\n /* And once the menu is back on the page, the drawer has nothing left to show. */\n if (sizeClass.value !== 'drawer') drawerOpen.value = false\n })\n\n /**\n * The button does the one thing that is visible from where the reader is standing:\n * where the sidebar is on the page it collapses and expands it, and where the menu\n * is gone entirely it is the burger that brings the drawer back.\n */\n function toggle() {\n if (layout.value === 'drawer') {\n drawerOpen.value = !drawerOpen.value\n return\n }\n\n const closing = layout.value !== 'rail'\n preference.value = closing ? true : false\n\n /* Only the closing is worth keeping; an open sidebar is the default anyway. */\n if (closing) memory.write({ collapsed: true })\n else memory.clear()\n }\n\n function close() {\n drawerOpen.value = false\n }\n\n return { width, layout, collapsed, showAside, drawerOpen, toggle, close }\n}\n"],"names":["accordionKey","useAccordion","inject","props","__props","emit","__emit","model","_useModel","provide","computed","watch","value","classes","_createBlock","_unref","AccordionRoot","$event","_renderSlot","_ctx","PAGE","TEXT","SHEET","SLIDES","PDF","ARCHIVE","AUDIO","VIDEO","PICTURE","VECTOR","LAYERED","CODE","FONT","FOLDER","builtinIcons","customIcons","registerIcons","icons","name","content","resolveIcon","iconNames","keywordSizes","boxSize","size","_createElementBlock","accordion","iconPosition","headingTag","AccordionItem","_createElementVNode","_hoisted_1","_createVNode","AccordionHeader","AccordionTrigger","WxIcon","_hoisted_2","_hoisted_3","_hoisted_4","_toDisplayString","$slots","_openBlock","_hoisted_5","AccordionContent","_hoisted_6","hoverable","useHoverPointer","state","ref","query","event","open","width","shut","trigger","useTemplateRef","quietFocus","el","request","next","TooltipProvider","TooltipRoot","TooltipTrigger","TooltipPortal","TooltipContent","_mergeProps","TooltipArrow","actionsKey","useActions","presets","group","preset","icon","tone","accessibleName","tag","nativeAttrs","onClick","_normalizeClass","WxTooltip","_resolveDynamicComponent","$attrs","root","observer","host","publish","bottom","release","track","onMounted","onBeforeUnmount","dropdownKey","useDropdown","close","onPanelClick","PopoverRoot","PopoverTrigger","PopoverPortal","PopoverContent","menuOpen","row","tooWide","collapsed","measure","rowEl","parent","style","padding","available","observe","__expose","WxDropdown","WxAction","stuck","sentinel","watchSentinel","margin","entry","visible","typeIcons","iconName","onClose","slots","useSlots","zoned","toLength","vars","collapsedWidth","formContextKey","formItemContextKey","uid","useId","prefix","useFormField","form","item","fallbackId","id","disabled","status","describedBy","checkboxGroupKey","radioGroupKey","provideFormItem","context","useControlAttrs","attrs","useAttrs","rootAttrs","picked","controlAttrs","rest","key","text","field","debounceTimer","picking","cancelSearch","showClear","hasList","onSelect","option","clear","AutocompleteAnchor","AutocompletePortal","AutocompleteContent","AutocompleteViewport","AutocompleteEmpty","_Fragment","_renderList","AutocompleteItem","TONES","initialsOf","words","hash","total","character","initials","failed","onError","flattenNodes","nodes","node","Fragment","Comment","Text","WxNodes","defineComponent","cloneVNode","avatars","shown","hidden","WxAvatar","_createTextVNode","scroller","offsetOf","element","onScroll","toTop","watched","_Transition","_cache","breadcrumbKey","useBreadcrumb","breadcrumb","isLink","isCurrent","linkAttrs","separatorIcon","separator","buttonGroupKey","useButtonGroup","type","variant","isDisabled","hasHeader","hasSidebar","_hoisted_7","_hoisted_8","activePath","panel","loadedChildren","loadingKeys","keyOf","path","rootOptions","childrenOf","parents","isLeaf","loaded","isLoading","columns","result","index","children","resolvePath","values","level","candidate","findPath","options","found","selectedPath","hasValue","displayLabel","formValue","loadLevel","expand","select","onOptionClick","leaf","onOptionHover","optionsIn","focusOption","items","bounded","onPanelKeydown","target","column","current","nextTick","PopoverAnchor","inputRef","checked","syncIndeterminate","onChange","input","SIGILS","scanMustache","tags","at","from","triple","end","inner","sigil","kind","openSections","before","mustacheProblems","variables","problems","lists","variable","known","section","unknown","marks","Decoration","decorate","view","ranges","mustacheHighlighting","ViewPlugin","update","plugin","WORDS","say","line","replace","whole","exampleOf","example","isList","sectionOf","block","mustacheCompletions","said","byName","pos","start","typed","head","after","to","depth","list","one","nearest","WxCodeEditor","defineAsyncComponent","toggle","locked","WxCheckbox","breakpoints","normalize","span","offset","HEX","toWorking","hex","convertToHsb","parseColor","working","colorToHex","areaStyle","getAreaBackgroundStyle","hueStyle","getSliderBackgroundStyle","swatch","commit","onInput","onBlur","onColor","color","onHex","openPicker","_normalizeStyle","ColorAreaRoot","ColorAreaArea","ColorAreaThumb","ColorSliderRoot","ColorSliderTrack","ColorSliderThumb","display","units","formatCountdown","ms","format","remaining","out","token","unit","toTimestamp","parsed","timer","stop","tick","left","running","WxStatistic","cache","dateFnsLocale","cached","built","build","supported","months","memo","monthNames","days","dayNames","periods","dayPeriodNames","eras","eraNames","quarters","quarterNames","localize","ordinalNumber","match","str","nameMatcher","widths","indexed","contexts","formatLong","weekStartsOn","make","store","names","entries","sorted","a","b","lower","month","day","hour","partOf","date","part","_","weekday","am","pm","era","bc","parts","time","dateTime","pick","formats","first","dateLocaleKey","provideDateLocale","locale","useDateLocale","provided","asked","browserLocale","dateTimezoneKey","provideDateTimezone","timezone","useDateTimezone","readersTimezone","hasTime","modelType","displayFormat","zone","config","timeConfig","inputAttrs","onUpdate","onCleared","_withCtx","slotProps","_normalizeProps","_guardReactiveProps","WxDatePicker","$props","_createSlots","descriptionsKey","useDescriptions","stacked","cssLength","trimmed","pixelLength","clamp","min","max","usePanelMemory","storageKey","raw","GUTTER","hasTitle","hasHead","scrollsInPlace","movable","sizable","layout","memory","panelVars","height","sidebar","dragging","resizing","gesture","begin","rect","move","startDrag","startResize","dx","dy","top","stopListening","reset","restore","saved","onEscape","onInteractOutside","onOpenAutoFocus","onViewportPointerDown","DialogRoot","DialogTrigger","DialogPortal","DialogOverlay","DialogContent","DialogTitle","DialogClose","hasLabel","STEP","horizontal","panelOf","currentSize","maxSize","sizeFrom","startSize","delta","onHandleKeydown","dropdown","defaultImageSize","imageSize","hasMedia","initial","hasMeta","YOUTUBE_HOSTS","YOUTUBE_ID","youTubeId","address","url","youTubeEmbed","playing","resolveVideo","video","embed","src","resolveItem","source","counter","ZOOM_STEP","TAP_SLOP","SWIPE","SWIPE_CLOSE","DOUBLE_TAP_MS","position","many","strip","canPrev","canNext","counterLabel","go","prev","isVideo","zoomable","stage","picture","reactive","drag","resetView","actualScale","img","maxScale","clampPan","box","spareX","spareY","zoomTo","scale","px","py","ratio","zoomIn","zoomOut","canZoomIn","canZoomOut","fromCentre","clientX","clientY","toggleZoom","onWheel","pointers","moving","pinch","lastTap","spread","onPointerDown","onPointerMove","now","onPointerUp","done","onTap","x","y","onPointerCancel","near","pictureStyle","onKeydown","action","step","neighbour","thumbs","thumb","_hoisted_13","_hoisted_17","_hoisted_18","i","_hoisted_21","imageGroupKey","useImageGroup","previewing","onLoad","joined","onCleanup","previewItems","startIndex","lightboxMade","lightboxIndex","openPreview","length","WxLightbox","localesKey","standalone","provideLocales","useLocales","localeLabel","localizedValue","fallback","useLocalized","locales","on","active","chosen","code","read","write","base","nameFor","$emit","TOKEN_NAME","TOKEN","tokenSpans","spans","tokenSegments","segments","tokenQuery","tokenText","tokenAnchor","owner","rectOf","fieldAnchor","caret","textRect","walker","range","useTokenMenu","tokens","browsing","anchor","shallowRef","all","suggest","wasOpen","browse","where","choose","insert","keydown","count","onOutside","reference","placement","placedAt","focused","editing","currentValue","carried","tokenized","rootRef","mirrorRef","hasTokens","listId","segment","syncMirror","mirror","caretAnchor","suggestTokens","insertToken","browseTokens","had","onCaretMove","onFocus","other","WxTokenButton","WxTokenMenu","LocalePicker","answered","confirm","cancel","was","panelStyle","WxButton","PopoverArrow","PopoverClose","useElementWidth","observed","measured","extensionOf","dot","PICTURES","isPicture","subtype","fileIconName","ext","named","extension","glyph","renaming","draft","openLater","openTimers","startRename","selectTimers","stopSelecting","take","commitRename","cancelRename","confirming","removeQuestion","askRemove","confirmRemoval","copied","copiedTimer","copy","copyByHand","confirmCopied","error","area","label","labelWidth","truncated","shows","hasActions","WxImage","WxPopover","WxInput","WxPopconfirm","WxActions","WxDropdownItem","_hoisted_9","errors","toRef","onSubmit","onReset","baseId","errorId","helpId","labelMode","controlId","registerLabelTarget","messages","hasError","isInline","sizeForLevel","onEnter","grid","precision","decimals","round","factor","show","canDecrease","canIncrease","stepBy","direction","pair","SliderTrack","SliderRange","SliderThumb","mark","ratioLabelFor","denominator","numerator","fullCrop","bounds","crop","fitRatio","centreX","centreY","shrink","moveCrop","resizeCrop","handle","point","dirX","dirY","anchorX","anchorY","roomX","roomY","grow","turnCrop","mirrorCrop","axis","fitInside","maxWidth","maxHeight","NEUTRAL","isNeutral","adjust","filterString","luminance","r","g","clampByte","applyAdjustments","pixels","brightness","contrast","saturation","grey","objectUrl","image","natural","ready","busy","rotation","flipX","flipY","widthOverride","filter","touchedFilters","sliders","setAdjustment","touched","adjusted","work","chooseRatio","setCrop","frameStyle","imageStyle","cropStyle","handles","frame","cropBox","pointAt","rounded","beginDraw","onMove","endGesture","corner","turn","flag","fullSize","output","full","setOutputWidth","setOutputHeight","basename","guess","extensions","supportsFilter","encode","canvas","resolve","reject","blob","apply","byHand","zoom","dirty","_withModifiers","WxSegmented","slider","_hoisted_10","_hoisted_11","WxSlider","WxSwitch","_hoisted_12","WxInputNumber","_hoisted_14","_hoisted_15","_hoisted_16","lightboxAttrs","ordered","second","isAttached","markClasses","markStyle","an","Pe","yt","wt","bt","t","e","n","fe","$e","o","Ht","mn","vn","St","bn","yn","Dt","_t","wn","En","Tt","Ke","Sn","Dn","_n","Tn","Ct","Cn","On","Ot","ne","In","Ye","ie","An","xn","Nn","re","ae","xe","It","Te","Lt","Wt","Gt","S","E","We","Pn","Q","At","V","h","ye","jt","te","P","l","s","u","d","f","m","w","xt","ce","we","p","ht","J","Nt","Mn","Fn","Je","Ce","zt","Rn","Ut","Vt","$t","q","Xn","Bn","Yn","ge","Ze","Ne","kn","L","G","R","j","Hn","z","c","O","T","pe","Be","C","ue","Se","Y","be","Oe","$","se","Zt","Qt","W","Me","ve","Ge","je","de","Z","Qe","et","Pt","Mt","me","Ie","Ae","Fe","ke","H","tt","lt","ze","Ve","Re","Ft","Ln","qt","Kt","Wn","Gn","Jt","he","jn","Zn","nt","He","ee","Ee","vt","rn","Xe","B","$n","Vn","X","K","oe","le","k","v","D","A","qn","I","M","F","Un","st","zn","Jn","Kn","N","De","ut","ct","ot","rt","Ue","_e","Qn","Rt","Le","it","en","pt","gt","eo","dt","sn","no","un","kt","tn","nn","Xt","oo","Yt","U","qe","mt","ln","ft","ro","lo","cn","Et","fn","dn","hn","pn","ownId","cardGroup","boardStyle","isFull","isCollapsed","isLocked","columnById","cardTitle","card","nameOf","groupFor","fromIndex","toIndex","via","onCardDrop","fromId","toId","columnOrder","moveColumn","onColumnDrop","grabbed","grabbedColumn","announcement","isGrabbed","isColumnGrabbed","positionOf","refocus","attribute","wanted","elements","onCardKeydown","held","origin","run","stepCard","shiftCard","columnIndex","onColumnKeydown","VueDraggable","WxBadge","WxEntityCard","rel","href","SETTLE","filtersOpen","hasDetail","toPx","settled","need","inline","threshold","previous","filtersInline","detailInline","listAlone","openFilters","closeFilters","back","WxDrawer","showing","loading","delay","menuKey","submenuKey","useMenu","useSubmenu","menu","panelId","ancestors","isTrail","asFlyout","flyoutOpen","isOpen","flyoutSide","chevron","triggerClasses","setOpen","onTriggerClick","OVERFLOW","openKeys","listWidth","splits","fits","measuring","closeSignal","overflowing","inBar","inBranch","lengthOf","gap","room","branch","child","budget","used","positions","seen","trail","here","autoExpand","missing","WxSubmenu","submenu","isActive","page","perPage","currentPerPage","lastPage","currentPage","last","numbers","distance","setPerPage","RADIUS","percent","circumference","thickness","aria","fallbackName","WxRadio","hovered","interactive","stars","fill","valueAt","set","onHover","star","grip","handleSelector","labelOf","record","nameAt","dragged","onLift","onDrop","rowElements","up","down","WxFormScope","sequence","keys","folded","nextKey","keyAt","foldable","atMax","atMin","isInvalid","_item","add","remove","patch","WxSortableList","_withDirectives","_vShow","GLYPH","TONE","WxRichText","viewport","behavior","filterRef","searchText","selection","selectedOptions","singleLabel","hasSelection","openList","displayValue","onSearch","removeTag","ComboboxAnchor","ComboboxTrigger","ComboboxPortal","ComboboxContent","ComboboxViewport","ComboboxEmpty","ComboboxItem","ComboboxItemIndicator","SELECTABLE","valueOf","written","vWxSelect","binding","INTERACTIVE","selecting","selected","isSelected","pointer","started","boxDrag","downTarget","downShift","downToggle","downX","downY","originX","originY","atX","atY","borderLeft","borderTop","candidates","mode","hits","right","caught","drop","have","speed","edge","scrollerOf","scrolls","ownControl","hit","isTouch","capture","pointerId","selectAll","lines","WxSkeletonItem","sizes","stepsKey","useSteps","steps","ids","TabsContent","fetched","useTreeNodes","accessors","expanded","refused","identity","map","walk","parentKey","toValue","filtered","term","keep","matched","isExpandable","isExpanded","rows","expandable","setExpanded","siblings","needsChildren","fetchChildren","collapse","expandAll","collapseAll","openPath","reveal","isAncestorOf","descendants","canDrop","dragKey","dropKey","UTILITY_WIDTH","STORAGE_PREFIX","sort","search","isTree","treeOptions","treeKeyOf","tree","treeRows","treeAt","toggleBranch","rowsFor","dropZone","springKey","springTimer","canDragRow","onRowDragStart","zoneAt","cancelSpring","spring","onRowDragOver","onRowDrop","landed","onRowDragEnd","paginator","showPagination","visibleColumns","utilityCount","columnCount","instance","getCurrentInstance","clickable","onRowClick","asCards","cardColumns","headShift","moreLeft","moreRight","headShiftStyle","scrollStyle","widthOf","colStyle","minStyle","headRow","laidOut","measureColumns","cells","cell","readScroll","remeasure","followPage","tableEl","scrollBoundary","findScrollBoundary","overflow","table","foot","shift","laidOutWidth","offsets","utilities","lefts","order","rights","hasLeftFixed","hasFixed","fixedStyle","pin","fixedClass","utilityStyle","slot","utilityClass","cellText","canSelect","canExpand","selectableRows","selectableKeys","selectedCount","allSelected","someSelected","announce","toggleAll","toggleRow","toggleExpand","sortableIn","onSort","ariaSort","sortState","alignClass","settledSearch","onSearchChanged","settle","save","summaryStart","summarySpan","summaryColumns","summaryValue","summaryText","WxIndicator","WxPagination","_hoisted_22","_hoisted_24","_hoisted_25","_hoisted_27","lineIndex","_hoisted_28","_hoisted_29","_hoisted_31","_hoisted_32","rendered","readTabs","collect","scheduleSelect","WxTab","tabProps","tabSlots","selectFirst","tabs","tab","selectQueued","overflowStart","overflowEnd","scrollable","revealActive","instant","centred","ownWidth","TabsRoot","TabsList","TabsTrigger","highlighted","armed","suggestions","suggestion","showList","clampLines","textareaRef","autosizeOptions","syncHeight","styles","lineHeight","vertical","textarea","choices","choice","buttons","timelineKey","useTimeline","timeline","hasMark","dotClasses","queue","nextId","LEAVING_MS","toastQueue","readonly","dismissToast","toast","removeToast","clearToasts","raise","normalise","extra","api","message","useToast","FOREVER","iconOf","ToastProvider","ToastRoot","ToastTitle","ToastDescription","ToastAction","ToastClose","ToastViewport","sides","ticked","byValue","panels","matches","needle","tickedSet","side","pickable","allTicked","someTicked","tickAll","send","moveOne","listStyle","expandedKeys","selectedKey","checkedKeys","checkedSet","halfChecked","onCheck","canDrag","onDragStart","onDragOver","onDragEnd","keyboardMove","activeKey","focusKey","lookup","paths","given","givenPath","selectedNodes","_node","onChecked","WxTree","files","idFor","file","matchesAccept","rule","incoming","added","onPick","readableSize","bytes","power","WxProgress","modalKey","installed","connectModals","app","contextFor","explicit","handlerFor","camel","letter","listOf","declares","component","openModal","fail","promise","container","gone","unmount","render","finish","listeners","onErrorCaptured","vnode","createModal","defaults","fromHost","useModal","WebxUI","exported","components","registeredName","dismiss","WxDialog","ConfirmDialog","answer","editor","WxImageEditor","openImageEditor","ImageEditorDialog","onOpen","openLightbox","modal","LightboxModal","PHONE","TABLET","shellLayoutFor","phone","tablet","useResponsiveShell","drawerOpen","preference","showAside","sizeClass","closing"],"mappings":"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","x_google_ignoreList":[88]}
|