@sparklingopinions/sparkling-ui 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/aliases.d.ts +4 -0
- package/dist/components/ActionBar/ActionBar.js.map +1 -1
- package/dist/components/ActionBar/ActionBar.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/ActionBar/ActionBar.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Alert/Alert.js.map +1 -1
- package/dist/components/Alert/Alert.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/Alert/Alert.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/AlertDialog/AlertDialog.js.map +1 -1
- package/dist/components/AlertDialog/AlertDialog.vue_vue_type_script_setup_true_lang.js +5 -5
- package/dist/components/AlertDialog/AlertDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Avatar/Avatar.js.map +1 -1
- package/dist/components/Avatar/Avatar.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/Avatar/Avatar.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Badge/Badge.js.map +1 -1
- package/dist/components/Badge/Badge.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/Badge/Badge.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Board/Board.js.map +1 -1
- package/dist/components/Board/Board.vue.d.ts +3 -0
- package/dist/components/Board/Board.vue_vue_type_script_setup_true_lang.js +68 -63
- package/dist/components/Board/Board.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Button/Button.vue_vue_type_script_setup_true_lang.js +23 -22
- package/dist/components/Button/Button.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Calendar/Calendar.js.map +1 -1
- package/dist/components/Calendar/Calendar.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/components/Calendar/Calendar.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/Checkbox/Checkbox.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/DataList/DataList.js.map +1 -1
- package/dist/components/DataList/DataList.vue_vue_type_script_setup_true_lang.js +103 -103
- package/dist/components/DataList/DataList.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Dialog/ContextSeparator.js +19 -0
- package/dist/components/Dialog/ContextSeparator.js.map +1 -0
- package/dist/components/Dialog/ContextSeparator.vue.d.ts +3 -0
- package/dist/components/Dialog/Dialog.js.map +1 -1
- package/dist/components/Dialog/Dialog.vue.d.ts +16 -11
- package/dist/components/Dialog/Dialog.vue_vue_type_script_setup_true_lang.js +130 -119
- package/dist/components/Dialog/Dialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Dialog/focus.d.ts +2 -0
- package/dist/components/Dialog/focus.js +2 -2
- package/dist/components/Dialog/focus.js.map +1 -1
- package/dist/components/EmptyState/EmptyState.js.map +1 -1
- package/dist/components/EmptyState/EmptyState.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/EmptyState/EmptyState.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Filters/FilterChip.js.map +1 -1
- package/dist/components/Filters/FilterChip.vue_vue_type_script_setup_true_lang.js +7 -7
- package/dist/components/Filters/FilterChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Filters/FilterFrame.js.map +1 -1
- package/dist/components/Filters/FilterFrame.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/Filters/FilterFrame.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Filters/FilterMenu.js.map +1 -1
- package/dist/components/Filters/FilterMenu.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/components/Filters/FilterMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Filters/SortMenu.js.map +1 -1
- package/dist/components/Filters/SortMenu.vue_vue_type_script_setup_true_lang.js +7 -7
- package/dist/components/Filters/SortMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Input/Input.js.map +1 -1
- package/dist/components/Input/Input.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/Input/Input.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Kbd/Kbd.js +1 -1
- package/dist/components/Kbd/Kbd.js.map +1 -1
- package/dist/components/Pagination/Pagination.js.map +1 -1
- package/dist/components/Pagination/Pagination.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/Pagination/Pagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Popover/Popover.js.map +1 -1
- package/dist/components/Popover/Popover.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/Popover/Popover.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Popover/PopoverDialog.js.map +1 -1
- package/dist/components/Popover/PopoverDialog.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/Popover/PopoverDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/PropertyList/Editable.js.map +1 -1
- package/dist/components/PropertyList/Editable.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/PropertyList/Editable.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/SegmentedControl/SegmentedControl.js.map +1 -1
- package/dist/components/SegmentedControl/SegmentedControl.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/SegmentedControl/SegmentedControl.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Select/Select.vue_vue_type_script_setup_true_lang.js +4 -4
- package/dist/components/Select/Select.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Skeleton/Skeleton.js.map +1 -1
- package/dist/components/Skeleton/Skeleton.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/Skeleton/Skeleton.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Table/Table.js.map +1 -1
- package/dist/components/Table/Table.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/components/Table/Table.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Tag/Tag.js.map +1 -1
- package/dist/components/Tag/Tag.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/components/Tag/Tag.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Textarea/Textarea.js.map +1 -1
- package/dist/components/Textarea/Textarea.vue.d.ts +3 -0
- package/dist/components/Textarea/Textarea.vue_vue_type_script_setup_true_lang.js +7 -2
- package/dist/components/Textarea/Textarea.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/internal/menu.d.ts +2 -2
- package/dist/components/internal/menu.js +1 -1
- package/dist/components/internal/menu.js.map +1 -1
- package/dist/index.js +15 -15
- package/package.json +1 -1
- package/src/styles/tailwind.css +93 -12
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SortMenu.vue_vue_type_script_setup_true_lang.js","names":["$slots","_useModel","_openBlock","_createBlock","_unref","_withCtx","_renderSlot","_createVNode","Button","_mergeProps","_createElementVNode","_createTextVNode","_toDisplayString","SortArrow","FilterFrame","_createElementBlock","_createCommentVNode","_Fragment","_renderList","_normalizeClass","FilterGlyph","CheckIcon","Button_default","CheckIcon_default","FilterFrame_default","FilterGlyph_default","SortArrow_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","row","SortMenu_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","\"open\"","\"openModifiers\"","props","__props","sort","useModel","open","attrs","useAttrs","custom","useCustomTrigger","current","computed","o","words","type","sortDirections","dirLabel","pickField","field","name","clear","_ctx","openBlock","createBlock","unref","PopoverRoot","_cache","$event","withCtx","PopoverAnchor","renderSlot","PopoverTrigger","createVNode","mergeProps","createElementVNode","createTextVNode","toDisplayString","PopoverPortal","PopoverContent","createElementBlock","createCommentVNode","RadioGroupRoot","Fragment","renderList","RadioGroupItem","option","normalizeClass","dir","i"],"sources":["../../../src/components/Filters/SortMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\n\nimport {\n PopoverAnchor,\n PopoverContent,\n PopoverPortal,\n PopoverRoot,\n PopoverTrigger,\n RadioGroupItem,\n RadioGroupRoot\n} from 'reka-ui'\n\nimport Button from '../Button/Button.vue'\nimport CheckIcon from '../internal/CheckIcon.vue'\nimport FilterFrame from './FilterFrame.vue'\nimport FilterGlyph from './FilterGlyph.vue'\nimport SortArrow from './SortArrow.vue'\nimport { sortDirections } from './defaults'\nimport { type FilterTriggerProps, useCustomTrigger } from './trigger'\nimport type { FilterField, FilterFieldType, ViewSort } from './types'\n\nexport interface SortMenuProps {\n /** The sortable fields. */\n options: FilterField[]\n /** chip: the sort in the view bar, which shows only while there is one. button: the page header's Sort button. */\n as?: 'chip' | 'button'\n /** as=\"button\" only: ghost for a page header. Secondary by default, tinted while sorted. */\n variant?: 'secondary' | 'ghost' | 'tinted'\n /** Boards can't sort: disable the button, with a Tooltip saying why. */\n disabled?: boolean\n status?: string\n /** The two directions' words for each field type, ascending first. */\n directionLabels?: Partial<Record<FilterFieldType, [string, string]>>\n title?: string\n buttonLabel?: string\n clearLabel?: string\n directionLabel?: string\n doneLabel?: string\n closeLabel?: string\n}\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<SortMenuProps>(), {\n as: 'chip',\n variant: undefined,\n status: undefined,\n directionLabels: () => ({}),\n title: 'Sort by',\n buttonLabel: 'Sort',\n clearLabel: 'Clear sort',\n directionLabel: 'Direction',\n doneLabel: 'Done',\n closeLabel: 'Close'\n})\n\nconst sort = defineModel<ViewSort | null>({ default: null })\nconst open = defineModel<boolean>('open', { default: false })\n\ndefineSlots<{\n /** Your own opener in place of the chip or button: spread `props` on it. `label` reads like the chip. */\n trigger?: (props: {\n open: boolean\n toggle: () => void\n active: boolean\n label: string\n props: FilterTriggerProps\n }) => unknown\n}>()\n\nconst attrs = useAttrs()\nconst custom = useCustomTrigger(open)\n\nconst current = computed(() => (sort.value ? props.options.find((o) => o.name === sort.value!.name) : undefined))\nconst words = (type: FilterFieldType) => props.directionLabels[type] ?? sortDirections[type]\nconst dirLabel = computed(() => (current.value ? words(current.value.type)[sort.value!.dir === 'desc' ? 1 : 0] : ''))\n\nfunction pickField(name: string) {\n const field = props.options.find((o) => o.name === name)\n sort.value = { name, dir: sort.value?.name === name ? sort.value.dir : (field?.sortDir ?? 'asc') }\n}\n\nfunction clear() {\n sort.value = null\n open.value = false\n}\n\nconst row =\n 'flex min-h-9 w-full cursor-pointer items-center gap-2.5 rounded-lg px-2 py-1 text-left text-13.5 outline-hidden transition-colors duration-100 focus-visible:sui-ring-inset'\n</script>\n\n<!-- A view's sort: the header's Sort button or the view bar's chip (\"Name, A → Z\") open a panel of fields and a direction. -->\n<template>\n <PopoverRoot v-if=\"$slots.trigger || as === 'button' || current\" v-model:open=\"open\">\n <PopoverAnchor v-if=\"$slots.trigger\" as-child>\n <slot\n :active=\"!!current\"\n :label=\"current ? `${current.label}, ${dirLabel}` : ''\"\n name=\"trigger\"\n :open=\"open\"\n :props=\"custom.props.value\"\n :toggle=\"custom.toggle\"\n />\n </PopoverAnchor>\n <PopoverTrigger v-else-if=\"as === 'button'\" as-child>\n <Button v-bind=\"attrs\" :disabled=\"disabled\" :variant=\"variant ?? (current ? 'tinted' : 'secondary')\">\n <svg\n aria-hidden=\"true\"\n class=\"size-4 fill-none stroke-current\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.5\"\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M5 13V3M2.5 5.5 5 3l2.5 2.5M11 3v10M8.5 10.5 11 13l2.5-2.5\" />\n </svg>\n {{ buttonLabel }}\n </Button>\n </PopoverTrigger>\n <PopoverTrigger\n v-else\n v-bind=\"attrs\"\n class=\"inline-flex h-7.5 items-center gap-1.5 rounded-lg border border-sui-accent-line bg-sui-accent-wash pr-1.5 pl-2 text-13 whitespace-nowrap text-sui-accent outline-hidden transition-[border-color,box-shadow] duration-150 hover:border-sui-accent-bright focus-visible:sui-ring data-[state=open]:border-sui-accent-solid data-[state=open]:shadow-[0_0_0_3px_rgb(var(--sui-focus-ring))]\"\n >\n <SortArrow :dir=\"sort!.dir\" />\n <span\n ><span class=\"font-medium\">{{ current!.label }},</span>{{ ' ' }}{{ dirLabel }}</span\n >\n <svg\n aria-hidden=\"true\"\n class=\"size-3.5 shrink-0 fill-none stroke-current opacity-70\"\n stroke-linecap=\"round\"\n stroke-width=\"2.2\"\n viewBox=\"0 0 24 24\"\n >\n <path d=\"M6 9l6 6 6-6\" />\n </svg>\n </PopoverTrigger>\n <PopoverPortal>\n <PopoverContent\n align=\"start\"\n :aria-label=\"$slots.trigger ? title : undefined\"\n class=\"z-[1100] w-85 max-w-[calc(100vw-2rem)] origin-(--reka-popover-content-transform-origin) rounded-xl border border-sui-line bg-sui-surface text-sui-ink shadow-lg data-[state=open]:animate-sui-overlay-in\"\n :data-sui-panel=\"custom.panelKey\"\n :side-offset=\"8\"\n @close-auto-focus=\"custom.returnFocus\"\n @interact-outside=\"custom.ignoreTrigger\"\n >\n <FilterFrame :close-label=\"closeLabel\" :enter-label=\"doneLabel\" :status=\"status\" @enter=\"open = false\">\n <div class=\"flex h-11 items-center gap-1.5 pr-1.5 pl-3.5 text-sui-ink-muted\">\n <svg\n aria-hidden=\"true\"\n class=\"size-4 fill-none stroke-current\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.5\"\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M5 13V3M2.5 5.5 5 3l2.5 2.5M11 3v10M8.5 10.5 11 13l2.5-2.5\" />\n </svg>\n <span class=\"text-sm font-semibold text-sui-ink\">{{ title }}</span>\n <button\n v-if=\"current\"\n class=\"ml-auto inline-flex h-7 items-center rounded-lg px-2 text-12.5 font-medium text-sui-ink-muted outline-hidden transition-colors duration-150 hover:bg-sui-sunken hover:text-sui-ink focus-visible:sui-ring-inset\"\n type=\"button\"\n @click=\"clear\"\n >\n {{ clearLabel }}\n </button>\n </div>\n <RadioGroupRoot\n :aria-label=\"title\"\n class=\"max-h-64 overflow-auto px-1.5 pt-1 pb-1.5\"\n :model-value=\"sort?.name\"\n @update:model-value=\"pickField($event as string)\"\n >\n <RadioGroupItem\n v-for=\"option in options\"\n :key=\"option.name\"\n :class=\"[\n row,\n option.name === sort?.name\n ? 'bg-sui-accent-wash font-semibold text-sui-accent'\n : 'text-sui-ink hover:bg-sui-sunken'\n ]\"\n :value=\"option.name\"\n >\n <span\n class=\"flex size-6 shrink-0 items-center justify-center rounded-md\"\n :class=\"\n option.name === sort?.name ? 'bg-sui-surface text-sui-accent' : 'bg-sui-sunken text-sui-ink-body'\n \"\n >\n <FilterGlyph :name=\"option.type\" />\n </span>\n <span class=\"min-w-0 flex-1 truncate\">{{ option.label }}</span>\n <CheckIcon v-if=\"option.name === sort?.name\" />\n </RadioGroupItem>\n </RadioGroupRoot>\n <RadioGroupRoot\n v-if=\"current\"\n :aria-label=\"directionLabel\"\n class=\"mx-3 mb-3 grid grid-cols-2 gap-0.5 rounded-lg bg-sui-sunken p-0.75\"\n :model-value=\"sort!.dir\"\n orientation=\"horizontal\"\n @update:model-value=\"sort = { name: sort!.name, dir: $event as ViewSort['dir'] }\"\n >\n <RadioGroupItem\n v-for=\"(dir, i) in ['asc', 'desc'] as const\"\n :key=\"dir\"\n class=\"flex h-9 items-center justify-center gap-1.5 rounded-md text-13 font-medium outline-hidden transition-colors duration-150 focus-visible:sui-ring-inset\"\n :class=\"\n sort!.dir === dir\n ? 'bg-sui-surface text-sui-ink shadow-(--sui-shadow-raised) ring-1 ring-sui-line-subtle'\n : 'text-sui-ink-body hover:text-sui-ink'\n \"\n :value=\"dir\"\n >\n <SortArrow :dir=\"dir\" />\n {{ words(current.type)[i] }}\n </RadioGroupItem>\n </RadioGroupRoot>\n </FilterFrame>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SortMenu.vue_vue_type_script_setup_true_lang.js","names":["$slots","_useModel","_openBlock","_createBlock","_unref","_withCtx","_renderSlot","_createVNode","Button","_mergeProps","_createElementVNode","_createTextVNode","_toDisplayString","SortArrow","FilterFrame","_createElementBlock","_createCommentVNode","_Fragment","_renderList","_normalizeClass","FilterGlyph","CheckIcon","Button_default","CheckIcon_default","FilterFrame_default","FilterGlyph_default","SortArrow_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","row","SortMenu_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","\"open\"","\"openModifiers\"","props","__props","sort","useModel","open","attrs","useAttrs","custom","useCustomTrigger","current","computed","o","words","type","sortDirections","dirLabel","pickField","field","name","clear","_ctx","openBlock","createBlock","unref","PopoverRoot","_cache","$event","withCtx","PopoverAnchor","renderSlot","PopoverTrigger","createVNode","mergeProps","createElementVNode","createTextVNode","toDisplayString","PopoverPortal","PopoverContent","createElementBlock","createCommentVNode","RadioGroupRoot","Fragment","renderList","RadioGroupItem","option","normalizeClass","dir","i"],"sources":["../../../src/components/Filters/SortMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\n\nimport {\n PopoverAnchor,\n PopoverContent,\n PopoverPortal,\n PopoverRoot,\n PopoverTrigger,\n RadioGroupItem,\n RadioGroupRoot\n} from 'reka-ui'\n\nimport Button from '../Button/Button.vue'\nimport CheckIcon from '../internal/CheckIcon.vue'\nimport FilterFrame from './FilterFrame.vue'\nimport FilterGlyph from './FilterGlyph.vue'\nimport SortArrow from './SortArrow.vue'\nimport { sortDirections } from './defaults'\nimport { type FilterTriggerProps, useCustomTrigger } from './trigger'\nimport type { FilterField, FilterFieldType, ViewSort } from './types'\n\nexport interface SortMenuProps {\n /** The sortable fields. */\n options: FilterField[]\n /** chip: the sort in the view bar, which shows only while there is one. button: the page header's Sort button. */\n as?: 'chip' | 'button'\n /** as=\"button\" only: ghost for a page header. Secondary by default, tinted while sorted. */\n variant?: 'secondary' | 'ghost' | 'tinted'\n /** Boards can't sort: disable the button, with a Tooltip saying why. */\n disabled?: boolean\n status?: string\n /** The two directions' words for each field type, ascending first. */\n directionLabels?: Partial<Record<FilterFieldType, [string, string]>>\n title?: string\n buttonLabel?: string\n clearLabel?: string\n directionLabel?: string\n doneLabel?: string\n closeLabel?: string\n}\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<SortMenuProps>(), {\n as: 'chip',\n variant: undefined,\n status: undefined,\n directionLabels: () => ({}),\n title: 'Sort by',\n buttonLabel: 'Sort',\n clearLabel: 'Clear sort',\n directionLabel: 'Direction',\n doneLabel: 'Done',\n closeLabel: 'Close'\n})\n\nconst sort = defineModel<ViewSort | null>({ default: null })\nconst open = defineModel<boolean>('open', { default: false })\n\ndefineSlots<{\n /** Your own opener in place of the chip or button: spread `props` on it. `label` reads like the chip. */\n trigger?: (props: {\n open: boolean\n toggle: () => void\n active: boolean\n label: string\n props: FilterTriggerProps\n }) => unknown\n}>()\n\nconst attrs = useAttrs()\nconst custom = useCustomTrigger(open)\n\nconst current = computed(() => (sort.value ? props.options.find((o) => o.name === sort.value!.name) : undefined))\nconst words = (type: FilterFieldType) => props.directionLabels[type] ?? sortDirections[type]\nconst dirLabel = computed(() => (current.value ? words(current.value.type)[sort.value!.dir === 'desc' ? 1 : 0] : ''))\n\nfunction pickField(name: string) {\n const field = props.options.find((o) => o.name === name)\n sort.value = { name, dir: sort.value?.name === name ? sort.value.dir : (field?.sortDir ?? 'asc') }\n}\n\nfunction clear() {\n sort.value = null\n open.value = false\n}\n\nconst row =\n 'flex min-h-8 w-full cursor-pointer items-center gap-2.5 rounded-lg px-2 py-1 text-left text-13.5 outline-hidden transition-colors duration-100 focus-visible:sui-ring-inset'\n</script>\n\n<!-- A view's sort: the header's Sort button or the view bar's chip (\"Name, A → Z\") open a panel of fields and a direction. -->\n<template>\n <PopoverRoot v-if=\"$slots.trigger || as === 'button' || current\" v-model:open=\"open\">\n <PopoverAnchor v-if=\"$slots.trigger\" as-child>\n <slot\n :active=\"!!current\"\n :label=\"current ? `${current.label}, ${dirLabel}` : ''\"\n name=\"trigger\"\n :open=\"open\"\n :props=\"custom.props.value\"\n :toggle=\"custom.toggle\"\n />\n </PopoverAnchor>\n <PopoverTrigger v-else-if=\"as === 'button'\" as-child>\n <Button v-bind=\"attrs\" :disabled=\"disabled\" :variant=\"variant ?? (current ? 'tinted' : 'secondary')\">\n <svg\n aria-hidden=\"true\"\n class=\"size-4 fill-none stroke-current\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.5\"\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M5 13V3M2.5 5.5 5 3l2.5 2.5M11 3v10M8.5 10.5 11 13l2.5-2.5\" />\n </svg>\n {{ buttonLabel }}\n </Button>\n </PopoverTrigger>\n <PopoverTrigger\n v-else\n v-bind=\"attrs\"\n class=\"inline-flex h-7.5 items-center gap-1.5 rounded-lg border border-sui-accent-line bg-sui-accent-wash pr-1.5 pl-2 text-13 whitespace-nowrap text-sui-accent outline-hidden transition-[border-color,box-shadow] duration-150 hover:border-sui-accent-bright focus-visible:sui-ring data-[state=open]:border-sui-accent-solid data-[state=open]:shadow-[0_0_0_3px_rgb(var(--sui-focus-ring))]\"\n >\n <SortArrow :dir=\"sort!.dir\" />\n <span\n ><span class=\"font-medium\">{{ current!.label }},</span>{{ ' ' }}{{ dirLabel }}</span\n >\n <svg\n aria-hidden=\"true\"\n class=\"size-3.5 shrink-0 fill-none stroke-current opacity-70\"\n stroke-linecap=\"round\"\n stroke-width=\"2.2\"\n viewBox=\"0 0 24 24\"\n >\n <path d=\"M6 9l6 6 6-6\" />\n </svg>\n </PopoverTrigger>\n <PopoverPortal>\n <PopoverContent\n align=\"start\"\n :aria-label=\"$slots.trigger ? title : undefined\"\n class=\"z-[1100] w-85 max-w-[calc(100vw-2rem)] origin-(--reka-popover-content-transform-origin) rounded-xl border border-sui-edge bg-sui-raised text-sui-ink shadow-lg data-[state=open]:animate-sui-overlay-in\"\n :data-sui-panel=\"custom.panelKey\"\n :side-offset=\"8\"\n @close-auto-focus=\"custom.returnFocus\"\n @interact-outside=\"custom.ignoreTrigger\"\n >\n <FilterFrame :close-label=\"closeLabel\" :enter-label=\"doneLabel\" :status=\"status\" @enter=\"open = false\">\n <div class=\"flex h-11 items-center gap-1.5 pr-1.5 pl-3.5 text-sui-ink-muted\">\n <svg\n aria-hidden=\"true\"\n class=\"size-4 fill-none stroke-current\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.5\"\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M5 13V3M2.5 5.5 5 3l2.5 2.5M11 3v10M8.5 10.5 11 13l2.5-2.5\" />\n </svg>\n <span class=\"text-sm font-semibold text-sui-ink\">{{ title }}</span>\n <button\n v-if=\"current\"\n class=\"ml-auto inline-flex h-7 items-center rounded-lg px-2 text-12.5 font-medium text-sui-ink-muted outline-hidden transition-colors duration-150 hover:bg-sui-fill-hover hover:text-sui-ink focus-visible:sui-ring-inset\"\n type=\"button\"\n @click=\"clear\"\n >\n {{ clearLabel }}\n </button>\n </div>\n <RadioGroupRoot\n :aria-label=\"title\"\n class=\"max-h-64 overflow-auto px-1.5 pt-1 pb-1.5\"\n :model-value=\"sort?.name\"\n @update:model-value=\"pickField($event as string)\"\n >\n <RadioGroupItem\n v-for=\"option in options\"\n :key=\"option.name\"\n :class=\"[\n row,\n option.name === sort?.name\n ? 'bg-sui-accent-wash font-semibold text-sui-accent'\n : 'text-sui-ink hover:bg-sui-fill-hover'\n ]\"\n :value=\"option.name\"\n >\n <span\n class=\"flex size-6 shrink-0 items-center justify-center rounded-md\"\n :class=\"\n option.name === sort?.name\n ? 'bg-sui-lifted text-sui-accent shadow-(--sui-shadow-lifted)'\n : 'bg-sui-fill text-sui-ink-body'\n \"\n >\n <FilterGlyph :name=\"option.type\" />\n </span>\n <span class=\"min-w-0 flex-1 truncate\">{{ option.label }}</span>\n <CheckIcon v-if=\"option.name === sort?.name\" />\n </RadioGroupItem>\n </RadioGroupRoot>\n <RadioGroupRoot\n v-if=\"current\"\n :aria-label=\"directionLabel\"\n class=\"mx-3 mb-3 grid grid-cols-2 gap-0.5 rounded-lg bg-sui-track p-0.75 ring-1 ring-sui-fill-line ring-inset\"\n :model-value=\"sort!.dir\"\n orientation=\"horizontal\"\n @update:model-value=\"sort = { name: sort!.name, dir: $event as ViewSort['dir'] }\"\n >\n <RadioGroupItem\n v-for=\"(dir, i) in ['asc', 'desc'] as const\"\n :key=\"dir\"\n class=\"flex h-7 items-center justify-center gap-1.5 rounded-md text-13 font-medium outline-hidden transition-colors duration-150 focus-visible:sui-ring-inset\"\n :class=\"\n sort!.dir === dir\n ? 'bg-sui-lifted text-sui-ink shadow-(--sui-shadow-lifted)'\n : 'text-sui-ink-body hover:text-sui-ink'\n \"\n :value=\"dir\"\n >\n <SortArrow :dir=\"dir\" />\n {{ words(current.type)[i] }}\n </RadioGroupItem>\n </RadioGroupRoot>\n </FilterFrame>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n</template>\n"],"mappings":";;;;;;;;;;A,mNAwFM+B,IACJ,+K;;;;;;;;;;;;;;;;;;;;;;;;;;;EA7CF,IAAMM,IAAQC,GAaRC,IAAOtC,EAA4BqC,GAAA,YAAkB,GACrDG,IAAOxC,EAAoBqC,GAAC,MAA0B,GAatDI,IAAQC,EAAS,GACjBC,IAASC,EAAiBJ,CAAI,GAE9BK,IAAUC,QAAgBR,EAAK,QAAQF,EAAM,QAAQ,MAAM,MAAMW,EAAE,SAAST,EAAK,MAAO,IAAI,IAAI,KAAA,CAAU,GAC1GU,KAAS,MAA0BZ,EAAM,gBAAgBa,MAASC,EAAeD,IACjFE,IAAWL,QAAgBD,EAAQ,QAAQG,EAAMH,EAAQ,MAAM,IAAI,CAAC,CAAC,IAAK,MAAO,QAAQ,WAAkB,EAAG;EAEpH,SAASO,EAAU,GAAc;GAC/B,IAAMC,IAAQjB,EAAM,QAAQ,MAAM,MAAMW,EAAE,SAASO,CAAI;GACvD,EAAK,QAAQ;IAAE;IAAM,KAAKhB,EAAK,OAAO,SAASgB,IAAOhB,EAAK,MAAM,MAAOe,GAAO,WAAW;GAAO;EACnG;EAEA,SAASE,IAAQ;GAEf,AADA,EAAK,QAAQ,MACb,EAAK,QAAQ;EACf;E,iBAQqBxD,EAAAA,OAAO,WAAWsC,EAAA,OAAE,YAAiBQ,EAAA,SAAxD5C,EAAA,GAAAC,EAsIcC,EAAAyD,CAAA,GAAA;;GAtI2D,MAAMpB,EAAA;GAAA,iBAAA,AAAAqB,EAAA,QAAA,MAAA,EAAI,QAAAC;;GACjF,SAAA1D,QASgB,CATKL,EAAAA,OAAO,WAA5BE,EAAA,GAAAC,EASgBC,EAAA6D,CAAA,GAAA;;IATqB,YAAA;;IACnC,SAAA5D,QAOE,CAPFC,EAOEmD,EAAA,QAAA,WAAA;KANC,QAAM,CAAA,CAAIX,EAAA;KACV,OAAOA,EAAA,QAAO,GAAMA,EAAA,MAAQ,MAAK,IAAKM,EAAA,UAAQ;KAE9C,MAAMX,EAAA;KACN,OAAOrC,EAAAwC,CAAA,CAAM,CAAC,MAAM;KACpB,QAAQxC,EAAAwC,CAAA,CAAM,CAAC;;;G,MAGON,EAAA,OAAE,YAA7BpC,EAAA,GAAAC,EAciBC,EAAA+D,CAAA,GAAA;;IAd2B,YAAA;;IAC1C,SAAA9D,QAYS,CAZTE,EAYSC,GAZTC,EAAgBL,EAYPsC,CAAA,GAZY;KAAG,UAAUJ,EAAA;KAAW,SAASA,EAAA,YAAYQ,EAAA,QAAO,WAAA;;KACvE,SAAAzC,QASM,CATN,AAAAyD,EAAA,OAAApD,EASM,OAAA;MARJ,eAAY;MACZ,OAAM;MACN,kBAAe;MACf,mBAAgB;MAChB,gBAAa;MACb,SAAQ;K,IAERA,EAAuE,QAAA,EAAjE,GAAE,6DAA4D,CAAA,C,QAChEC,EAAA,MACNC,EAAG0B,EAAA,WAAW,GAAA,CAAA,C;;;;G,OAGlBpC,EAAA,GAAAC,EAkBiBC,EAAA+D,CAAA,GAlBjB1D,EAkBiB,EAAA,KAAA,EAAA,GAhBPL,EAAAsC,CAAA,GAAK,EACb,OAAM,4XAA2X,CAAA,GAAA;IAEjY,SAAArC,QAA8B;KAA9BE,EAA8BM,GAAA,EAAlB,KAAK0B,EAAA,MAAM,I;KACvB7B,EAEC,QAAA,MAAA,CADEA,EAAsD,QAAtDiB,GAAsDf,EAAzBkC,EAAA,MAAS,KAAK,IAAG,KAAC,CAAA,GAAUnC,EAAAC,EAAA,GAAG,IAAAA,EAAMwC,EAAA,KAAQ,GAAA,CAAA,C;KAE7E,AAAAU,EAAA,OAAApD,EAQM,OAAA;MAPJ,eAAY;MACZ,OAAM;MACN,kBAAe;MACf,gBAAa;MACb,SAAQ;K,IAERA,EAAyB,QAAA,EAAnB,GAAE,eAAc,CAAA,C;;;G,SAG1BH,EAwFgBH,EAAAqE,CAAA,GAAA,MAAA;IAvFd,SAAApE,QAsFiB,CAtFjBE,EAsFiBH,EAAAsE,CAAA,GAAA;KArFf,OAAM;KACL,cAAY1E,EAAAA,OAAO,UAAUsC,EAAA,QAAQ,KAAA;KACtC,OAAM;KACL,kBAAgBlC,EAAAwC,CAAA,CAAM,CAAC;KACvB,eAAa;KACb,kBAAkBxC,EAAAwC,CAAA,CAAM,CAAC;KACzB,mBAAkBxC,EAAAwC,CAAA,CAAM,CAAC;;KAE1B,SAAAvC,QA4Ec,CA5EdE,EA4EcO,GAAA;MA5EA,eAAawB,EAAA;MAAa,eAAaA,EAAA;MAAY,QAAQA,EAAA;MAAS,SAAK,AAAAwB,EAAA,QAAA,MAAE,EAAA,QAAI;;MAC3F,SAAAzD,QAoBM;OApBNK,EAoBM,OApBNkB,GAoBM;QAnBJ,AAAAkC,EAAA,OAAApD,EASM,OAAA;SARJ,eAAY;SACZ,OAAM;SACN,kBAAe;SACf,mBAAgB;SAChB,gBAAa;SACb,SAAQ;Q,IAERA,EAAuE,QAAA,EAAjE,GAAE,6DAA4D,CAAA,C;QAEtEA,EAAmE,QAAnEmB,GAAmEjB,EAAf0B,EAAA,KAAK,GAAA,CAAA;QAEjDQ,EAAA,SADR5C,EAAA,GAAAa,EAOS,UAAA;;SALP,OAAM;SACN,MAAK;SACJ,SAAOyC;QAEL,GAAA5C,EAAA0B,EAAA,UAAU,GAAA,CAAA,K;;OAGjB/B,EA8BiBH,EAAAyE,CAAA,GAAA;QA7Bd,cAAYvC,EAAA;QACb,OAAM;QACL,eAAaC,EAAA,OAAM;QACnB,uBAAkB,AAAAuB,EAAA,QAAA,MAAET,EAAUU,CAAM;;QAGnC,SAAA1D,QAAyB,EAD3BH,EAAA,EAAA,GAAAa,EAuBiBE,GAAA,MAAAC,EAtBEoB,EAAA,UAAV,OADTpC,EAAA,GAAAC,EAuBiBC,EAAA4E,CAAA,GAAA;SArBd,KAAKC,EAAO;SACZ,OAAK9D,EAAA,CAAoBY,GAAqBkD,EAAO,SAAS1C,EAAA,OAAM,O;SAMpE,OAAO0C,EAAO;;SAEf,SAAA5E,QASO;UATPK,EASO,QAAA,EARL,OAAKS,EAAA,CAAC,+DACqB8D,EAAO,SAAS1C,EAAA,OAAM,O,qGAMjDhC,EAAmCa,GAAA,EAArB,MAAM6D,EAAO,K;UAE7BvE,EAA+D,QAA/DoB,GAA+DlB,EAAtBqE,EAAO,KAAK,GAAA,CAAA;UACpCA,EAAO,SAAS1C,EAAA,OAAM,QAAvCrC,EAAA,GAAAC,EAA+CkB,GAAA,EAAA,KAAA,EAAA,CAAA,K;;;;;;OAI3CyB,EAAA,SADR5C,EAAA,GAAAC,EAsBiBC,EAAAyE,CAAA,GAAA;;QApBd,cAAYvC,EAAA;QACb,OAAM;QACL,eAAaC,EAAA,MAAM;QACpB,aAAY;QACX,uBAAkB,AAAAuB,EAAA,QAAA,MAAE,EAAA,QAAI;SAAA,MAAWvB,EAAA,MAAM;SAAI,KAAOwB;QAAM;;QAGzD,SAAA1D,QAA4C,EAD9CH,EAAA,GAAAa,EAaiBE,GAAA,MAAAC,EAZI,CAAA,OAAA,MAAA,IAAX,GAAK,MADfX,EAaiBH,EAAA4E,CAAA,GAAA;SAXd,KAAKG;SACN,OAAKhE,EAAA,CAAC,0JACmBoB,EAAA,MAAM,QAAQ4C,I;SAKtC,OAAOA;;SAER,SAAA9E,QAAwB,CAAxBE,EAAwBM,GAAA,EAAP,OAAG,GAAA,MAAA,GAAA,CAAA,KAAA,CAAA,GAAIF,EAAA,MACxBC,EAAGqC,EAAMH,EAAA,MAAQ,IAAI,CAAA,CAAEsC,EAAC,GAAA,CAAA,C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.js","names":["_sfc_main","Input_vue_vue_type_script_setup_true_lang_default","Input_default"],"sources":["../../../src/components/Input/Input.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useFieldControl } from '../FormField/context'\n\nexport interface InputProps {\n /** Marks the field as failing validation: a danger border and `aria-invalid`. */\n invalid?: boolean\n disabled?: boolean\n}\n\nconst props = defineProps<InputProps>()\n\nconst model = defineModel<string | null>()\n\nconst { attrs: fieldAttrs, invalid: isInvalid } = useFieldControl(\n () => model.value,\n () => props.invalid\n)\n</script>\n\n<!-- Attributes (id, type, placeholder, readonly, autocomplete...) land on the input itself. -->\n<template>\n <input\n v-bind=\"fieldAttrs\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n class=\"m-0 h-
|
|
1
|
+
{"version":3,"file":"Input.js","names":["_sfc_main","Input_vue_vue_type_script_setup_true_lang_default","Input_default"],"sources":["../../../src/components/Input/Input.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useFieldControl } from '../FormField/context'\n\nexport interface InputProps {\n /** Marks the field as failing validation: a danger border and `aria-invalid`. */\n invalid?: boolean\n disabled?: boolean\n}\n\nconst props = defineProps<InputProps>()\n\nconst model = defineModel<string | null>()\n\nconst { attrs: fieldAttrs, invalid: isInvalid } = useFieldControl(\n () => model.value,\n () => props.invalid\n)\n</script>\n\n<!-- Attributes (id, type, placeholder, readonly, autocomplete...) land on the input itself. -->\n<template>\n <input\n v-bind=\"fieldAttrs\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n class=\"m-0 h-(--sui-control-height) w-full appearance-none rounded-lg border bg-sui-fill px-3 font-sans text-sm leading-none text-sui-ink transition-[border-color,box-shadow,background-color] duration-200 placeholder:text-sui-ink-faint\"\n :class=\"[\n isInvalid ? 'border-sui-danger-mid' : 'border-sui-fill-line hover:bg-sui-fill-hover',\n disabled\n ? 'pointer-events-none cursor-default opacity-60 select-none'\n : 'focus:border-sui-accent focus:bg-transparent focus:ring-0 focus-visible:sui-ring-field'\n ]\"\n :disabled=\"disabled\"\n :value=\"model ?? ''\"\n @input=\"model = ($event.target as HTMLInputElement).value\"\n />\n</template>\n"],"mappings":""}
|
|
@@ -19,7 +19,7 @@ var c = [
|
|
|
19
19
|
let r = n, l = s(n, "modelValue"), { attrs: u, invalid: d } = e(() => l.value, () => r.invalid);
|
|
20
20
|
return (e, r) => (a(), t("input", i(o(u), {
|
|
21
21
|
"aria-invalid": o(d) ? "true" : void 0,
|
|
22
|
-
class: ["m-0 h-
|
|
22
|
+
class: ["m-0 h-(--sui-control-height) w-full appearance-none rounded-lg border bg-sui-fill px-3 font-sans text-sm leading-none text-sui-ink transition-[border-color,box-shadow,background-color] duration-200 placeholder:text-sui-ink-faint", [o(d) ? "border-sui-danger-mid" : "border-sui-fill-line hover:bg-sui-fill-hover", n.disabled ? "pointer-events-none cursor-default opacity-60 select-none" : "focus:border-sui-accent focus:bg-transparent focus:ring-0 focus-visible:sui-ring-field"]],
|
|
23
23
|
disabled: n.disabled,
|
|
24
24
|
value: l.value ?? "",
|
|
25
25
|
onInput: r[0] ||= (e) => l.value = e.target.value
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_mergeProps","_unref","_hoisted_1","Input_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","props","__props","model","useModel","fieldAttrs","isInvalid","useFieldControl","openBlock","createElementBlock","mergeProps","unref","_cache","$event"],"sources":["../../../src/components/Input/Input.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useFieldControl } from '../FormField/context'\n\nexport interface InputProps {\n /** Marks the field as failing validation: a danger border and `aria-invalid`. */\n invalid?: boolean\n disabled?: boolean\n}\n\nconst props = defineProps<InputProps>()\n\nconst model = defineModel<string | null>()\n\nconst { attrs: fieldAttrs, invalid: isInvalid } = useFieldControl(\n () => model.value,\n () => props.invalid\n)\n</script>\n\n<!-- Attributes (id, type, placeholder, readonly, autocomplete...) land on the input itself. -->\n<template>\n <input\n v-bind=\"fieldAttrs\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n class=\"m-0 h-
|
|
1
|
+
{"version":3,"file":"Input.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_mergeProps","_unref","_hoisted_1","Input_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","props","__props","model","useModel","fieldAttrs","isInvalid","useFieldControl","openBlock","createElementBlock","mergeProps","unref","_cache","$event"],"sources":["../../../src/components/Input/Input.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useFieldControl } from '../FormField/context'\n\nexport interface InputProps {\n /** Marks the field as failing validation: a danger border and `aria-invalid`. */\n invalid?: boolean\n disabled?: boolean\n}\n\nconst props = defineProps<InputProps>()\n\nconst model = defineModel<string | null>()\n\nconst { attrs: fieldAttrs, invalid: isInvalid } = useFieldControl(\n () => model.value,\n () => props.invalid\n)\n</script>\n\n<!-- Attributes (id, type, placeholder, readonly, autocomplete...) land on the input itself. -->\n<template>\n <input\n v-bind=\"fieldAttrs\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n class=\"m-0 h-(--sui-control-height) w-full appearance-none rounded-lg border bg-sui-fill px-3 font-sans text-sm leading-none text-sui-ink transition-[border-color,box-shadow,background-color] duration-200 placeholder:text-sui-ink-faint\"\n :class=\"[\n isInvalid ? 'border-sui-danger-mid' : 'border-sui-fill-line hover:bg-sui-fill-hover',\n disabled\n ? 'pointer-events-none cursor-default opacity-60 select-none'\n : 'focus:border-sui-accent focus:bg-transparent focus:ring-0 focus-visible:sui-ring-field'\n ]\"\n :disabled=\"disabled\"\n :value=\"model ?? ''\"\n @input=\"model = ($event.target as HTMLInputElement).value\"\n />\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;EASA,IAAMS,IAAQC,GAERC,IAAQX,EAA0BU,GAAA,YAAC,GAEnC,EAAE,OAAOG,GAAY,SAASC,MAAcC,QAC1CJ,EAAM,aACNF,EAAM,OACd;E,kBAKER,EAAA,GAAAC,EAaE,SAbFC,EACUC,EAYRS,CAAA,GAZkB;GACjB,gBAAcT,EAAAU,CAAA,IAAS,SAAY,KAAA;GACpC,OAAK,CAAC,wOAAsO,CAC5NV,EAAAU,CAAA,IAAS,0BAAA,gDAAmFJ,EAAA,W;GAM3G,UAAUA,EAAA;GACV,OAAOC,EAAA,SAAK;GACZ,SAAK,AAAAS,EAAA,QAAA,MAAE,EAAA,QAASC,EAAO,OAA4B"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import e from "../../_virtual/_plugin-vue_export-helper.js";
|
|
2
2
|
import { createElementBlock as t, openBlock as n, renderSlot as r } from "vue";
|
|
3
3
|
//#region src/components/Kbd/Kbd.vue
|
|
4
|
-
var i = {}, a = { class: "inline-flex h-5 min-w-5 items-center justify-center rounded-[5px] border border-
|
|
4
|
+
var i = {}, a = { class: "inline-flex h-5 min-w-5 items-center justify-center rounded-[5px] border border-sui-fill-line bg-sui-fill px-1.25 font-sans text-11 leading-none font-medium text-sui-ink-subtle" };
|
|
5
5
|
function o(e, i) {
|
|
6
6
|
return n(), t("kbd", a, [r(e.$slots, "default")]);
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Kbd.js","names":["_openBlock","_createElementBlock","_renderSlot","_plugin_vue_export_helper_default","_sfc_main","_hoisted_1","_sfc_render","openBlock","createElementBlock","renderSlot","_ctx","Kbd_default"],"sources":["../../../src/components/Kbd/Kbd.vue"],"sourcesContent":["<!-- A key or shortcut, e.g. Esc or ⌘K. -->\n<template>\n <kbd\n class=\"inline-flex h-5 min-w-5 items-center justify-center rounded-[5px] border border-
|
|
1
|
+
{"version":3,"file":"Kbd.js","names":["_openBlock","_createElementBlock","_renderSlot","_plugin_vue_export_helper_default","_sfc_main","_hoisted_1","_sfc_render","openBlock","createElementBlock","renderSlot","_ctx","Kbd_default"],"sources":["../../../src/components/Kbd/Kbd.vue"],"sourcesContent":["<!-- A key or shortcut, e.g. Esc or ⌘K. -->\n<template>\n <kbd\n class=\"inline-flex h-5 min-w-5 items-center justify-center rounded-[5px] border border-sui-fill-line bg-sui-fill px-1.25 font-sans text-11 leading-none font-medium text-sui-ink-subtle\"\n ><slot\n /></kbd>\n</template>\n"],"mappings":";;;A,YAGIK,IAAA,EAAA,OAAM,mLAAkL;;CAD1L,OAAAL,EAAA,GAAAC,EAGQ,OAHRI,GAGQ,CADLH,EACDQ,EAAA,QAAA,SAAA,C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Pagination.js","names":["_sfc_main","Pagination_vue_vue_type_script_setup_true_lang_default","Pagination_default"],"sources":["../../../src/components/Pagination/Pagination.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport { paginationItems } from './items'\n\nexport interface PaginationProps {\n pageCount: number\n /** Pages shown on each side of the current one. */\n siblingCount?: number\n /** Pages always shown at each end. */\n boundaryCount?: number\n /** Shows first and last page buttons. */\n showEnds?: boolean\n disabled?: boolean\n /** The navigation landmark's name. */\n label?: string\n firstLabel?: string\n previousLabel?: string\n nextLabel?: string\n lastLabel?: string\n /** Each page button's name; `{page}` is its number. */\n pageLabel?: string\n}\n\nconst props = withDefaults(defineProps<PaginationProps>(), {\n siblingCount: 1,\n boundaryCount: 1,\n showEnds: true,\n label: 'Pagination',\n firstLabel: 'First page',\n previousLabel: 'Previous page',\n nextLabel: 'Next page',\n lastLabel: 'Last page',\n pageLabel: 'Page {page}'\n})\n\nconst page = defineModel<number>('page', { default: 1 })\n\nconst controls = computed(() => [\n ...(props.showEnds ? (['first'] as const) : []),\n 'previous' as const,\n ...paginationItems(page.value, props.pageCount, props.siblingCount, props.boundaryCount),\n 'next' as const,\n ...(props.showEnds ? (['last'] as const) : [])\n])\n\nfunction go(target: number) {\n if (!props.disabled && target >= 1 && target <= props.pageCount) page.value = target\n}\n\nconst arrows = computed(() => {\n const atStart = page.value <= 1\n const atEnd = page.value >= props.pageCount\n return {\n first: { label: props.firstLabel, target: 1, off: atStart, path: 'M8 3 3 8l5 5M13 3 8 8l5 5' },\n previous: { label: props.previousLabel, target: page.value - 1, off: atStart, path: 'M10 3 5 8l5 5' },\n next: { label: props.nextLabel, target: page.value + 1, off: atEnd, path: 'm6 3 5 5-5 5' },\n last: { label: props.lastLabel, target: props.pageCount, off: atEnd, path: 'm3 3 5 5-5 5m5-10 5 5-5 5' }\n }\n})\n\nconst button =\n 'inline-flex h-7 min-w-7 items-center justify-center rounded-(--sui-radius-button) px-1.5 text-13 font-medium tabular-nums transition-colors duration-150 focus-visible:sui-ring disabled:cursor-default disabled:opacity-50'\nconst idle = 'text-sui-ink-body enabled:hover:bg-sui-
|
|
1
|
+
{"version":3,"file":"Pagination.js","names":["_sfc_main","Pagination_vue_vue_type_script_setup_true_lang_default","Pagination_default"],"sources":["../../../src/components/Pagination/Pagination.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport { paginationItems } from './items'\n\nexport interface PaginationProps {\n pageCount: number\n /** Pages shown on each side of the current one. */\n siblingCount?: number\n /** Pages always shown at each end. */\n boundaryCount?: number\n /** Shows first and last page buttons. */\n showEnds?: boolean\n disabled?: boolean\n /** The navigation landmark's name. */\n label?: string\n firstLabel?: string\n previousLabel?: string\n nextLabel?: string\n lastLabel?: string\n /** Each page button's name; `{page}` is its number. */\n pageLabel?: string\n}\n\nconst props = withDefaults(defineProps<PaginationProps>(), {\n siblingCount: 1,\n boundaryCount: 1,\n showEnds: true,\n label: 'Pagination',\n firstLabel: 'First page',\n previousLabel: 'Previous page',\n nextLabel: 'Next page',\n lastLabel: 'Last page',\n pageLabel: 'Page {page}'\n})\n\nconst page = defineModel<number>('page', { default: 1 })\n\nconst controls = computed(() => [\n ...(props.showEnds ? (['first'] as const) : []),\n 'previous' as const,\n ...paginationItems(page.value, props.pageCount, props.siblingCount, props.boundaryCount),\n 'next' as const,\n ...(props.showEnds ? (['last'] as const) : [])\n])\n\nfunction go(target: number) {\n if (!props.disabled && target >= 1 && target <= props.pageCount) page.value = target\n}\n\nconst arrows = computed(() => {\n const atStart = page.value <= 1\n const atEnd = page.value >= props.pageCount\n return {\n first: { label: props.firstLabel, target: 1, off: atStart, path: 'M8 3 3 8l5 5M13 3 8 8l5 5' },\n previous: { label: props.previousLabel, target: page.value - 1, off: atStart, path: 'M10 3 5 8l5 5' },\n next: { label: props.nextLabel, target: page.value + 1, off: atEnd, path: 'm6 3 5 5-5 5' },\n last: { label: props.lastLabel, target: props.pageCount, off: atEnd, path: 'm3 3 5 5-5 5m5-10 5 5-5 5' }\n }\n})\n\nconst button =\n 'inline-flex h-7 min-w-7 items-center justify-center rounded-(--sui-radius-button) px-1.5 text-13 font-medium tabular-nums transition-colors duration-150 focus-visible:sui-ring disabled:cursor-default disabled:opacity-50'\nconst idle = 'text-sui-ink-body enabled:hover:bg-sui-fill-hover enabled:hover:text-sui-ink'\n</script>\n\n<!-- A table's paginator: first, previous, the pages with gaps, next, last. The current page is a solid accent tile. -->\n<template>\n <nav :aria-label=\"label\" class=\"flex items-center gap-0.5\">\n <template v-for=\"control in controls\" :key=\"control\">\n <span\n v-if=\"control === 'gap-start' || control === 'gap-end'\"\n aria-hidden=\"true\"\n class=\"inline-flex size-7 items-center justify-center text-13 text-sui-ink-muted select-none\"\n >…</span\n >\n <button\n v-else-if=\"typeof control === 'string'\"\n :aria-label=\"arrows[control].label\"\n :class=\"[button, idle]\"\n :disabled=\"disabled || arrows[control].off\"\n :title=\"arrows[control].label\"\n type=\"button\"\n @click=\"go(arrows[control].target)\"\n >\n <svg\n aria-hidden=\"true\"\n class=\"size-4 fill-none stroke-current\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.5\"\n viewBox=\"0 0 16 16\"\n >\n <path :d=\"arrows[control].path\" />\n </svg>\n </button>\n <button\n v-else\n :aria-current=\"control === page ? 'page' : undefined\"\n :aria-label=\"pageLabel.replace('{page}', String(control))\"\n :class=\"[button, control === page ? 'bg-sui-accent-solid font-semibold text-sui-on-accent' : idle]\"\n :disabled=\"disabled\"\n type=\"button\"\n @click=\"go(control)\"\n >\n {{ control }}\n </button>\n </template>\n </nav>\n</template>\n"],"mappings":""}
|
|
@@ -22,7 +22,7 @@ var f = ["aria-label"], p = {
|
|
|
22
22
|
"aria-label",
|
|
23
23
|
"disabled",
|
|
24
24
|
"onClick"
|
|
25
|
-
], v = "inline-flex h-7 min-w-7 items-center justify-center rounded-(--sui-radius-button) px-1.5 text-13 font-medium tabular-nums transition-colors duration-150 focus-visible:sui-ring disabled:cursor-default disabled:opacity-50", y = "text-sui-ink-body enabled:hover:bg-sui-
|
|
25
|
+
], v = "inline-flex h-7 min-w-7 items-center justify-center rounded-(--sui-radius-button) px-1.5 text-13 font-medium tabular-nums transition-colors duration-150 focus-visible:sui-ring disabled:cursor-default disabled:opacity-50", y = "text-sui-ink-body enabled:hover:bg-sui-fill-hover enabled:hover:text-sui-ink", b = /*@__PURE__*/ a({
|
|
26
26
|
__name: "Pagination",
|
|
27
27
|
props: /*@__PURE__*/ o({
|
|
28
28
|
pageCount: {},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Pagination.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_Fragment","_renderList","_normalizeClass","_createElementVNode","_toDisplayString","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","button","idle","Pagination_vue_vue_type_script_setup_true_lang_default","\"page\"","\"pageModifiers\"","props","__props","page","useModel","controls","computed","paginationItems","go","target","arrows","atStart","atEnd","openBlock","createElementBlock","Fragment","renderList","control","normalizeClass","createElementVNode","toDisplayString"],"sources":["../../../src/components/Pagination/Pagination.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport { paginationItems } from './items'\n\nexport interface PaginationProps {\n pageCount: number\n /** Pages shown on each side of the current one. */\n siblingCount?: number\n /** Pages always shown at each end. */\n boundaryCount?: number\n /** Shows first and last page buttons. */\n showEnds?: boolean\n disabled?: boolean\n /** The navigation landmark's name. */\n label?: string\n firstLabel?: string\n previousLabel?: string\n nextLabel?: string\n lastLabel?: string\n /** Each page button's name; `{page}` is its number. */\n pageLabel?: string\n}\n\nconst props = withDefaults(defineProps<PaginationProps>(), {\n siblingCount: 1,\n boundaryCount: 1,\n showEnds: true,\n label: 'Pagination',\n firstLabel: 'First page',\n previousLabel: 'Previous page',\n nextLabel: 'Next page',\n lastLabel: 'Last page',\n pageLabel: 'Page {page}'\n})\n\nconst page = defineModel<number>('page', { default: 1 })\n\nconst controls = computed(() => [\n ...(props.showEnds ? (['first'] as const) : []),\n 'previous' as const,\n ...paginationItems(page.value, props.pageCount, props.siblingCount, props.boundaryCount),\n 'next' as const,\n ...(props.showEnds ? (['last'] as const) : [])\n])\n\nfunction go(target: number) {\n if (!props.disabled && target >= 1 && target <= props.pageCount) page.value = target\n}\n\nconst arrows = computed(() => {\n const atStart = page.value <= 1\n const atEnd = page.value >= props.pageCount\n return {\n first: { label: props.firstLabel, target: 1, off: atStart, path: 'M8 3 3 8l5 5M13 3 8 8l5 5' },\n previous: { label: props.previousLabel, target: page.value - 1, off: atStart, path: 'M10 3 5 8l5 5' },\n next: { label: props.nextLabel, target: page.value + 1, off: atEnd, path: 'm6 3 5 5-5 5' },\n last: { label: props.lastLabel, target: props.pageCount, off: atEnd, path: 'm3 3 5 5-5 5m5-10 5 5-5 5' }\n }\n})\n\nconst button =\n 'inline-flex h-7 min-w-7 items-center justify-center rounded-(--sui-radius-button) px-1.5 text-13 font-medium tabular-nums transition-colors duration-150 focus-visible:sui-ring disabled:cursor-default disabled:opacity-50'\nconst idle = 'text-sui-ink-body enabled:hover:bg-sui-
|
|
1
|
+
{"version":3,"file":"Pagination.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_Fragment","_renderList","_normalizeClass","_createElementVNode","_toDisplayString","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","button","idle","Pagination_vue_vue_type_script_setup_true_lang_default","\"page\"","\"pageModifiers\"","props","__props","page","useModel","controls","computed","paginationItems","go","target","arrows","atStart","atEnd","openBlock","createElementBlock","Fragment","renderList","control","normalizeClass","createElementVNode","toDisplayString"],"sources":["../../../src/components/Pagination/Pagination.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport { paginationItems } from './items'\n\nexport interface PaginationProps {\n pageCount: number\n /** Pages shown on each side of the current one. */\n siblingCount?: number\n /** Pages always shown at each end. */\n boundaryCount?: number\n /** Shows first and last page buttons. */\n showEnds?: boolean\n disabled?: boolean\n /** The navigation landmark's name. */\n label?: string\n firstLabel?: string\n previousLabel?: string\n nextLabel?: string\n lastLabel?: string\n /** Each page button's name; `{page}` is its number. */\n pageLabel?: string\n}\n\nconst props = withDefaults(defineProps<PaginationProps>(), {\n siblingCount: 1,\n boundaryCount: 1,\n showEnds: true,\n label: 'Pagination',\n firstLabel: 'First page',\n previousLabel: 'Previous page',\n nextLabel: 'Next page',\n lastLabel: 'Last page',\n pageLabel: 'Page {page}'\n})\n\nconst page = defineModel<number>('page', { default: 1 })\n\nconst controls = computed(() => [\n ...(props.showEnds ? (['first'] as const) : []),\n 'previous' as const,\n ...paginationItems(page.value, props.pageCount, props.siblingCount, props.boundaryCount),\n 'next' as const,\n ...(props.showEnds ? (['last'] as const) : [])\n])\n\nfunction go(target: number) {\n if (!props.disabled && target >= 1 && target <= props.pageCount) page.value = target\n}\n\nconst arrows = computed(() => {\n const atStart = page.value <= 1\n const atEnd = page.value >= props.pageCount\n return {\n first: { label: props.firstLabel, target: 1, off: atStart, path: 'M8 3 3 8l5 5M13 3 8 8l5 5' },\n previous: { label: props.previousLabel, target: page.value - 1, off: atStart, path: 'M10 3 5 8l5 5' },\n next: { label: props.nextLabel, target: page.value + 1, off: atEnd, path: 'm6 3 5 5-5 5' },\n last: { label: props.lastLabel, target: props.pageCount, off: atEnd, path: 'm3 3 5 5-5 5m5-10 5 5-5 5' }\n }\n})\n\nconst button =\n 'inline-flex h-7 min-w-7 items-center justify-center rounded-(--sui-radius-button) px-1.5 text-13 font-medium tabular-nums transition-colors duration-150 focus-visible:sui-ring disabled:cursor-default disabled:opacity-50'\nconst idle = 'text-sui-ink-body enabled:hover:bg-sui-fill-hover enabled:hover:text-sui-ink'\n</script>\n\n<!-- A table's paginator: first, previous, the pages with gaps, next, last. The current page is a solid accent tile. -->\n<template>\n <nav :aria-label=\"label\" class=\"flex items-center gap-0.5\">\n <template v-for=\"control in controls\" :key=\"control\">\n <span\n v-if=\"control === 'gap-start' || control === 'gap-end'\"\n aria-hidden=\"true\"\n class=\"inline-flex size-7 items-center justify-center text-13 text-sui-ink-muted select-none\"\n >…</span\n >\n <button\n v-else-if=\"typeof control === 'string'\"\n :aria-label=\"arrows[control].label\"\n :class=\"[button, idle]\"\n :disabled=\"disabled || arrows[control].off\"\n :title=\"arrows[control].label\"\n type=\"button\"\n @click=\"go(arrows[control].target)\"\n >\n <svg\n aria-hidden=\"true\"\n class=\"size-4 fill-none stroke-current\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.5\"\n viewBox=\"0 0 16 16\"\n >\n <path :d=\"arrows[control].path\" />\n </svg>\n </button>\n <button\n v-else\n :aria-current=\"control === page ? 'page' : undefined\"\n :aria-label=\"pageLabel.replace('{page}', String(control))\"\n :class=\"[button, control === page ? 'bg-sui-accent-solid font-semibold text-sui-on-accent' : idle]\"\n :disabled=\"disabled\"\n type=\"button\"\n @click=\"go(control)\"\n >\n {{ control }}\n </button>\n </template>\n </nav>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;A,GA6DMc,IACJ,+NACIC,IAAO,gF;;;;;;;;;;;;;;;;;;;;;;;EAvCb,IAAMI,IAAQC,GAYRC,IAAOrB,EAAmBoB,GAAC,MAAsB,GAEjDG,IAAWC,QAAe;GAC9B,GAAIL,EAAM,WAAY,CAAC,OAAO,IAAc,CAAC;GAC7C;GACA,GAAGM,EAAgBJ,EAAK,OAAOF,EAAM,WAAWA,EAAM,cAAcA,EAAM,aAAa;GACvF;GACA,GAAIA,EAAM,WAAY,CAAC,MAAM,IAAc,CAAC;EAC9C,CAAC;EAED,SAASO,EAAG,GAAgB;GAC1B,AAAI,CAACP,EAAM,YAAYQ,KAAU,KAAKA,KAAUR,EAAM,cAAW,EAAK,QAAQQ;EAChF;EAEA,IAAMC,IAASJ,QAAe;GAC5B,IAAMK,IAAUR,EAAK,SAAS,GACxBS,IAAQT,EAAK,SAASF,EAAM;GAClC,OAAO;IACL,OAAO;KAAE,OAAOA,EAAM;KAAY,QAAQ;KAAG,KAAKU;KAAS,MAAM;IAA4B;IAC7F,UAAU;KAAE,OAAOV,EAAM;KAAe,QAAQE,EAAK,QAAQ;KAAG,KAAKQ;KAAS,MAAM;IAAgB;IACpG,MAAM;KAAE,OAAOV,EAAM;KAAW,QAAQE,EAAK,QAAQ;KAAG,KAAKS;KAAO,MAAM;IAAe;IACzF,MAAM;KAAE,OAAOX,EAAM;KAAW,QAAQA,EAAM;KAAW,KAAKW;KAAO,MAAM;IAA4B;GACzG;EACF,CAAC;E,kBASC7B,EAAA,GAAAC,EAwCM,OAAA;GAxCA,cAAYkB,EAAA;GAAO,OAAM;E,KAC7BnB,EAAA,EAAA,GAAAC,EAsCWC,GAAA,MAAAC,EAtCiBmB,EAAA,QAAX,OAA2BtB,EAAA,GAAAC,EAAAC,GAAA,EAAA,KAAAgC,EAAO,GAAA,CAEzCA,MAAO,eAAoBA,MAAO,aAD1ClC,EAAA,GAAAC,EAKC,QALDO,GAIG,GAAC,KAGgB,OAAA0B,KAAO,YAD3BlC,EAAA,GAAAC,EAmBS,UAAA;;GAjBN,cAAY0B,EAAA,MAAOO,EAAO,CAAE;GAC5B,OAAK9B,EAAA,CAAGS,GAAQC,CAAI,CAAA;GACpB,UAAUK,EAAA,YAAYQ,EAAA,MAAOO,EAAO,CAAE;GACtC,OAAOP,EAAA,MAAOO,EAAO,CAAE;GACxB,MAAK;GACJ,UAAK,MAAET,EAAGE,EAAA,MAAOO,EAAO,CAAE,MAAM;E,KAEjClC,EAAA,GAAAC,EASM,OATNS,GASM,CADJL,EAAkC,QAAA,EAA3B,GAAGsB,EAAA,MAAOO,EAAO,CAAE,K,+BAG9BlC,EAAA,GAAAC,EAUS,UAAA;;GARN,gBAAciC,MAAYd,EAAA,QAAI,SAAY,KAAA;GAC1C,cAAYD,EAAA,UAAU,QAAO,UAAW,OAAOe,CAAO,CAAA;GACtD,OAAK9B,EAAA,CAAGS,GAAQqB,MAAYd,EAAA,QAAI,yDAA4DN,CAAI,CAAA;GAChG,UAAUK,EAAA;GACX,MAAK;GACJ,UAAK,MAAEM,EAAGS,CAAO;EAEf,GAAA5B,EAAA4B,CAAO,GAAA,IAAAtB,CAAA,E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Popover.js","names":["_sfc_main","Popover_vue_vue_type_script_setup_true_lang_default","Popover_default"],"sources":["../../../src/components/Popover/Popover.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onBeforeUnmount, ref, useAttrs, watch } from 'vue'\n\nimport { PopoverAnchor, PopoverContent, PopoverPortal, PopoverRoot } from 'reka-ui'\n\nexport interface PopoverProps {\n /** The gap to the anchor, in px; negative overlaps it. */\n offset?: number\n /** Shifts it along the anchor's edge, in px. */\n alignOffset?: number\n closeOnEscape?: boolean\n /** The panel's width, e.g. `20rem`. */\n width?: string\n}\n\n// Root is Reka's renderless PopoverRoot: class and attributes belong on the panel.\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<PopoverProps>(), {\n offset: 4,\n alignOffset: 0,\n closeOnEscape: true,\n width: '16rem'\n})\n\nconst emit = defineEmits<{ show: []; hide: [] }>()\n\nconst attrs = useAttrs()\n\nconst open = ref(false)\nconst anchor = ref<HTMLElement>()\n// What was clicked to open it; clicks on it toggle the popover rather than counting as outside.\nconst opener = ref<HTMLElement>()\nconst label = ref<string>()\n// A press outside closes it and leaves focus to what was pressed.\nlet pressedOutside = false\n\n/** Opens below the event's element, or below `target` when given. */\nfunction show(event: Event, target?: HTMLElement) {\n opener.value = event.currentTarget as HTMLElement\n anchor.value = target ?? opener.value\n // A dialog needs a name: an aria-label given to the popover, or else the name of the element it opened from.\n label.value =\n (attrs['aria-label'] as string | undefined) ??\n opener.value?.getAttribute('aria-label') ??\n opener.value?.textContent?.trim()\n pressedOutside = false\n open.value = true\n}\n\nfunction hide() {\n open.value = false\n}\n\nfunction toggle(event: Event, target?: HTMLElement) {\n if (open.value) hide()\n else show(event, target)\n}\n\ndefineExpose({ show, hide, toggle })\n\nfunction isOnAnchor(target: EventTarget | null) {\n return target instanceof Node && [anchor.value, opener.value].some((el) => el?.contains(target))\n}\n\nfunction onPointerDownOutside(event: CustomEvent<{ originalEvent: PointerEvent }>) {\n if (isOnAnchor(event.detail.originalEvent.target)) event.preventDefault()\n else pressedOutside = true\n}\n\nfunction onEscape(event: KeyboardEvent) {\n if (!props.closeOnEscape) event.preventDefault()\n}\n\n// Otherwise focus left in the panel goes back to the anchor.\nfunction onCloseAutoFocus(event: Event) {\n event.preventDefault()\n const active = document.activeElement\n const inPanel = !active || active === document.body || (event.target as HTMLElement).contains(active)\n if (inPanel && !pressedOutside) anchor.value?.focus()\n}\n\n// Focus goes to an [autofocus] element inside, or else the panel, so Tab moves through it and Escape works at once.\n// The event comes from Reka's positioning wrapper around the panel.\nfunction onOpenAutoFocus(event: Event) {\n event.preventDefault()\n const wrapper = event.target as HTMLElement | null\n const panel = wrapper?.querySelector<HTMLElement>('[role=\"dialog\"]')\n ;(panel?.querySelector<HTMLElement>('[autofocus]') ?? panel)?.focus()\n}\n\n// It closes when the page moves under it: a scrolling ancestor of the anchor, or a resized window.\nfunction onScroll(event: Event) {\n if (event.target instanceof Node && event.target.contains(anchor.value ?? null)) hide()\n}\n\nwatch(open, (isOpen) => {\n if (isOpen) {\n window.addEventListener('scroll', onScroll, true)\n window.addEventListener('resize', hide)\n emit('show')\n } else {\n window.removeEventListener('scroll', onScroll, true)\n window.removeEventListener('resize', hide)\n emit('hide')\n }\n})\n\nonBeforeUnmount(() => {\n window.removeEventListener('scroll', onScroll, true)\n window.removeEventListener('resize', hide)\n})\n</script>\n\n<template>\n <PopoverRoot v-model:open=\"open\">\n <PopoverAnchor :reference=\"anchor\" />\n <PopoverPortal>\n <PopoverContent\n v-bind=\"$attrs\"\n align=\"start\"\n :align-offset=\"alignOffset\"\n :aria-label=\"label\"\n class=\"z-[1100] block max-h-(--reka-popover-content-available-height) origin-center overflow-y-auto rounded-
|
|
1
|
+
{"version":3,"file":"Popover.js","names":["_sfc_main","Popover_vue_vue_type_script_setup_true_lang_default","Popover_default"],"sources":["../../../src/components/Popover/Popover.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onBeforeUnmount, ref, useAttrs, watch } from 'vue'\n\nimport { PopoverAnchor, PopoverContent, PopoverPortal, PopoverRoot } from 'reka-ui'\n\nexport interface PopoverProps {\n /** The gap to the anchor, in px; negative overlaps it. */\n offset?: number\n /** Shifts it along the anchor's edge, in px. */\n alignOffset?: number\n closeOnEscape?: boolean\n /** The panel's width, e.g. `20rem`. */\n width?: string\n}\n\n// Root is Reka's renderless PopoverRoot: class and attributes belong on the panel.\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<PopoverProps>(), {\n offset: 4,\n alignOffset: 0,\n closeOnEscape: true,\n width: '16rem'\n})\n\nconst emit = defineEmits<{ show: []; hide: [] }>()\n\nconst attrs = useAttrs()\n\nconst open = ref(false)\nconst anchor = ref<HTMLElement>()\n// What was clicked to open it; clicks on it toggle the popover rather than counting as outside.\nconst opener = ref<HTMLElement>()\nconst label = ref<string>()\n// A press outside closes it and leaves focus to what was pressed.\nlet pressedOutside = false\n\n/** Opens below the event's element, or below `target` when given. */\nfunction show(event: Event, target?: HTMLElement) {\n opener.value = event.currentTarget as HTMLElement\n anchor.value = target ?? opener.value\n // A dialog needs a name: an aria-label given to the popover, or else the name of the element it opened from.\n label.value =\n (attrs['aria-label'] as string | undefined) ??\n opener.value?.getAttribute('aria-label') ??\n opener.value?.textContent?.trim()\n pressedOutside = false\n open.value = true\n}\n\nfunction hide() {\n open.value = false\n}\n\nfunction toggle(event: Event, target?: HTMLElement) {\n if (open.value) hide()\n else show(event, target)\n}\n\ndefineExpose({ show, hide, toggle })\n\nfunction isOnAnchor(target: EventTarget | null) {\n return target instanceof Node && [anchor.value, opener.value].some((el) => el?.contains(target))\n}\n\nfunction onPointerDownOutside(event: CustomEvent<{ originalEvent: PointerEvent }>) {\n if (isOnAnchor(event.detail.originalEvent.target)) event.preventDefault()\n else pressedOutside = true\n}\n\nfunction onEscape(event: KeyboardEvent) {\n if (!props.closeOnEscape) event.preventDefault()\n}\n\n// Otherwise focus left in the panel goes back to the anchor.\nfunction onCloseAutoFocus(event: Event) {\n event.preventDefault()\n const active = document.activeElement\n const inPanel = !active || active === document.body || (event.target as HTMLElement).contains(active)\n if (inPanel && !pressedOutside) anchor.value?.focus()\n}\n\n// Focus goes to an [autofocus] element inside, or else the panel, so Tab moves through it and Escape works at once.\n// The event comes from Reka's positioning wrapper around the panel.\nfunction onOpenAutoFocus(event: Event) {\n event.preventDefault()\n const wrapper = event.target as HTMLElement | null\n const panel = wrapper?.querySelector<HTMLElement>('[role=\"dialog\"]')\n ;(panel?.querySelector<HTMLElement>('[autofocus]') ?? panel)?.focus()\n}\n\n// It closes when the page moves under it: a scrolling ancestor of the anchor, or a resized window.\nfunction onScroll(event: Event) {\n if (event.target instanceof Node && event.target.contains(anchor.value ?? null)) hide()\n}\n\nwatch(open, (isOpen) => {\n if (isOpen) {\n window.addEventListener('scroll', onScroll, true)\n window.addEventListener('resize', hide)\n emit('show')\n } else {\n window.removeEventListener('scroll', onScroll, true)\n window.removeEventListener('resize', hide)\n emit('hide')\n }\n})\n\nonBeforeUnmount(() => {\n window.removeEventListener('scroll', onScroll, true)\n window.removeEventListener('resize', hide)\n})\n</script>\n\n<template>\n <PopoverRoot v-model:open=\"open\">\n <PopoverAnchor :reference=\"anchor\" />\n <PopoverPortal>\n <PopoverContent\n v-bind=\"$attrs\"\n align=\"start\"\n :align-offset=\"alignOffset\"\n :aria-label=\"label\"\n class=\"z-[1100] block max-h-(--reka-popover-content-available-height) origin-center overflow-y-auto rounded-xl outline-hidden border border-sui-edge bg-sui-raised text-sui-ink shadow-xl data-[state=closed]:animate-sui-overlay-out data-[state=open]:animate-sui-overlay-in\"\n :collision-padding=\"8\"\n side=\"bottom\"\n :side-offset=\"offset\"\n :style=\"{ width }\"\n @close-auto-focus=\"onCloseAutoFocus\"\n @escape-key-down=\"onEscape\"\n @focus-outside.prevent\n @open-auto-focus=\"onOpenAutoFocus\"\n @pointer-down-outside=\"onPointerDownOutside\"\n >\n <slot :hide=\"hide\" />\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n</template>\n"],"mappings":""}
|
|
@@ -65,7 +65,7 @@ var _ = /*@__PURE__*/ n({
|
|
|
65
65
|
align: "start",
|
|
66
66
|
"align-offset": n.alignOffset,
|
|
67
67
|
"aria-label": T.value,
|
|
68
|
-
class: "z-[1100] block max-h-(--reka-popover-content-available-height) origin-center overflow-y-auto rounded-
|
|
68
|
+
class: "z-[1100] block max-h-(--reka-popover-content-available-height) origin-center overflow-y-auto rounded-xl outline-hidden border border-sui-edge bg-sui-raised text-sui-ink shadow-xl data-[state=closed]:animate-sui-overlay-out data-[state=open]:animate-sui-overlay-in",
|
|
69
69
|
"collision-padding": 8,
|
|
70
70
|
side: "bottom",
|
|
71
71
|
"side-offset": n.offset,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Popover.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_openBlock","_createBlock","_unref","_withCtx","_createVNode","_mergeProps","_withModifiers","_renderSlot","Popover_vue_vue_type_script_setup_true_lang_default","__expose","__emit","props","__props","emit","attrs","useAttrs","open","ref","anchor","opener","label","pressedOutside","show","event","target","hide","toggle","isOnAnchor","el","onPointerDownOutside","onEscape","onCloseAutoFocus","active","onOpenAutoFocus","panel","onScroll","watch","isOpen","onBeforeUnmount","openBlock","createBlock","unref","PopoverRoot","_cache","$event","withCtx","createVNode","PopoverAnchor","PopoverPortal","PopoverContent","mergeProps","_ctx","withModifiers","renderSlot"],"sources":["../../../src/components/Popover/Popover.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onBeforeUnmount, ref, useAttrs, watch } from 'vue'\n\nimport { PopoverAnchor, PopoverContent, PopoverPortal, PopoverRoot } from 'reka-ui'\n\nexport interface PopoverProps {\n /** The gap to the anchor, in px; negative overlaps it. */\n offset?: number\n /** Shifts it along the anchor's edge, in px. */\n alignOffset?: number\n closeOnEscape?: boolean\n /** The panel's width, e.g. `20rem`. */\n width?: string\n}\n\n// Root is Reka's renderless PopoverRoot: class and attributes belong on the panel.\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<PopoverProps>(), {\n offset: 4,\n alignOffset: 0,\n closeOnEscape: true,\n width: '16rem'\n})\n\nconst emit = defineEmits<{ show: []; hide: [] }>()\n\nconst attrs = useAttrs()\n\nconst open = ref(false)\nconst anchor = ref<HTMLElement>()\n// What was clicked to open it; clicks on it toggle the popover rather than counting as outside.\nconst opener = ref<HTMLElement>()\nconst label = ref<string>()\n// A press outside closes it and leaves focus to what was pressed.\nlet pressedOutside = false\n\n/** Opens below the event's element, or below `target` when given. */\nfunction show(event: Event, target?: HTMLElement) {\n opener.value = event.currentTarget as HTMLElement\n anchor.value = target ?? opener.value\n // A dialog needs a name: an aria-label given to the popover, or else the name of the element it opened from.\n label.value =\n (attrs['aria-label'] as string | undefined) ??\n opener.value?.getAttribute('aria-label') ??\n opener.value?.textContent?.trim()\n pressedOutside = false\n open.value = true\n}\n\nfunction hide() {\n open.value = false\n}\n\nfunction toggle(event: Event, target?: HTMLElement) {\n if (open.value) hide()\n else show(event, target)\n}\n\ndefineExpose({ show, hide, toggle })\n\nfunction isOnAnchor(target: EventTarget | null) {\n return target instanceof Node && [anchor.value, opener.value].some((el) => el?.contains(target))\n}\n\nfunction onPointerDownOutside(event: CustomEvent<{ originalEvent: PointerEvent }>) {\n if (isOnAnchor(event.detail.originalEvent.target)) event.preventDefault()\n else pressedOutside = true\n}\n\nfunction onEscape(event: KeyboardEvent) {\n if (!props.closeOnEscape) event.preventDefault()\n}\n\n// Otherwise focus left in the panel goes back to the anchor.\nfunction onCloseAutoFocus(event: Event) {\n event.preventDefault()\n const active = document.activeElement\n const inPanel = !active || active === document.body || (event.target as HTMLElement).contains(active)\n if (inPanel && !pressedOutside) anchor.value?.focus()\n}\n\n// Focus goes to an [autofocus] element inside, or else the panel, so Tab moves through it and Escape works at once.\n// The event comes from Reka's positioning wrapper around the panel.\nfunction onOpenAutoFocus(event: Event) {\n event.preventDefault()\n const wrapper = event.target as HTMLElement | null\n const panel = wrapper?.querySelector<HTMLElement>('[role=\"dialog\"]')\n ;(panel?.querySelector<HTMLElement>('[autofocus]') ?? panel)?.focus()\n}\n\n// It closes when the page moves under it: a scrolling ancestor of the anchor, or a resized window.\nfunction onScroll(event: Event) {\n if (event.target instanceof Node && event.target.contains(anchor.value ?? null)) hide()\n}\n\nwatch(open, (isOpen) => {\n if (isOpen) {\n window.addEventListener('scroll', onScroll, true)\n window.addEventListener('resize', hide)\n emit('show')\n } else {\n window.removeEventListener('scroll', onScroll, true)\n window.removeEventListener('resize', hide)\n emit('hide')\n }\n})\n\nonBeforeUnmount(() => {\n window.removeEventListener('scroll', onScroll, true)\n window.removeEventListener('resize', hide)\n})\n</script>\n\n<template>\n <PopoverRoot v-model:open=\"open\">\n <PopoverAnchor :reference=\"anchor\" />\n <PopoverPortal>\n <PopoverContent\n v-bind=\"$attrs\"\n align=\"start\"\n :align-offset=\"alignOffset\"\n :aria-label=\"label\"\n class=\"z-[1100] block max-h-(--reka-popover-content-available-height) origin-center overflow-y-auto rounded-
|
|
1
|
+
{"version":3,"file":"Popover.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_openBlock","_createBlock","_unref","_withCtx","_createVNode","_mergeProps","_withModifiers","_renderSlot","Popover_vue_vue_type_script_setup_true_lang_default","__expose","__emit","props","__props","emit","attrs","useAttrs","open","ref","anchor","opener","label","pressedOutside","show","event","target","hide","toggle","isOnAnchor","el","onPointerDownOutside","onEscape","onCloseAutoFocus","active","onOpenAutoFocus","panel","onScroll","watch","isOpen","onBeforeUnmount","openBlock","createBlock","unref","PopoverRoot","_cache","$event","withCtx","createVNode","PopoverAnchor","PopoverPortal","PopoverContent","mergeProps","_ctx","withModifiers","renderSlot"],"sources":["../../../src/components/Popover/Popover.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onBeforeUnmount, ref, useAttrs, watch } from 'vue'\n\nimport { PopoverAnchor, PopoverContent, PopoverPortal, PopoverRoot } from 'reka-ui'\n\nexport interface PopoverProps {\n /** The gap to the anchor, in px; negative overlaps it. */\n offset?: number\n /** Shifts it along the anchor's edge, in px. */\n alignOffset?: number\n closeOnEscape?: boolean\n /** The panel's width, e.g. `20rem`. */\n width?: string\n}\n\n// Root is Reka's renderless PopoverRoot: class and attributes belong on the panel.\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<PopoverProps>(), {\n offset: 4,\n alignOffset: 0,\n closeOnEscape: true,\n width: '16rem'\n})\n\nconst emit = defineEmits<{ show: []; hide: [] }>()\n\nconst attrs = useAttrs()\n\nconst open = ref(false)\nconst anchor = ref<HTMLElement>()\n// What was clicked to open it; clicks on it toggle the popover rather than counting as outside.\nconst opener = ref<HTMLElement>()\nconst label = ref<string>()\n// A press outside closes it and leaves focus to what was pressed.\nlet pressedOutside = false\n\n/** Opens below the event's element, or below `target` when given. */\nfunction show(event: Event, target?: HTMLElement) {\n opener.value = event.currentTarget as HTMLElement\n anchor.value = target ?? opener.value\n // A dialog needs a name: an aria-label given to the popover, or else the name of the element it opened from.\n label.value =\n (attrs['aria-label'] as string | undefined) ??\n opener.value?.getAttribute('aria-label') ??\n opener.value?.textContent?.trim()\n pressedOutside = false\n open.value = true\n}\n\nfunction hide() {\n open.value = false\n}\n\nfunction toggle(event: Event, target?: HTMLElement) {\n if (open.value) hide()\n else show(event, target)\n}\n\ndefineExpose({ show, hide, toggle })\n\nfunction isOnAnchor(target: EventTarget | null) {\n return target instanceof Node && [anchor.value, opener.value].some((el) => el?.contains(target))\n}\n\nfunction onPointerDownOutside(event: CustomEvent<{ originalEvent: PointerEvent }>) {\n if (isOnAnchor(event.detail.originalEvent.target)) event.preventDefault()\n else pressedOutside = true\n}\n\nfunction onEscape(event: KeyboardEvent) {\n if (!props.closeOnEscape) event.preventDefault()\n}\n\n// Otherwise focus left in the panel goes back to the anchor.\nfunction onCloseAutoFocus(event: Event) {\n event.preventDefault()\n const active = document.activeElement\n const inPanel = !active || active === document.body || (event.target as HTMLElement).contains(active)\n if (inPanel && !pressedOutside) anchor.value?.focus()\n}\n\n// Focus goes to an [autofocus] element inside, or else the panel, so Tab moves through it and Escape works at once.\n// The event comes from Reka's positioning wrapper around the panel.\nfunction onOpenAutoFocus(event: Event) {\n event.preventDefault()\n const wrapper = event.target as HTMLElement | null\n const panel = wrapper?.querySelector<HTMLElement>('[role=\"dialog\"]')\n ;(panel?.querySelector<HTMLElement>('[autofocus]') ?? panel)?.focus()\n}\n\n// It closes when the page moves under it: a scrolling ancestor of the anchor, or a resized window.\nfunction onScroll(event: Event) {\n if (event.target instanceof Node && event.target.contains(anchor.value ?? null)) hide()\n}\n\nwatch(open, (isOpen) => {\n if (isOpen) {\n window.addEventListener('scroll', onScroll, true)\n window.addEventListener('resize', hide)\n emit('show')\n } else {\n window.removeEventListener('scroll', onScroll, true)\n window.removeEventListener('resize', hide)\n emit('hide')\n }\n})\n\nonBeforeUnmount(() => {\n window.removeEventListener('scroll', onScroll, true)\n window.removeEventListener('resize', hide)\n})\n</script>\n\n<template>\n <PopoverRoot v-model:open=\"open\">\n <PopoverAnchor :reference=\"anchor\" />\n <PopoverPortal>\n <PopoverContent\n v-bind=\"$attrs\"\n align=\"start\"\n :align-offset=\"alignOffset\"\n :aria-label=\"label\"\n class=\"z-[1100] block max-h-(--reka-popover-content-available-height) origin-center overflow-y-auto rounded-xl outline-hidden border border-sui-edge bg-sui-raised text-sui-ink shadow-xl data-[state=closed]:animate-sui-overlay-out data-[state=open]:animate-sui-overlay-in\"\n :collision-padding=\"8\"\n side=\"bottom\"\n :side-offset=\"offset\"\n :style=\"{ width }\"\n @close-auto-focus=\"onCloseAutoFocus\"\n @escape-key-down=\"onEscape\"\n @focus-outside.prevent\n @open-auto-focus=\"onOpenAutoFocus\"\n @pointer-down-outside=\"onPointerDownOutside\"\n >\n <slot :hide=\"hide\" />\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n</template>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PopoverDialog.js","names":["_sfc_main","PopoverDialog_vue_vue_type_script_setup_true_lang_default","PopoverDialog_default"],"sources":["../../../src/components/Popover/PopoverDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n type ComponentPublicInstance,\n type MaybeRef,\n computed,\n onBeforeUnmount,\n ref,\n shallowRef,\n toValue,\n useSlots,\n watch\n} from 'vue'\n\nimport { PopoverAnchor, PopoverContent, PopoverPortal, PopoverRoot } from 'reka-ui'\n\nimport Button from '../Button/Button.vue'\nimport Dialog from '../Dialog/Dialog.vue'\nimport { type FilterTriggerProps, useCustomTrigger } from '../Filters/trigger'\n\nexport type PopoverDialogTriggerProps = FilterTriggerProps\n\nexport interface PopoverDialogProps {\n title: string\n /** What it opens under on the desktop: an element, a component, or a ref to one. Without it, the `trigger` slot. */\n anchor?: MaybeRef<HTMLElement | ComponentPublicInstance | null | undefined>\n /** The popover's width in px, or a CSS width. */\n width?: number | string\n /** Shows Cancel and this confirm button in the footer; it emits `confirm`, as ⌘ or Ctrl Enter does. */\n confirmLabel?: string\n confirmDisabled?: boolean\n cancelLabel?: string\n closeLabel?: string\n /** The viewport width in px below which it's a bottom sheet. */\n sheetBelow?: number\n}\n\nconst props = withDefaults(defineProps<PopoverDialogProps>(), {\n anchor: undefined,\n width: 320,\n confirmLabel: undefined,\n cancelLabel: 'Cancel',\n closeLabel: 'Close',\n sheetBelow: 640\n})\n\nconst emit = defineEmits<{ confirm: []; cancel: [] }>()\n\nconst open = defineModel<boolean>('open', { default: false })\n\ndefineSlots<{\n default?: () => unknown\n /** Replaces Cancel and the confirm button. */\n footer?: () => unknown\n /** The opener, when there's no `anchor`: spread `props` on your button. */\n trigger?: (props: { props: PopoverDialogTriggerProps; open: boolean }) => unknown\n}>()\n\nconst slots = useSlots()\nconst trigger = useCustomTrigger(open)\nconst triggerElement = shallowRef<HTMLElement | null>(null)\nconst triggerProps = computed<PopoverDialogTriggerProps>(() => ({\n ...trigger.props.value,\n ref: (node) => {\n trigger.props.value.ref(node)\n triggerElement.value = node instanceof Element ? (node as HTMLElement) : ((node?.$el as HTMLElement) ?? null)\n }\n}))\n\nconst anchorElement = computed(() => {\n const value = toValue(props.anchor)\n if (value instanceof Element) return value as HTMLElement\n return (value?.$el as HTMLElement | undefined) ?? triggerElement.value ?? undefined\n})\n\nconst narrow = ref(false)\nlet query: MediaQueryList | undefined\nconst onQuery = () => (narrow.value = !!query?.matches)\nwatch(\n () => props.sheetBelow,\n (below) => {\n query?.removeEventListener('change', onQuery)\n query =\n typeof window !== 'undefined' && window.matchMedia\n ? window.matchMedia(`(max-width: ${below - 0.02}px)`)\n : undefined\n query?.addEventListener('change', onQuery)\n onQuery()\n },\n { immediate: true }\n)\nonBeforeUnmount(() => query?.removeEventListener('change', onQuery))\n\n// A popover needs something to sit under; without one it's a small dialog, and on a phone always a sheet.\nconst presentation = computed(() => (narrow.value ? 'sheet' : anchorElement.value ? 'popover' : 'dialog'))\n\n// Focus goes back to what had it when it opened (a row opened by a shortcut, a button), else the anchor; a press\n// outside leaves it where it landed.\nlet returnTo: HTMLElement | null = null\nlet pressedOutside = false\nwatch(open, (isOpen) => {\n if (!isOpen) return\n const active = document.activeElement as HTMLElement | null\n returnTo = active && active !== document.body ? active : null\n pressedOutside = false\n})\n\nfunction cancel() {\n emit('cancel')\n open.value = false\n}\n\nfunction onOpenAutoFocus(event: Event) {\n event.preventDefault()\n const panel =\n (event.target as HTMLElement).querySelector<HTMLElement>('[role=\"dialog\"]') ?? (event.target as HTMLElement)\n ;(panel.querySelector<HTMLElement>('[autofocus]') ?? panel).focus()\n}\n\nfunction onCloseAutoFocus(event: Event) {\n event.preventDefault()\n if (pressedOutside) return\n const target = returnTo?.isConnected ? returnTo : anchorElement.value\n target?.focus()\n}\n\nfunction onPointerDownOutside(event: CustomEvent<{ originalEvent: PointerEvent }>) {\n const target = event.detail.originalEvent.target\n if (target instanceof Node && triggerElement.value?.contains(target)) {\n event.preventDefault()\n return\n }\n pressedOutside = true\n emit('cancel')\n}\n\nfunction confirmFromKeyboard(event: KeyboardEvent) {\n if (!event.metaKey && !event.ctrlKey) return\n event.preventDefault()\n if (props.confirmLabel && !props.confirmDisabled) emit('confirm')\n}\n\nconst panelWidth = computed(() => (typeof props.width === 'number' ? `${props.width}px` : props.width))\n</script>\n\n<!-- A small decision: a popover under its anchor on the desktop, a bottom sheet on the phone. -->\n<template>\n <slot v-if=\"slots.trigger\" name=\"trigger\" :open=\"open\" :props=\"triggerProps\" />\n <PopoverRoot v-if=\"presentation === 'popover'\" v-model:open=\"open\">\n <PopoverAnchor :reference=\"anchorElement\" />\n <PopoverPortal>\n <PopoverContent\n align=\"start\"\n :aria-label=\"title\"\n class=\"z-[1100] flex max-h-(--reka-popover-content-available-height) flex-col gap-2.5 overflow-y-auto rounded-
|
|
1
|
+
{"version":3,"file":"PopoverDialog.js","names":["_sfc_main","PopoverDialog_vue_vue_type_script_setup_true_lang_default","PopoverDialog_default"],"sources":["../../../src/components/Popover/PopoverDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n type ComponentPublicInstance,\n type MaybeRef,\n computed,\n onBeforeUnmount,\n ref,\n shallowRef,\n toValue,\n useSlots,\n watch\n} from 'vue'\n\nimport { PopoverAnchor, PopoverContent, PopoverPortal, PopoverRoot } from 'reka-ui'\n\nimport Button from '../Button/Button.vue'\nimport Dialog from '../Dialog/Dialog.vue'\nimport { type FilterTriggerProps, useCustomTrigger } from '../Filters/trigger'\n\nexport type PopoverDialogTriggerProps = FilterTriggerProps\n\nexport interface PopoverDialogProps {\n title: string\n /** What it opens under on the desktop: an element, a component, or a ref to one. Without it, the `trigger` slot. */\n anchor?: MaybeRef<HTMLElement | ComponentPublicInstance | null | undefined>\n /** The popover's width in px, or a CSS width. */\n width?: number | string\n /** Shows Cancel and this confirm button in the footer; it emits `confirm`, as ⌘ or Ctrl Enter does. */\n confirmLabel?: string\n confirmDisabled?: boolean\n cancelLabel?: string\n closeLabel?: string\n /** The viewport width in px below which it's a bottom sheet. */\n sheetBelow?: number\n}\n\nconst props = withDefaults(defineProps<PopoverDialogProps>(), {\n anchor: undefined,\n width: 320,\n confirmLabel: undefined,\n cancelLabel: 'Cancel',\n closeLabel: 'Close',\n sheetBelow: 640\n})\n\nconst emit = defineEmits<{ confirm: []; cancel: [] }>()\n\nconst open = defineModel<boolean>('open', { default: false })\n\ndefineSlots<{\n default?: () => unknown\n /** Replaces Cancel and the confirm button. */\n footer?: () => unknown\n /** The opener, when there's no `anchor`: spread `props` on your button. */\n trigger?: (props: { props: PopoverDialogTriggerProps; open: boolean }) => unknown\n}>()\n\nconst slots = useSlots()\nconst trigger = useCustomTrigger(open)\nconst triggerElement = shallowRef<HTMLElement | null>(null)\nconst triggerProps = computed<PopoverDialogTriggerProps>(() => ({\n ...trigger.props.value,\n ref: (node) => {\n trigger.props.value.ref(node)\n triggerElement.value = node instanceof Element ? (node as HTMLElement) : ((node?.$el as HTMLElement) ?? null)\n }\n}))\n\nconst anchorElement = computed(() => {\n const value = toValue(props.anchor)\n if (value instanceof Element) return value as HTMLElement\n return (value?.$el as HTMLElement | undefined) ?? triggerElement.value ?? undefined\n})\n\nconst narrow = ref(false)\nlet query: MediaQueryList | undefined\nconst onQuery = () => (narrow.value = !!query?.matches)\nwatch(\n () => props.sheetBelow,\n (below) => {\n query?.removeEventListener('change', onQuery)\n query =\n typeof window !== 'undefined' && window.matchMedia\n ? window.matchMedia(`(max-width: ${below - 0.02}px)`)\n : undefined\n query?.addEventListener('change', onQuery)\n onQuery()\n },\n { immediate: true }\n)\nonBeforeUnmount(() => query?.removeEventListener('change', onQuery))\n\n// A popover needs something to sit under; without one it's a small dialog, and on a phone always a sheet.\nconst presentation = computed(() => (narrow.value ? 'sheet' : anchorElement.value ? 'popover' : 'dialog'))\n\n// Focus goes back to what had it when it opened (a row opened by a shortcut, a button), else the anchor; a press\n// outside leaves it where it landed.\nlet returnTo: HTMLElement | null = null\nlet pressedOutside = false\nwatch(open, (isOpen) => {\n if (!isOpen) return\n const active = document.activeElement as HTMLElement | null\n returnTo = active && active !== document.body ? active : null\n pressedOutside = false\n})\n\nfunction cancel() {\n emit('cancel')\n open.value = false\n}\n\nfunction onOpenAutoFocus(event: Event) {\n event.preventDefault()\n const panel =\n (event.target as HTMLElement).querySelector<HTMLElement>('[role=\"dialog\"]') ?? (event.target as HTMLElement)\n ;(panel.querySelector<HTMLElement>('[autofocus]') ?? panel).focus()\n}\n\nfunction onCloseAutoFocus(event: Event) {\n event.preventDefault()\n if (pressedOutside) return\n const target = returnTo?.isConnected ? returnTo : anchorElement.value\n target?.focus()\n}\n\nfunction onPointerDownOutside(event: CustomEvent<{ originalEvent: PointerEvent }>) {\n const target = event.detail.originalEvent.target\n if (target instanceof Node && triggerElement.value?.contains(target)) {\n event.preventDefault()\n return\n }\n pressedOutside = true\n emit('cancel')\n}\n\nfunction confirmFromKeyboard(event: KeyboardEvent) {\n if (!event.metaKey && !event.ctrlKey) return\n event.preventDefault()\n if (props.confirmLabel && !props.confirmDisabled) emit('confirm')\n}\n\nconst panelWidth = computed(() => (typeof props.width === 'number' ? `${props.width}px` : props.width))\n</script>\n\n<!-- A small decision: a popover under its anchor on the desktop, a bottom sheet on the phone. -->\n<template>\n <slot v-if=\"slots.trigger\" name=\"trigger\" :open=\"open\" :props=\"triggerProps\" />\n <PopoverRoot v-if=\"presentation === 'popover'\" v-model:open=\"open\">\n <PopoverAnchor :reference=\"anchorElement\" />\n <PopoverPortal>\n <PopoverContent\n align=\"start\"\n :aria-label=\"title\"\n class=\"z-[1100] flex max-h-(--reka-popover-content-available-height) flex-col gap-2.5 overflow-y-auto rounded-xl border border-sui-edge bg-sui-raised px-4 py-3.5 text-sm text-sui-ink shadow-xl outline-hidden data-[state=closed]:animate-sui-overlay-out data-[state=open]:animate-sui-overlay-in\"\n :collision-padding=\"8\"\n :data-sui-panel=\"trigger.panelKey\"\n role=\"dialog\"\n side=\"bottom\"\n :side-offset=\"4\"\n :style=\"{ width: panelWidth }\"\n @close-auto-focus=\"onCloseAutoFocus\"\n @escape-key-down=\"emit('cancel')\"\n @focus-outside.prevent\n @keydown.enter=\"confirmFromKeyboard\"\n @open-auto-focus=\"onOpenAutoFocus\"\n @pointer-down-outside=\"onPointerDownOutside\"\n >\n <h2 class=\"m-0 text-sm font-semibold text-sui-ink\">{{ title }}</h2>\n <slot />\n <div v-if=\"$slots.footer || confirmLabel\" class=\"flex items-center justify-end gap-2 pt-0.5\">\n <slot name=\"footer\">\n <Button size=\"sm\" type=\"button\" variant=\"ghost\" @click=\"cancel\">{{ cancelLabel }}</Button>\n <Button :disabled=\"confirmDisabled\" size=\"sm\" type=\"button\" variant=\"primary\" @click=\"emit('confirm')\">\n {{ confirmLabel }}\n </Button>\n </slot>\n </div>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n <Dialog\n v-else\n v-model:open=\"open\"\n :cancel-label=\"cancelLabel\"\n :close-label=\"closeLabel\"\n :confirm-disabled=\"confirmDisabled\"\n :confirm-label=\"confirmLabel\"\n :presentation=\"presentation === 'sheet' ? 'sheet' : 'dialog'\"\n size=\"sm\"\n :title=\"title\"\n @cancel=\"emit('cancel')\"\n @confirm=\"emit('confirm')\"\n >\n <slot />\n <template v-if=\"$slots.footer\" #footer><slot name=\"footer\" /></template>\n </Dialog>\n</template>\n"],"mappings":""}
|
|
@@ -76,7 +76,7 @@ var N = { class: "m-0 text-sm font-semibold text-sui-ink" }, P = {
|
|
|
76
76
|
default: E(() => [d(S(A), {
|
|
77
77
|
align: "start",
|
|
78
78
|
"aria-label": f.title,
|
|
79
|
-
class: "z-[1100] flex max-h-(--reka-popover-content-available-height) flex-col gap-2.5 overflow-y-auto rounded-
|
|
79
|
+
class: "z-[1100] flex max-h-(--reka-popover-content-available-height) flex-col gap-2.5 overflow-y-auto rounded-xl border border-sui-edge bg-sui-raised px-4 py-3.5 text-sm text-sui-ink shadow-xl outline-hidden data-[state=closed]:animate-sui-overlay-out data-[state=open]:animate-sui-overlay-in",
|
|
80
80
|
"collision-padding": 8,
|
|
81
81
|
"data-sui-panel": S(z).panelKey,
|
|
82
82
|
role: "dialog",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PopoverDialog.vue_vue_type_script_setup_true_lang.js","names":["$slots","_useModel","_openBlock","_createElementBlock","_Fragment","_unref","_renderSlot","_createCommentVNode","_createBlock","_withCtx","_createVNode","_normalizeStyle","_withModifiers","_withKeys","_createElementVNode","_toDisplayString","Button","_createTextVNode","Dialog","_createSlots","Button_default","Dialog_default","_hoisted_1","_hoisted_2","PopoverDialog_vue_vue_type_script_setup_true_lang_default","\"open\"","\"openModifiers\"","__emit","props","__props","emit","open","useModel","slots","useSlots","trigger","useCustomTrigger","triggerElement","shallowRef","triggerProps","computed","node","anchorElement","value","toValue","narrow","ref","query","onQuery","watch","below","onBeforeUnmount","presentation","returnTo","pressedOutside","isOpen","active","cancel","onOpenAutoFocus","panel","event","onCloseAutoFocus","onPointerDownOutside","target","confirmFromKeyboard","panelWidth","openBlock","createElementBlock","Fragment","unref","renderSlot","_ctx","createCommentVNode","createBlock","PopoverRoot","_cache","$event","withCtx","createVNode","PopoverAnchor","PopoverPortal","PopoverContent","normalizeStyle","withModifiers","withKeys","createElementVNode","toDisplayString","createTextVNode","createSlots"],"sources":["../../../src/components/Popover/PopoverDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n type ComponentPublicInstance,\n type MaybeRef,\n computed,\n onBeforeUnmount,\n ref,\n shallowRef,\n toValue,\n useSlots,\n watch\n} from 'vue'\n\nimport { PopoverAnchor, PopoverContent, PopoverPortal, PopoverRoot } from 'reka-ui'\n\nimport Button from '../Button/Button.vue'\nimport Dialog from '../Dialog/Dialog.vue'\nimport { type FilterTriggerProps, useCustomTrigger } from '../Filters/trigger'\n\nexport type PopoverDialogTriggerProps = FilterTriggerProps\n\nexport interface PopoverDialogProps {\n title: string\n /** What it opens under on the desktop: an element, a component, or a ref to one. Without it, the `trigger` slot. */\n anchor?: MaybeRef<HTMLElement | ComponentPublicInstance | null | undefined>\n /** The popover's width in px, or a CSS width. */\n width?: number | string\n /** Shows Cancel and this confirm button in the footer; it emits `confirm`, as ⌘ or Ctrl Enter does. */\n confirmLabel?: string\n confirmDisabled?: boolean\n cancelLabel?: string\n closeLabel?: string\n /** The viewport width in px below which it's a bottom sheet. */\n sheetBelow?: number\n}\n\nconst props = withDefaults(defineProps<PopoverDialogProps>(), {\n anchor: undefined,\n width: 320,\n confirmLabel: undefined,\n cancelLabel: 'Cancel',\n closeLabel: 'Close',\n sheetBelow: 640\n})\n\nconst emit = defineEmits<{ confirm: []; cancel: [] }>()\n\nconst open = defineModel<boolean>('open', { default: false })\n\ndefineSlots<{\n default?: () => unknown\n /** Replaces Cancel and the confirm button. */\n footer?: () => unknown\n /** The opener, when there's no `anchor`: spread `props` on your button. */\n trigger?: (props: { props: PopoverDialogTriggerProps; open: boolean }) => unknown\n}>()\n\nconst slots = useSlots()\nconst trigger = useCustomTrigger(open)\nconst triggerElement = shallowRef<HTMLElement | null>(null)\nconst triggerProps = computed<PopoverDialogTriggerProps>(() => ({\n ...trigger.props.value,\n ref: (node) => {\n trigger.props.value.ref(node)\n triggerElement.value = node instanceof Element ? (node as HTMLElement) : ((node?.$el as HTMLElement) ?? null)\n }\n}))\n\nconst anchorElement = computed(() => {\n const value = toValue(props.anchor)\n if (value instanceof Element) return value as HTMLElement\n return (value?.$el as HTMLElement | undefined) ?? triggerElement.value ?? undefined\n})\n\nconst narrow = ref(false)\nlet query: MediaQueryList | undefined\nconst onQuery = () => (narrow.value = !!query?.matches)\nwatch(\n () => props.sheetBelow,\n (below) => {\n query?.removeEventListener('change', onQuery)\n query =\n typeof window !== 'undefined' && window.matchMedia\n ? window.matchMedia(`(max-width: ${below - 0.02}px)`)\n : undefined\n query?.addEventListener('change', onQuery)\n onQuery()\n },\n { immediate: true }\n)\nonBeforeUnmount(() => query?.removeEventListener('change', onQuery))\n\n// A popover needs something to sit under; without one it's a small dialog, and on a phone always a sheet.\nconst presentation = computed(() => (narrow.value ? 'sheet' : anchorElement.value ? 'popover' : 'dialog'))\n\n// Focus goes back to what had it when it opened (a row opened by a shortcut, a button), else the anchor; a press\n// outside leaves it where it landed.\nlet returnTo: HTMLElement | null = null\nlet pressedOutside = false\nwatch(open, (isOpen) => {\n if (!isOpen) return\n const active = document.activeElement as HTMLElement | null\n returnTo = active && active !== document.body ? active : null\n pressedOutside = false\n})\n\nfunction cancel() {\n emit('cancel')\n open.value = false\n}\n\nfunction onOpenAutoFocus(event: Event) {\n event.preventDefault()\n const panel =\n (event.target as HTMLElement).querySelector<HTMLElement>('[role=\"dialog\"]') ?? (event.target as HTMLElement)\n ;(panel.querySelector<HTMLElement>('[autofocus]') ?? panel).focus()\n}\n\nfunction onCloseAutoFocus(event: Event) {\n event.preventDefault()\n if (pressedOutside) return\n const target = returnTo?.isConnected ? returnTo : anchorElement.value\n target?.focus()\n}\n\nfunction onPointerDownOutside(event: CustomEvent<{ originalEvent: PointerEvent }>) {\n const target = event.detail.originalEvent.target\n if (target instanceof Node && triggerElement.value?.contains(target)) {\n event.preventDefault()\n return\n }\n pressedOutside = true\n emit('cancel')\n}\n\nfunction confirmFromKeyboard(event: KeyboardEvent) {\n if (!event.metaKey && !event.ctrlKey) return\n event.preventDefault()\n if (props.confirmLabel && !props.confirmDisabled) emit('confirm')\n}\n\nconst panelWidth = computed(() => (typeof props.width === 'number' ? `${props.width}px` : props.width))\n</script>\n\n<!-- A small decision: a popover under its anchor on the desktop, a bottom sheet on the phone. -->\n<template>\n <slot v-if=\"slots.trigger\" name=\"trigger\" :open=\"open\" :props=\"triggerProps\" />\n <PopoverRoot v-if=\"presentation === 'popover'\" v-model:open=\"open\">\n <PopoverAnchor :reference=\"anchorElement\" />\n <PopoverPortal>\n <PopoverContent\n align=\"start\"\n :aria-label=\"title\"\n class=\"z-[1100] flex max-h-(--reka-popover-content-available-height) flex-col gap-2.5 overflow-y-auto rounded-lg border border-sui-line-subtle bg-sui-surface px-4 py-3.5 text-sm text-sui-ink shadow-xl outline-hidden data-[state=closed]:animate-sui-overlay-out data-[state=open]:animate-sui-overlay-in\"\n :collision-padding=\"8\"\n :data-sui-panel=\"trigger.panelKey\"\n role=\"dialog\"\n side=\"bottom\"\n :side-offset=\"4\"\n :style=\"{ width: panelWidth }\"\n @close-auto-focus=\"onCloseAutoFocus\"\n @escape-key-down=\"emit('cancel')\"\n @focus-outside.prevent\n @keydown.enter=\"confirmFromKeyboard\"\n @open-auto-focus=\"onOpenAutoFocus\"\n @pointer-down-outside=\"onPointerDownOutside\"\n >\n <h2 class=\"m-0 text-sm font-semibold text-sui-ink\">{{ title }}</h2>\n <slot />\n <div v-if=\"$slots.footer || confirmLabel\" class=\"flex items-center justify-end gap-2 pt-0.5\">\n <slot name=\"footer\">\n <Button size=\"sm\" type=\"button\" variant=\"ghost\" @click=\"cancel\">{{ cancelLabel }}</Button>\n <Button :disabled=\"confirmDisabled\" size=\"sm\" type=\"button\" variant=\"primary\" @click=\"emit('confirm')\">\n {{ confirmLabel }}\n </Button>\n </slot>\n </div>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n <Dialog\n v-else\n v-model:open=\"open\"\n :cancel-label=\"cancelLabel\"\n :close-label=\"closeLabel\"\n :confirm-disabled=\"confirmDisabled\"\n :confirm-label=\"confirmLabel\"\n :presentation=\"presentation === 'sheet' ? 'sheet' : 'dialog'\"\n size=\"sm\"\n :title=\"title\"\n @cancel=\"emit('cancel')\"\n @confirm=\"emit('confirm')\"\n >\n <slot />\n <template v-if=\"$slots.footer\" #footer><slot name=\"footer\" /></template>\n </Dialog>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PopoverDialog.vue_vue_type_script_setup_true_lang.js","names":["$slots","_useModel","_openBlock","_createElementBlock","_Fragment","_unref","_renderSlot","_createCommentVNode","_createBlock","_withCtx","_createVNode","_normalizeStyle","_withModifiers","_withKeys","_createElementVNode","_toDisplayString","Button","_createTextVNode","Dialog","_createSlots","Button_default","Dialog_default","_hoisted_1","_hoisted_2","PopoverDialog_vue_vue_type_script_setup_true_lang_default","\"open\"","\"openModifiers\"","__emit","props","__props","emit","open","useModel","slots","useSlots","trigger","useCustomTrigger","triggerElement","shallowRef","triggerProps","computed","node","anchorElement","value","toValue","narrow","ref","query","onQuery","watch","below","onBeforeUnmount","presentation","returnTo","pressedOutside","isOpen","active","cancel","onOpenAutoFocus","panel","event","onCloseAutoFocus","onPointerDownOutside","target","confirmFromKeyboard","panelWidth","openBlock","createElementBlock","Fragment","unref","renderSlot","_ctx","createCommentVNode","createBlock","PopoverRoot","_cache","$event","withCtx","createVNode","PopoverAnchor","PopoverPortal","PopoverContent","normalizeStyle","withModifiers","withKeys","createElementVNode","toDisplayString","createTextVNode","createSlots"],"sources":["../../../src/components/Popover/PopoverDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n type ComponentPublicInstance,\n type MaybeRef,\n computed,\n onBeforeUnmount,\n ref,\n shallowRef,\n toValue,\n useSlots,\n watch\n} from 'vue'\n\nimport { PopoverAnchor, PopoverContent, PopoverPortal, PopoverRoot } from 'reka-ui'\n\nimport Button from '../Button/Button.vue'\nimport Dialog from '../Dialog/Dialog.vue'\nimport { type FilterTriggerProps, useCustomTrigger } from '../Filters/trigger'\n\nexport type PopoverDialogTriggerProps = FilterTriggerProps\n\nexport interface PopoverDialogProps {\n title: string\n /** What it opens under on the desktop: an element, a component, or a ref to one. Without it, the `trigger` slot. */\n anchor?: MaybeRef<HTMLElement | ComponentPublicInstance | null | undefined>\n /** The popover's width in px, or a CSS width. */\n width?: number | string\n /** Shows Cancel and this confirm button in the footer; it emits `confirm`, as ⌘ or Ctrl Enter does. */\n confirmLabel?: string\n confirmDisabled?: boolean\n cancelLabel?: string\n closeLabel?: string\n /** The viewport width in px below which it's a bottom sheet. */\n sheetBelow?: number\n}\n\nconst props = withDefaults(defineProps<PopoverDialogProps>(), {\n anchor: undefined,\n width: 320,\n confirmLabel: undefined,\n cancelLabel: 'Cancel',\n closeLabel: 'Close',\n sheetBelow: 640\n})\n\nconst emit = defineEmits<{ confirm: []; cancel: [] }>()\n\nconst open = defineModel<boolean>('open', { default: false })\n\ndefineSlots<{\n default?: () => unknown\n /** Replaces Cancel and the confirm button. */\n footer?: () => unknown\n /** The opener, when there's no `anchor`: spread `props` on your button. */\n trigger?: (props: { props: PopoverDialogTriggerProps; open: boolean }) => unknown\n}>()\n\nconst slots = useSlots()\nconst trigger = useCustomTrigger(open)\nconst triggerElement = shallowRef<HTMLElement | null>(null)\nconst triggerProps = computed<PopoverDialogTriggerProps>(() => ({\n ...trigger.props.value,\n ref: (node) => {\n trigger.props.value.ref(node)\n triggerElement.value = node instanceof Element ? (node as HTMLElement) : ((node?.$el as HTMLElement) ?? null)\n }\n}))\n\nconst anchorElement = computed(() => {\n const value = toValue(props.anchor)\n if (value instanceof Element) return value as HTMLElement\n return (value?.$el as HTMLElement | undefined) ?? triggerElement.value ?? undefined\n})\n\nconst narrow = ref(false)\nlet query: MediaQueryList | undefined\nconst onQuery = () => (narrow.value = !!query?.matches)\nwatch(\n () => props.sheetBelow,\n (below) => {\n query?.removeEventListener('change', onQuery)\n query =\n typeof window !== 'undefined' && window.matchMedia\n ? window.matchMedia(`(max-width: ${below - 0.02}px)`)\n : undefined\n query?.addEventListener('change', onQuery)\n onQuery()\n },\n { immediate: true }\n)\nonBeforeUnmount(() => query?.removeEventListener('change', onQuery))\n\n// A popover needs something to sit under; without one it's a small dialog, and on a phone always a sheet.\nconst presentation = computed(() => (narrow.value ? 'sheet' : anchorElement.value ? 'popover' : 'dialog'))\n\n// Focus goes back to what had it when it opened (a row opened by a shortcut, a button), else the anchor; a press\n// outside leaves it where it landed.\nlet returnTo: HTMLElement | null = null\nlet pressedOutside = false\nwatch(open, (isOpen) => {\n if (!isOpen) return\n const active = document.activeElement as HTMLElement | null\n returnTo = active && active !== document.body ? active : null\n pressedOutside = false\n})\n\nfunction cancel() {\n emit('cancel')\n open.value = false\n}\n\nfunction onOpenAutoFocus(event: Event) {\n event.preventDefault()\n const panel =\n (event.target as HTMLElement).querySelector<HTMLElement>('[role=\"dialog\"]') ?? (event.target as HTMLElement)\n ;(panel.querySelector<HTMLElement>('[autofocus]') ?? panel).focus()\n}\n\nfunction onCloseAutoFocus(event: Event) {\n event.preventDefault()\n if (pressedOutside) return\n const target = returnTo?.isConnected ? returnTo : anchorElement.value\n target?.focus()\n}\n\nfunction onPointerDownOutside(event: CustomEvent<{ originalEvent: PointerEvent }>) {\n const target = event.detail.originalEvent.target\n if (target instanceof Node && triggerElement.value?.contains(target)) {\n event.preventDefault()\n return\n }\n pressedOutside = true\n emit('cancel')\n}\n\nfunction confirmFromKeyboard(event: KeyboardEvent) {\n if (!event.metaKey && !event.ctrlKey) return\n event.preventDefault()\n if (props.confirmLabel && !props.confirmDisabled) emit('confirm')\n}\n\nconst panelWidth = computed(() => (typeof props.width === 'number' ? `${props.width}px` : props.width))\n</script>\n\n<!-- A small decision: a popover under its anchor on the desktop, a bottom sheet on the phone. -->\n<template>\n <slot v-if=\"slots.trigger\" name=\"trigger\" :open=\"open\" :props=\"triggerProps\" />\n <PopoverRoot v-if=\"presentation === 'popover'\" v-model:open=\"open\">\n <PopoverAnchor :reference=\"anchorElement\" />\n <PopoverPortal>\n <PopoverContent\n align=\"start\"\n :aria-label=\"title\"\n class=\"z-[1100] flex max-h-(--reka-popover-content-available-height) flex-col gap-2.5 overflow-y-auto rounded-xl border border-sui-edge bg-sui-raised px-4 py-3.5 text-sm text-sui-ink shadow-xl outline-hidden data-[state=closed]:animate-sui-overlay-out data-[state=open]:animate-sui-overlay-in\"\n :collision-padding=\"8\"\n :data-sui-panel=\"trigger.panelKey\"\n role=\"dialog\"\n side=\"bottom\"\n :side-offset=\"4\"\n :style=\"{ width: panelWidth }\"\n @close-auto-focus=\"onCloseAutoFocus\"\n @escape-key-down=\"emit('cancel')\"\n @focus-outside.prevent\n @keydown.enter=\"confirmFromKeyboard\"\n @open-auto-focus=\"onOpenAutoFocus\"\n @pointer-down-outside=\"onPointerDownOutside\"\n >\n <h2 class=\"m-0 text-sm font-semibold text-sui-ink\">{{ title }}</h2>\n <slot />\n <div v-if=\"$slots.footer || confirmLabel\" class=\"flex items-center justify-end gap-2 pt-0.5\">\n <slot name=\"footer\">\n <Button size=\"sm\" type=\"button\" variant=\"ghost\" @click=\"cancel\">{{ cancelLabel }}</Button>\n <Button :disabled=\"confirmDisabled\" size=\"sm\" type=\"button\" variant=\"primary\" @click=\"emit('confirm')\">\n {{ confirmLabel }}\n </Button>\n </slot>\n </div>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n <Dialog\n v-else\n v-model:open=\"open\"\n :cancel-label=\"cancelLabel\"\n :close-label=\"closeLabel\"\n :confirm-disabled=\"confirmDisabled\"\n :confirm-label=\"confirmLabel\"\n :presentation=\"presentation === 'sheet' ? 'sheet' : 'dialog'\"\n size=\"sm\"\n :title=\"title\"\n @cancel=\"emit('cancel')\"\n @confirm=\"emit('confirm')\"\n >\n <slot />\n <template v-if=\"$slots.footer\" #footer><slot name=\"footer\" /></template>\n </Dialog>\n</template>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Editable.js","names":["_sfc_main","Editable_vue_vue_type_script_setup_true_lang_default","Editable_default"],"sources":["../../../src/components/PropertyList/Editable.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, nextTick, ref, toRaw, useAttrs, useTemplateRef, watch } from 'vue'\n\nimport Select from '../Select/Select.vue'\nimport type { SelectOption, SelectValue } from '../Select/types'\nimport Tag from '../Tag/Tag.vue'\nimport Textarea from '../Textarea/Textarea.vue'\n\nexport interface EditableProps {\n /** `text` (one line), `multiline` (Shift+Enter for a new line), `select` (an outline Tag, picked from `options`) or `title`\n * (a record's 18px name). */\n variant?: 'text' | 'multiline' | 'select' | 'title'\n placeholder?: string\n /** For `select`. */\n options?: SelectOption[]\n disabled?: boolean\n}\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<EditableProps>(), {\n variant: 'text',\n placeholder: undefined,\n options: () => []\n})\n\nconst emit = defineEmits<{ blur: [] }>()\n\nconst model = defineModel<string | SelectValue | null>({ default: null })\n\n// Only the id, class and data- and aria- attributes go on the root. The name is said before the value, not as an\n// aria-label, which would hide the value from it.\nconst attrs = useAttrs()\nconst rootAttrs = computed(() =>\n Object.fromEntries(\n Object.entries(attrs).filter(\n ([key]) => key !== 'aria-label' && (key === 'id' || key === 'class' || /^(data|aria)-/.test(key))\n )\n )\n)\nconst name = computed(() => (attrs['aria-label'] as string | undefined) ?? props.placeholder)\n\nconst title = computed(() => props.variant === 'title')\nconst multiline = computed(() => props.variant === 'multiline')\n\nconst local = ref(toRaw(model.value) as string | null)\nconst original = ref(local.value)\nconst editing = ref(false)\nconst wrapper = useTemplateRef<HTMLElement>('wrapper')\n\n// Follows the value from outside (a failed save rolled back, a refetch) unless it's being edited.\nwatch(model, (value) => {\n if (editing.value) return\n local.value = toRaw(value) as string | null\n original.value = local.value\n})\n\nconst rows = computed(() => (title.value ? 1 : Math.max(1, Math.ceil((local.value?.length ?? 0) / 34))))\n\nasync function edit() {\n if (props.disabled) return\n editing.value = true\n await nextTick()\n wrapper.value?.querySelector('textarea')?.focus()\n}\n\nfunction save() {\n editing.value = false\n const value = toRaw(local.value) || null\n // Leaving it untouched isn't a change: an empty value stays as it came, '' or null.\n if (value !== (toRaw(model.value) || null)) model.value = value\n original.value = local.value\n emit('blur')\n}\n\nfunction revert(event: KeyboardEvent) {\n event.preventDefault()\n event.stopPropagation()\n local.value = original.value\n editing.value = false\n}\n\nfunction onEnter(event: KeyboardEvent) {\n if (multiline.value && event.shiftKey) return\n event.preventDefault()\n ;(event.target as HTMLElement).blur()\n}\n\nconst field =\n 'block w-full rounded-lg border border-transparent px-[0.6875rem] py-1.25 text-left text-sui-ink transition-[background-color,border-color,box-shadow] outline-hidden focus-visible:border-sui-accent focus-visible:sui-ring-field'\n</script>\n\n<!-- One value shown as plain text and edited where it is: click or Enter to edit, Enter or leaving to save, Escape to\n undo. A `select` opens its list under the value instead. -->\n<template>\n <Select\n v-if=\"variant === 'select'\"\n v-model=\"model as SelectValue | null\"\n :aria-label=\"name\"\n :disabled=\"disabled\"\n :options=\"options\"\n @update:model-value=\"emit('blur')\"\n >\n <template #trigger=\"{ open, toggle, selected }\">\n <button\n v-bind=\"rootAttrs\"\n :aria-expanded=\"open\"\n aria-haspopup=\"listbox\"\n :class=\"[\n field,\n 'max-w-[16rem] text-sm leading-5',\n disabled ? 'cursor-auto' : 'cursor-pointer hover:bg-sui-
|
|
1
|
+
{"version":3,"file":"Editable.js","names":["_sfc_main","Editable_vue_vue_type_script_setup_true_lang_default","Editable_default"],"sources":["../../../src/components/PropertyList/Editable.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, nextTick, ref, toRaw, useAttrs, useTemplateRef, watch } from 'vue'\n\nimport Select from '../Select/Select.vue'\nimport type { SelectOption, SelectValue } from '../Select/types'\nimport Tag from '../Tag/Tag.vue'\nimport Textarea from '../Textarea/Textarea.vue'\n\nexport interface EditableProps {\n /** `text` (one line), `multiline` (Shift+Enter for a new line), `select` (an outline Tag, picked from `options`) or `title`\n * (a record's 18px name). */\n variant?: 'text' | 'multiline' | 'select' | 'title'\n placeholder?: string\n /** For `select`. */\n options?: SelectOption[]\n disabled?: boolean\n}\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<EditableProps>(), {\n variant: 'text',\n placeholder: undefined,\n options: () => []\n})\n\nconst emit = defineEmits<{ blur: [] }>()\n\nconst model = defineModel<string | SelectValue | null>({ default: null })\n\n// Only the id, class and data- and aria- attributes go on the root. The name is said before the value, not as an\n// aria-label, which would hide the value from it.\nconst attrs = useAttrs()\nconst rootAttrs = computed(() =>\n Object.fromEntries(\n Object.entries(attrs).filter(\n ([key]) => key !== 'aria-label' && (key === 'id' || key === 'class' || /^(data|aria)-/.test(key))\n )\n )\n)\nconst name = computed(() => (attrs['aria-label'] as string | undefined) ?? props.placeholder)\n\nconst title = computed(() => props.variant === 'title')\nconst multiline = computed(() => props.variant === 'multiline')\n\nconst local = ref(toRaw(model.value) as string | null)\nconst original = ref(local.value)\nconst editing = ref(false)\nconst wrapper = useTemplateRef<HTMLElement>('wrapper')\n\n// Follows the value from outside (a failed save rolled back, a refetch) unless it's being edited.\nwatch(model, (value) => {\n if (editing.value) return\n local.value = toRaw(value) as string | null\n original.value = local.value\n})\n\nconst rows = computed(() => (title.value ? 1 : Math.max(1, Math.ceil((local.value?.length ?? 0) / 34))))\n\nasync function edit() {\n if (props.disabled) return\n editing.value = true\n await nextTick()\n wrapper.value?.querySelector('textarea')?.focus()\n}\n\nfunction save() {\n editing.value = false\n const value = toRaw(local.value) || null\n // Leaving it untouched isn't a change: an empty value stays as it came, '' or null.\n if (value !== (toRaw(model.value) || null)) model.value = value\n original.value = local.value\n emit('blur')\n}\n\nfunction revert(event: KeyboardEvent) {\n event.preventDefault()\n event.stopPropagation()\n local.value = original.value\n editing.value = false\n}\n\nfunction onEnter(event: KeyboardEvent) {\n if (multiline.value && event.shiftKey) return\n event.preventDefault()\n ;(event.target as HTMLElement).blur()\n}\n\nconst field =\n 'block w-full rounded-lg border border-transparent px-[0.6875rem] py-1.25 text-left text-sui-ink transition-[background-color,border-color,box-shadow] outline-hidden focus-visible:border-sui-accent focus-visible:sui-ring-field'\n</script>\n\n<!-- One value shown as plain text and edited where it is: click or Enter to edit, Enter or leaving to save, Escape to\n undo. A `select` opens its list under the value instead. -->\n<template>\n <Select\n v-if=\"variant === 'select'\"\n v-model=\"model as SelectValue | null\"\n :aria-label=\"name\"\n :disabled=\"disabled\"\n :options=\"options\"\n @update:model-value=\"emit('blur')\"\n >\n <template #trigger=\"{ open, toggle, selected }\">\n <button\n v-bind=\"rootAttrs\"\n :aria-expanded=\"open\"\n aria-haspopup=\"listbox\"\n :class=\"[\n field,\n 'max-w-[16rem] text-sm leading-5',\n disabled ? 'cursor-auto' : 'cursor-pointer hover:bg-sui-fill-hover'\n ]\"\n :disabled=\"disabled\"\n type=\"button\"\n @click=\"toggle\"\n >\n <span v-if=\"name\" class=\"sr-only\">{{ name }}: </span>\n <Tag\n v-if=\"selected[0]\"\n :icon=\"selected[0].icon\"\n :icon-color=\"selected[0].iconColor\"\n :name=\"selected[0].label\"\n variant=\"outline\"\n />\n <span v-else class=\"text-sui-ink-muted\">{{ placeholder }}</span>\n </button>\n </template>\n </Select>\n <div\n v-else\n v-bind=\"rootAttrs\"\n ref=\"wrapper\"\n class=\"relative\"\n :class=\"[\n field,\n title\n ? 'min-h-10 min-w-4 text-lg leading-7 font-semibold [&_textarea]:min-h-10 [&_textarea]:text-lg [&_textarea]:leading-7 [&_textarea]:font-semibold [&_textarea]:whitespace-nowrap [&_textarea]:placeholder:text-lg [&_textarea]:placeholder:font-semibold'\n : 'max-w-[16rem] text-sm leading-5 [&_textarea]:placeholder:text-sm [&_textarea]:placeholder:leading-5',\n disabled ? 'cursor-auto' : 'cursor-pointer hover:bg-sui-fill-hover',\n '[&_textarea]:bg-sui-surface [&_textarea]:placeholder:text-sui-ink-muted'\n ]\"\n role=\"button\"\n :tabindex=\"disabled ? -1 : 0\"\n @click=\"edit\"\n @keydown.enter=\"!editing && ($event.preventDefault(), edit())\"\n >\n <div>\n <span v-if=\"name\" class=\"sr-only\">{{ name }}: </span>\n <span v-if=\"!local\" class=\"text-sui-ink-muted\">{{ placeholder }}</span>\n <span v-else :class=\"{ 'whitespace-pre-wrap': multiline }\">{{ local }}</span>\n </div>\n <div v-if=\"editing\" class=\"absolute inset-0 z-10\" :class=\"{ '-mt-px': title }\">\n <Textarea\n v-model=\"local\"\n :aria-label=\"name\"\n :auto-resize=\"!title\"\n class=\"resize-none\"\n :class=\"title && 'h-full px-3 py-1.5'\"\n :placeholder=\"placeholder\"\n :rows=\"rows\"\n @blur=\"save\"\n @keydown.enter.stop=\"onEnter\"\n @keydown.esc.stop=\"revert\"\n />\n </div>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -66,7 +66,7 @@ var T = [
|
|
|
66
66
|
class: [
|
|
67
67
|
j,
|
|
68
68
|
"max-w-[16rem] text-sm leading-5",
|
|
69
|
-
l.disabled ? "cursor-auto" : "cursor-pointer hover:bg-sui-
|
|
69
|
+
l.disabled ? "cursor-auto" : "cursor-pointer hover:bg-sui-fill-hover"
|
|
70
70
|
],
|
|
71
71
|
disabled: l.disabled,
|
|
72
72
|
type: "button",
|
|
@@ -94,7 +94,7 @@ var T = [
|
|
|
94
94
|
class: ["relative", [
|
|
95
95
|
j,
|
|
96
96
|
R.value ? "min-h-10 min-w-4 text-lg leading-7 font-semibold [&_textarea]:min-h-10 [&_textarea]:text-lg [&_textarea]:leading-7 [&_textarea]:font-semibold [&_textarea]:whitespace-nowrap [&_textarea]:placeholder:text-lg [&_textarea]:placeholder:font-semibold" : "max-w-[16rem] text-sm leading-5 [&_textarea]:placeholder:text-sm [&_textarea]:placeholder:leading-5",
|
|
97
|
-
l.disabled ? "cursor-auto" : "cursor-pointer hover:bg-sui-
|
|
97
|
+
l.disabled ? "cursor-auto" : "cursor-pointer hover:bg-sui-fill-hover",
|
|
98
98
|
"[&_textarea]:bg-sui-surface [&_textarea]:placeholder:text-sui-ink-muted"
|
|
99
99
|
]],
|
|
100
100
|
role: "button",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Editable.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createBlock","Select","_withCtx","_createElementVNode","_mergeProps","_createElementBlock","_toDisplayString","_createCommentVNode","Tag","_withKeys","_normalizeClass","_createVNode","Textarea","_withModifiers","Tag_default","Select_default","Textarea_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","field","Editable_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","__emit","props","__props","emit","model","useModel","attrs","useAttrs","rootAttrs","computed","key","name","title","multiline","local","ref","toRaw","original","editing","wrapper","useTemplateRef","value","rows","edit","nextTick","save","revert","event","onEnter","openBlock","createBlock","_cache","$event","withCtx","createElementVNode","mergeProps","open","toggle","createElementBlock","toDisplayString","createCommentVNode","selected","withKeys","normalizeClass","createVNode","withModifiers"],"sources":["../../../src/components/PropertyList/Editable.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, nextTick, ref, toRaw, useAttrs, useTemplateRef, watch } from 'vue'\n\nimport Select from '../Select/Select.vue'\nimport type { SelectOption, SelectValue } from '../Select/types'\nimport Tag from '../Tag/Tag.vue'\nimport Textarea from '../Textarea/Textarea.vue'\n\nexport interface EditableProps {\n /** `text` (one line), `multiline` (Shift+Enter for a new line), `select` (an outline Tag, picked from `options`) or `title`\n * (a record's 18px name). */\n variant?: 'text' | 'multiline' | 'select' | 'title'\n placeholder?: string\n /** For `select`. */\n options?: SelectOption[]\n disabled?: boolean\n}\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<EditableProps>(), {\n variant: 'text',\n placeholder: undefined,\n options: () => []\n})\n\nconst emit = defineEmits<{ blur: [] }>()\n\nconst model = defineModel<string | SelectValue | null>({ default: null })\n\n// Only the id, class and data- and aria- attributes go on the root. The name is said before the value, not as an\n// aria-label, which would hide the value from it.\nconst attrs = useAttrs()\nconst rootAttrs = computed(() =>\n Object.fromEntries(\n Object.entries(attrs).filter(\n ([key]) => key !== 'aria-label' && (key === 'id' || key === 'class' || /^(data|aria)-/.test(key))\n )\n )\n)\nconst name = computed(() => (attrs['aria-label'] as string | undefined) ?? props.placeholder)\n\nconst title = computed(() => props.variant === 'title')\nconst multiline = computed(() => props.variant === 'multiline')\n\nconst local = ref(toRaw(model.value) as string | null)\nconst original = ref(local.value)\nconst editing = ref(false)\nconst wrapper = useTemplateRef<HTMLElement>('wrapper')\n\n// Follows the value from outside (a failed save rolled back, a refetch) unless it's being edited.\nwatch(model, (value) => {\n if (editing.value) return\n local.value = toRaw(value) as string | null\n original.value = local.value\n})\n\nconst rows = computed(() => (title.value ? 1 : Math.max(1, Math.ceil((local.value?.length ?? 0) / 34))))\n\nasync function edit() {\n if (props.disabled) return\n editing.value = true\n await nextTick()\n wrapper.value?.querySelector('textarea')?.focus()\n}\n\nfunction save() {\n editing.value = false\n const value = toRaw(local.value) || null\n // Leaving it untouched isn't a change: an empty value stays as it came, '' or null.\n if (value !== (toRaw(model.value) || null)) model.value = value\n original.value = local.value\n emit('blur')\n}\n\nfunction revert(event: KeyboardEvent) {\n event.preventDefault()\n event.stopPropagation()\n local.value = original.value\n editing.value = false\n}\n\nfunction onEnter(event: KeyboardEvent) {\n if (multiline.value && event.shiftKey) return\n event.preventDefault()\n ;(event.target as HTMLElement).blur()\n}\n\nconst field =\n 'block w-full rounded-lg border border-transparent px-[0.6875rem] py-1.25 text-left text-sui-ink transition-[background-color,border-color,box-shadow] outline-hidden focus-visible:border-sui-accent focus-visible:sui-ring-field'\n</script>\n\n<!-- One value shown as plain text and edited where it is: click or Enter to edit, Enter or leaving to save, Escape to\n undo. A `select` opens its list under the value instead. -->\n<template>\n <Select\n v-if=\"variant === 'select'\"\n v-model=\"model as SelectValue | null\"\n :aria-label=\"name\"\n :disabled=\"disabled\"\n :options=\"options\"\n @update:model-value=\"emit('blur')\"\n >\n <template #trigger=\"{ open, toggle, selected }\">\n <button\n v-bind=\"rootAttrs\"\n :aria-expanded=\"open\"\n aria-haspopup=\"listbox\"\n :class=\"[\n field,\n 'max-w-[16rem] text-sm leading-5',\n disabled ? 'cursor-auto' : 'cursor-pointer hover:bg-sui-sunken'\n ]\"\n :disabled=\"disabled\"\n type=\"button\"\n @click=\"toggle\"\n >\n <span v-if=\"name\" class=\"sr-only\">{{ name }}: </span>\n <Tag\n v-if=\"selected[0]\"\n :icon=\"selected[0].icon\"\n :icon-color=\"selected[0].iconColor\"\n :name=\"selected[0].label\"\n variant=\"outline\"\n />\n <span v-else class=\"text-sui-ink-muted\">{{ placeholder }}</span>\n </button>\n </template>\n </Select>\n <div\n v-else\n v-bind=\"rootAttrs\"\n ref=\"wrapper\"\n class=\"relative\"\n :class=\"[\n field,\n title\n ? 'min-h-10 min-w-4 text-lg leading-7 font-semibold [&_textarea]:min-h-10 [&_textarea]:text-lg [&_textarea]:leading-7 [&_textarea]:font-semibold [&_textarea]:whitespace-nowrap [&_textarea]:placeholder:text-lg [&_textarea]:placeholder:font-semibold'\n : 'max-w-[16rem] text-sm leading-5 [&_textarea]:placeholder:text-sm [&_textarea]:placeholder:leading-5',\n disabled ? 'cursor-auto' : 'cursor-pointer hover:bg-sui-sunken',\n '[&_textarea]:bg-sui-surface [&_textarea]:placeholder:text-sui-ink-muted'\n ]\"\n role=\"button\"\n :tabindex=\"disabled ? -1 : 0\"\n @click=\"edit\"\n @keydown.enter=\"!editing && ($event.preventDefault(), edit())\"\n >\n <div>\n <span v-if=\"name\" class=\"sr-only\">{{ name }}: </span>\n <span v-if=\"!local\" class=\"text-sui-ink-muted\">{{ placeholder }}</span>\n <span v-else :class=\"{ 'whitespace-pre-wrap': multiline }\">{{ local }}</span>\n </div>\n <div v-if=\"editing\" class=\"absolute inset-0 z-10\" :class=\"{ '-mt-px': title }\">\n <Textarea\n v-model=\"local\"\n :aria-label=\"name\"\n :auto-resize=\"!title\"\n class=\"resize-none\"\n :class=\"title && 'h-full px-3 py-1.5'\"\n :placeholder=\"placeholder\"\n :rows=\"rows\"\n @blur=\"save\"\n @keydown.enter.stop=\"onEnter\"\n @keydown.esc.stop=\"revert\"\n />\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;A,GAwFMyB,IACJ,qO;;;;;;;;;;;;;;EArEF,IAAMK,IAAQC,GAMRC,IAAOH,GAEPI,IAAQjC,EAAwC+B,GAAA,YAAkB,GAIlEI,IAAQC,EAAS,GACjBC,IAAYC,QAChB,OAAO,YACL,OAAO,QAAQH,CAAK,CAAC,CAAC,QACnB,CAACI,OAASA,MAAQ,iBAAiBA,MAAQ,QAAQA,MAAQ,WAAW,gBAAgB,KAAKA,CAAG,EACjG,CACF,CACF,GACMC,IAAOF,QAAgBH,EAAM,iBAAwCL,EAAM,WAAW,GAEtFW,IAAQH,QAAeR,EAAM,YAAY,OAAO,GAChDY,IAAYJ,QAAeR,EAAM,YAAY,WAAW,GAExDa,IAAQC,EAAIC,EAAMZ,EAAM,KAAK,CAAkB,GAC/Ca,IAAWF,EAAID,EAAM,KAAK,GAC1BI,IAAUH,EAAI,EAAK,GACnBI,IAAUC,EAA4B,SAAS;EAGrD,EAAMhB,IAAQ,MAAU;GACtB,AAAIc,EAAQ,UACZ,EAAM,QAAQF,EAAMK,CAAK,GACzB,EAAS,QAAQP,EAAM;EACzB,CAAC;EAED,IAAMQ,IAAOb,QAAgBG,EAAM,QAAQ,IAAI,KAAK,IAAI,GAAG,KAAK,MAAME,EAAM,OAAO,UAAU,KAAK,EAAE,CAAC,CAAE;EAEvG,eAAeS,IAAO;GACpB,AAAItB,EAAM,aACV,EAAQ,QAAQ,IAChB,MAAMuB,EAAS,GACfL,EAAQ,OAAO,cAAc,UAAU,CAAC,EAAE,MAAM;EAClD;EAEA,SAASM,IAAO;GACd,EAAQ,QAAQ;GAChB,IAAMJ,IAAQL,EAAMF,EAAM,KAAK,KAAK;GAIpC,AAFIO,OAAWL,EAAMZ,EAAM,KAAK,KAAK,UAAO,EAAM,QAAQiB,IAC1D,EAAS,QAAQP,EAAM,OACvBX,EAAK,MAAM;EACb;EAEA,SAASuB,EAAO,GAAsB;GAIpC,AAHAC,EAAM,eAAe,GACrBA,EAAM,gBAAgB,GACtB,EAAM,QAAQV,EAAS,OACvB,EAAQ,QAAQ;EAClB;EAEA,SAASW,EAAQ,GAAsB;GACrC,AAAIf,EAAU,SAASc,EAAM,aAC7BA,EAAM,eAAe,GACpBA,EAAO,OAAuB,KAAK;EACtC;E,iBAUUzB,EAAA,YAAO,YADf9B,EAAA,GAAAC,EAiCSC,GAAA;;GA/BE,YAAA8B,EAAA;G,wBAAA,AAAA2B,EAAA,QAAA,MAAA,EAAA,QAAKC,GAIO,AAAAD,EAAA,QAAA,MAAA5B,EAAI,MAAA,C;GAHxB,cAAYQ,EAAA;GACZ,UAAUT,EAAA;GACV,SAASA,EAAA;;GAGC,SAAO3B,GAuBP,EAvBW,SAAM,WAAQ,kBAAQ,CAC1CC,EAsBS,UAtBTC,EACU+B,EAqBD,OArBU;IAChB,iBAAe4B;IAChB,iBAAc;IACb,OAAK;KAAcxC;;KAA8DM,EAAA,WAAQ,gBAAA;;IAKzF,UAAUA,EAAA;IACX,MAAK;IACJ,SAAOmC;G,KAEI1B,EAAA,SAAZvC,EAAA,GAAAM,EAAqD,QAArDa,GAAqDZ,EAAhBgC,EAAA,KAAI,IAAG,MAAE,CAAA,K,WAEtC8B,EAAQ,MADhBrE,EAAA,GAAAC,EAMEQ,GAAA;;IAJC,MAAM4D,EAAQ,EAAA,CAAI;IAClB,cAAYA,EAAQ,EAAA,CAAI;IACxB,MAAMA,EAAQ,EAAA,CAAI;IACnB,SAAQ;;;;;G,OAEVrE,EAAA,GAAAM,EAAgE,QAAhEc,GAAgEb,EAArBuB,EAAA,WAAW,GAAA,CAAA,E;;;;;;;E,OAI5D9B,EAAA,GAAAM,EAqCM,OArCND,EAqCM,EAAA,KAAA,EAAA,GAnCI+B,EAAA,OAAS;GACb,SAAA;GAAJ,KAAIW;GACJ,OAAK,CAAC,YAAU;IACAvB;IAAagB,EAAA,Q;IAA8XV,EAAA,WAAQ,gBAAA;;;GAQna,MAAK;GACJ,UAAUA,EAAA,WAAQ,KAAA;GAClB,SAAOqB;GACP,WAAO,AAAAQ,EAAA,OAAAjD,GAAA,MAAA,CAASoC,EAAA,UAAYc,EAAO,eAAc,GAAIT,EAAI,IAAA,CAAA,OAAA,CAAA;E,KAE1D/C,EAIM,OAAA,MAAA,CAHQmC,EAAA,SAAZvC,EAAA,GAAAM,EAAqD,QAArDgB,GAAqDf,EAAhBgC,EAAA,KAAI,IAAG,MAAE,CAAA,K,WACjCG,EAAA,SACb1C,EAAA,GAAAM,EAA6E,QAAA;;GAA/D,OAAKK,EAAA,EAAA,uBAA2B8B,EAAA,MAAS,CAAA;EAAO,GAAAlC,EAAAmC,EAAA,KAAK,GAAA,CAAA,MADnE1C,EAAA,GAAAM,EAAuE,QAAvEiB,GAAuEhB,EAArBuB,EAAA,WAAW,GAAA,CAAA,E,IAGpDgB,EAAA,SAAX9C,EAAA,GAAAM,EAaM,OAAA;;GAbc,OAAKK,EAAA,CAAC,yBAAuB,EAAA,UAAqB6B,EAAA,MAAK,CAAA,CAAA;E,IACzE5B,EAWEC,GAAA;GAVS,YAAA6B,EAAA;GAAA,uBAAA,AAAAiB,EAAA,QAAA,MAAA,EAAK,QAAAC;GACb,cAAYrB,EAAA;GACZ,eAAW,CAAGC,EAAA;GACf,OAAK7B,EAAA,CAAC,eACE6B,EAAA,SAAK,oBAAA,CAAA;GACZ,aAAaV,EAAA;GACb,MAAMoB,EAAA;GACN,QAAMG;GACN,WAAO,CAAa3C,EAAAI,EAAA0C,GAAO,CAAA,MAAA,CAAA,GAAA,CAAA,OAAA,CAAA,GACT9C,EAAAI,EAAAwC,GAAM,CAAA,MAAA,CAAA,GAAA,CAAA,KAAA,CAAA,C"}
|
|
1
|
+
{"version":3,"file":"Editable.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createBlock","Select","_withCtx","_createElementVNode","_mergeProps","_createElementBlock","_toDisplayString","_createCommentVNode","Tag","_withKeys","_normalizeClass","_createVNode","Textarea","_withModifiers","Tag_default","Select_default","Textarea_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","field","Editable_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","__emit","props","__props","emit","model","useModel","attrs","useAttrs","rootAttrs","computed","key","name","title","multiline","local","ref","toRaw","original","editing","wrapper","useTemplateRef","value","rows","edit","nextTick","save","revert","event","onEnter","openBlock","createBlock","_cache","$event","withCtx","createElementVNode","mergeProps","open","toggle","createElementBlock","toDisplayString","createCommentVNode","selected","withKeys","normalizeClass","createVNode","withModifiers"],"sources":["../../../src/components/PropertyList/Editable.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, nextTick, ref, toRaw, useAttrs, useTemplateRef, watch } from 'vue'\n\nimport Select from '../Select/Select.vue'\nimport type { SelectOption, SelectValue } from '../Select/types'\nimport Tag from '../Tag/Tag.vue'\nimport Textarea from '../Textarea/Textarea.vue'\n\nexport interface EditableProps {\n /** `text` (one line), `multiline` (Shift+Enter for a new line), `select` (an outline Tag, picked from `options`) or `title`\n * (a record's 18px name). */\n variant?: 'text' | 'multiline' | 'select' | 'title'\n placeholder?: string\n /** For `select`. */\n options?: SelectOption[]\n disabled?: boolean\n}\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<EditableProps>(), {\n variant: 'text',\n placeholder: undefined,\n options: () => []\n})\n\nconst emit = defineEmits<{ blur: [] }>()\n\nconst model = defineModel<string | SelectValue | null>({ default: null })\n\n// Only the id, class and data- and aria- attributes go on the root. The name is said before the value, not as an\n// aria-label, which would hide the value from it.\nconst attrs = useAttrs()\nconst rootAttrs = computed(() =>\n Object.fromEntries(\n Object.entries(attrs).filter(\n ([key]) => key !== 'aria-label' && (key === 'id' || key === 'class' || /^(data|aria)-/.test(key))\n )\n )\n)\nconst name = computed(() => (attrs['aria-label'] as string | undefined) ?? props.placeholder)\n\nconst title = computed(() => props.variant === 'title')\nconst multiline = computed(() => props.variant === 'multiline')\n\nconst local = ref(toRaw(model.value) as string | null)\nconst original = ref(local.value)\nconst editing = ref(false)\nconst wrapper = useTemplateRef<HTMLElement>('wrapper')\n\n// Follows the value from outside (a failed save rolled back, a refetch) unless it's being edited.\nwatch(model, (value) => {\n if (editing.value) return\n local.value = toRaw(value) as string | null\n original.value = local.value\n})\n\nconst rows = computed(() => (title.value ? 1 : Math.max(1, Math.ceil((local.value?.length ?? 0) / 34))))\n\nasync function edit() {\n if (props.disabled) return\n editing.value = true\n await nextTick()\n wrapper.value?.querySelector('textarea')?.focus()\n}\n\nfunction save() {\n editing.value = false\n const value = toRaw(local.value) || null\n // Leaving it untouched isn't a change: an empty value stays as it came, '' or null.\n if (value !== (toRaw(model.value) || null)) model.value = value\n original.value = local.value\n emit('blur')\n}\n\nfunction revert(event: KeyboardEvent) {\n event.preventDefault()\n event.stopPropagation()\n local.value = original.value\n editing.value = false\n}\n\nfunction onEnter(event: KeyboardEvent) {\n if (multiline.value && event.shiftKey) return\n event.preventDefault()\n ;(event.target as HTMLElement).blur()\n}\n\nconst field =\n 'block w-full rounded-lg border border-transparent px-[0.6875rem] py-1.25 text-left text-sui-ink transition-[background-color,border-color,box-shadow] outline-hidden focus-visible:border-sui-accent focus-visible:sui-ring-field'\n</script>\n\n<!-- One value shown as plain text and edited where it is: click or Enter to edit, Enter or leaving to save, Escape to\n undo. A `select` opens its list under the value instead. -->\n<template>\n <Select\n v-if=\"variant === 'select'\"\n v-model=\"model as SelectValue | null\"\n :aria-label=\"name\"\n :disabled=\"disabled\"\n :options=\"options\"\n @update:model-value=\"emit('blur')\"\n >\n <template #trigger=\"{ open, toggle, selected }\">\n <button\n v-bind=\"rootAttrs\"\n :aria-expanded=\"open\"\n aria-haspopup=\"listbox\"\n :class=\"[\n field,\n 'max-w-[16rem] text-sm leading-5',\n disabled ? 'cursor-auto' : 'cursor-pointer hover:bg-sui-fill-hover'\n ]\"\n :disabled=\"disabled\"\n type=\"button\"\n @click=\"toggle\"\n >\n <span v-if=\"name\" class=\"sr-only\">{{ name }}: </span>\n <Tag\n v-if=\"selected[0]\"\n :icon=\"selected[0].icon\"\n :icon-color=\"selected[0].iconColor\"\n :name=\"selected[0].label\"\n variant=\"outline\"\n />\n <span v-else class=\"text-sui-ink-muted\">{{ placeholder }}</span>\n </button>\n </template>\n </Select>\n <div\n v-else\n v-bind=\"rootAttrs\"\n ref=\"wrapper\"\n class=\"relative\"\n :class=\"[\n field,\n title\n ? 'min-h-10 min-w-4 text-lg leading-7 font-semibold [&_textarea]:min-h-10 [&_textarea]:text-lg [&_textarea]:leading-7 [&_textarea]:font-semibold [&_textarea]:whitespace-nowrap [&_textarea]:placeholder:text-lg [&_textarea]:placeholder:font-semibold'\n : 'max-w-[16rem] text-sm leading-5 [&_textarea]:placeholder:text-sm [&_textarea]:placeholder:leading-5',\n disabled ? 'cursor-auto' : 'cursor-pointer hover:bg-sui-fill-hover',\n '[&_textarea]:bg-sui-surface [&_textarea]:placeholder:text-sui-ink-muted'\n ]\"\n role=\"button\"\n :tabindex=\"disabled ? -1 : 0\"\n @click=\"edit\"\n @keydown.enter=\"!editing && ($event.preventDefault(), edit())\"\n >\n <div>\n <span v-if=\"name\" class=\"sr-only\">{{ name }}: </span>\n <span v-if=\"!local\" class=\"text-sui-ink-muted\">{{ placeholder }}</span>\n <span v-else :class=\"{ 'whitespace-pre-wrap': multiline }\">{{ local }}</span>\n </div>\n <div v-if=\"editing\" class=\"absolute inset-0 z-10\" :class=\"{ '-mt-px': title }\">\n <Textarea\n v-model=\"local\"\n :aria-label=\"name\"\n :auto-resize=\"!title\"\n class=\"resize-none\"\n :class=\"title && 'h-full px-3 py-1.5'\"\n :placeholder=\"placeholder\"\n :rows=\"rows\"\n @blur=\"save\"\n @keydown.enter.stop=\"onEnter\"\n @keydown.esc.stop=\"revert\"\n />\n </div>\n </div>\n</template>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SegmentedControl.js","names":["_sfc_main","SegmentedControl_vue_vue_type_script_setup_true_lang_default","SegmentedControl_default"],"sources":["../../../src/components/SegmentedControl/SegmentedControl.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"T extends string\">\nimport { RadioGroupItem, RadioGroupRoot } from 'reka-ui'\n\nimport Icon from '../Icon/Icon.vue'\n\nexport interface SegmentedControlOption<T extends string> {\n value: T\n label: string\n /** An Icon name. */\n iconName?: string\n /** An SVG path on a 24px grid. */\n icon?: string\n}\n\nexport interface SegmentedControlProps<T extends string> {\n options: SegmentedControlOption<T>[]\n /** Fills its row, the segments sharing it evenly with their labels truncated: phone tab bars. */\n block?: boolean\n}\n\ndefineProps<SegmentedControlProps<T>>()\n\nconst model = defineModel<T>({ required: true })\n</script>\n\n<!-- A few choices side by side, one picked: the chosen one lifts onto a card. Arrow keys move between them. -->\n<template>\n <RadioGroupRoot\n v-model=\"model\"\n class=\"flex gap-0.5 rounded-lg bg-sui-
|
|
1
|
+
{"version":3,"file":"SegmentedControl.js","names":["_sfc_main","SegmentedControl_vue_vue_type_script_setup_true_lang_default","SegmentedControl_default"],"sources":["../../../src/components/SegmentedControl/SegmentedControl.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"T extends string\">\nimport { RadioGroupItem, RadioGroupRoot } from 'reka-ui'\n\nimport Icon from '../Icon/Icon.vue'\n\nexport interface SegmentedControlOption<T extends string> {\n value: T\n label: string\n /** An Icon name. */\n iconName?: string\n /** An SVG path on a 24px grid. */\n icon?: string\n}\n\nexport interface SegmentedControlProps<T extends string> {\n options: SegmentedControlOption<T>[]\n /** Fills its row, the segments sharing it evenly with their labels truncated: phone tab bars. */\n block?: boolean\n}\n\ndefineProps<SegmentedControlProps<T>>()\n\nconst model = defineModel<T>({ required: true })\n</script>\n\n<!-- A few choices side by side, one picked: the chosen one lifts onto a card. Arrow keys move between them. -->\n<template>\n <RadioGroupRoot\n v-model=\"model\"\n class=\"flex gap-0.5 rounded-lg bg-sui-track p-0.75 ring-1 ring-sui-fill-line ring-inset\"\n :class=\"block ? 'w-full' : 'w-fit'\"\n orientation=\"horizontal\"\n >\n <RadioGroupItem\n v-for=\"option in options\"\n :key=\"option.value\"\n class=\"inline-flex h-7 items-center gap-1.5 rounded-md text-13 font-medium transition-colors focus-visible:sui-ring-inset [&_svg]:shrink-0 [&_svg]:[stroke-linecap:round] [&_svg]:[stroke-linejoin:round]\"\n :class=\"[\n block ? 'min-w-0 flex-1 justify-center px-2' : 'pr-3 pl-2.5',\n option.value === model\n ? 'bg-sui-lifted text-sui-ink shadow-(--sui-shadow-lifted)'\n : 'text-sui-ink-body hover:text-sui-ink'\n ]\"\n :value=\"option.value\"\n >\n <Icon\n v-if=\"option.iconName\"\n class=\"h-4 w-4\"\n :color=\"option.value === model ? 'ink' : 'ink-body'\"\n :name=\"option.iconName\"\n />\n <svg\n v-else-if=\"option.icon\"\n aria-hidden=\"true\"\n class=\"h-3.5 w-3.5\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n viewBox=\"0 0 24 24\"\n >\n <path :d=\"option.icon\" />\n </svg>\n <span class=\"min-w-0 truncate\">{{ option.label }}</span>\n </RadioGroupItem>\n </RadioGroupRoot>\n</template>\n"],"mappings":""}
|
package/dist/components/SegmentedControl/SegmentedControl.vue_vue_type_script_setup_true_lang.js
CHANGED
|
@@ -25,12 +25,12 @@ var _ = {
|
|
|
25
25
|
return (p, b) => (l(), n(f(g), {
|
|
26
26
|
modelValue: s.value,
|
|
27
27
|
"onUpdate:modelValue": b[0] ||= (e) => s.value = e,
|
|
28
|
-
class: c(["flex gap-0.5 rounded-lg bg-sui-
|
|
28
|
+
class: c(["flex gap-0.5 rounded-lg bg-sui-track p-0.75 ring-1 ring-sui-fill-line ring-inset", o.block ? "w-full" : "w-fit"]),
|
|
29
29
|
orientation: "horizontal"
|
|
30
30
|
}, {
|
|
31
31
|
default: m(() => [(l(!0), i(t, null, u(o.options, (t) => (l(), n(f(h), {
|
|
32
32
|
key: t.value,
|
|
33
|
-
class: c(["inline-flex h-7 items-center gap-1.5 rounded-md text-13 font-medium transition-colors focus-visible:sui-ring-inset [&_svg]:shrink-0 [&_svg]:[stroke-linecap:round] [&_svg]:[stroke-linejoin:round]", [o.block ? "min-w-0 flex-1 justify-center px-2" : "pr-3 pl-2.5", t.value === s.value ? "bg-sui-
|
|
33
|
+
class: c(["inline-flex h-7 items-center gap-1.5 rounded-md text-13 font-medium transition-colors focus-visible:sui-ring-inset [&_svg]:shrink-0 [&_svg]:[stroke-linecap:round] [&_svg]:[stroke-linejoin:round]", [o.block ? "min-w-0 flex-1 justify-center px-2" : "pr-3 pl-2.5", t.value === s.value ? "bg-sui-lifted text-sui-ink shadow-(--sui-shadow-lifted)" : "text-sui-ink-body hover:text-sui-ink"]]),
|
|
34
34
|
value: t.value
|
|
35
35
|
}, {
|
|
36
36
|
default: m(() => [t.iconName ? (l(), n(e, {
|