@sparklingopinions/sparkling-ui 0.7.0 → 0.9.1
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 +2 -2
- package/dist/aliases.d.ts +23 -2
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Button/Button.vue.d.ts +4 -0
- package/dist/components/Button/Button.vue_vue_type_script_setup_true_lang.js +21 -11
- package/dist/components/Button/Button.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.vue_vue_type_script_setup_true_lang.js +29 -20
- package/dist/components/ContextMenu/ContextMenu.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.d.ts +30 -3
- package/dist/components/DataList/DataList.vue_vue_type_script_setup_true_lang.js +188 -100
- package/dist/components/DataList/DataList.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/DataList/types.d.ts +2 -0
- package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.vue_vue_type_script_setup_true_lang.js +32 -23
- package/dist/components/DropdownMenu/DropdownMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Icon/iconSet.js +1 -0
- package/dist/components/Icon/iconSet.js.map +1 -1
- package/dist/components/Icon/resolver.js +3 -2
- package/dist/components/Icon/resolver.js.map +1 -1
- package/dist/components/Popover/PopoverDialog.js +7 -0
- package/dist/components/Popover/PopoverDialog.js.map +1 -0
- package/dist/components/Popover/PopoverDialog.vue.d.ts +56 -0
- package/dist/components/Popover/PopoverDialog.vue_vue_type_script_setup_true_lang.js +158 -0
- package/dist/components/Popover/PopoverDialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/Popover/index.d.ts +2 -0
- package/dist/components/PropertyList/Editable.js.map +1 -1
- package/dist/components/PropertyList/Editable.vue_vue_type_script_setup_true_lang.js +7 -1
- package/dist/components/PropertyList/Editable.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 +189 -139
- package/dist/components/Select/Select.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Select/types.d.ts +5 -0
- package/dist/components/Table/Table.js.map +1 -1
- package/dist/components/Table/Table.vue.d.ts +2 -0
- package/dist/components/Table/Table.vue_vue_type_script_setup_true_lang.js +5 -1
- 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.d.ts +13 -3
- package/dist/components/Tag/Tag.vue_vue_type_script_setup_true_lang.js +41 -27
- package/dist/components/Tag/Tag.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Toast/Toaster.js.map +1 -1
- package/dist/components/Toast/Toaster.vue.d.ts +4 -0
- package/dist/components/Toast/Toaster.vue_vue_type_script_setup_true_lang.js +49 -32
- package/dist/components/Toast/Toaster.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Toolbar/Toolbar.js +7 -0
- package/dist/components/Toolbar/Toolbar.js.map +1 -0
- package/dist/components/Toolbar/Toolbar.vue.d.ts +23 -0
- package/dist/components/Toolbar/Toolbar.vue_vue_type_script_setup_true_lang.js +52 -0
- package/dist/components/Toolbar/Toolbar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/Toolbar/index.d.ts +2 -0
- package/dist/components/internal/MenuItemContent.js.map +1 -1
- package/dist/components/internal/MenuItemContent.vue.d.ts +1 -0
- package/dist/components/internal/MenuItemContent.vue_vue_type_script_setup_true_lang.js +30 -14
- package/dist/components/internal/MenuItemContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/internal/menu.d.ts +5 -1
- package/dist/components/internal/menu.js +17 -14
- package/dist/components/internal/menu.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +18 -16
- package/package.json +1 -1
- package/src/styles/tailwind.css +22 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tag.vue_vue_type_script_setup_true_lang.js","names":["$emit","_useModel","_openBlock","_createElementBlock","_normalizeClass","_createElementVNode","_createCommentVNode","_renderSlot","_createTextVNode","_toDisplayString","_createVNode","CloseSmallIcon","CloseSmallIcon_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","Tag_vue_vue_type_script_setup_true_lang_default","\"pressed\"","\"pressedModifiers\"","pressed","useModel","__props","dots","openBlock","createElementBlock","normalizeClass","_cache","createElementVNode","createCommentVNode","renderSlot","_ctx","createTextVNode","toDisplayString","createVNode"],"sources":["../../../src/components/Tag/Tag.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { Hue } from '../../utils/hues'\nimport CloseSmallIcon from '../internal/CloseSmallIcon.vue'\n\nexport interface TagProps {\n /** The text; or use the default slot. */\n name?: string\n /** soft: a label people create, with an optional hue dot, removable. outline: a value from a fixed set (a stage, a status). */\n variant?: 'soft' | 'outline'\n /** soft only: a dot of the tag's own hue, on a neutral chip. */\n color?: Hue\n /** outline only: the quieter, superseded side, e.g. the \"from\" of a stage change. */\n muted?: boolean\n /** soft only. */\n removable?: boolean\n /** The remove button's accessible name. */\n removeLabel?: string\n /** A toggle button for quick choices, bound to `v-model:pressed`. Group several in a `role=\"group\"` with a label. */\n pressable?: boolean\n /** pressable only. */\n disabled?: boolean\n}\n\nwithDefaults(defineProps<TagProps>(), {\n name: undefined,\n variant: 'soft',\n color: undefined,\n removeLabel: 'Remove tag'\n})\n\ndefineEmits<{ remove: [] }>()\n\nconst pressed = defineModel<boolean>('pressed', { default: false })\n\nconst dots: Record<Hue, string> = {\n blue: 'bg-sui-hue-blue-ink',\n green: 'bg-sui-hue-green-ink',\n orange: 'bg-sui-hue-orange-ink',\n pink: 'bg-sui-hue-pink-ink',\n purple: 'bg-sui-hue-purple-ink',\n slate: 'bg-sui-hue-slate-ink',\n red: 'bg-sui-hue-red-ink',\n amber: 'bg-sui-hue-amber-ink',\n gray: 'bg-sui-ink'\n}\n</script>\n\n<!-- A label: soft for the ones people create, outline for a value from a fixed set; or, pressable, a toggle chip. -->\n<template>\n <button\n v-if=\"pressable\"\n :aria-pressed=\"pressed\"\n class=\"inline-flex
|
|
1
|
+
{"version":3,"file":"Tag.vue_vue_type_script_setup_true_lang.js","names":["$emit","_useModel","_openBlock","_createElementBlock","_normalizeClass","_createElementVNode","_createCommentVNode","_renderSlot","_createTextVNode","_toDisplayString","_createBlock","Icon","_createVNode","CloseSmallIcon","Icon_default","CloseSmallIcon_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","Tag_vue_vue_type_script_setup_true_lang_default","\"pressed\"","\"pressedModifiers\"","pressed","useModel","__props","dots","openBlock","createElementBlock","normalizeClass","_cache","createElementVNode","createCommentVNode","renderSlot","_ctx","createTextVNode","toDisplayString","createBlock","createVNode"],"sources":["../../../src/components/Tag/Tag.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { Hue } from '../../utils/hues'\nimport Icon from '../Icon/Icon.vue'\nimport type { IconColor } from '../Icon/colors'\nimport CloseSmallIcon from '../internal/CloseSmallIcon.vue'\n\nexport interface TagProps {\n /** The text; or use the default slot. */\n name?: string\n /** soft: a label people create, with an optional hue dot, removable. outline: a value from a fixed set (a stage, a status). */\n variant?: 'soft' | 'outline'\n /** soft only: a dot of the tag's own hue, on a neutral chip. */\n color?: Hue\n /** soft and outline: a 14px icon before the name, through the app's icon resolver, in place of the dot. */\n icon?: string\n /** The icon's colour; ink-subtle by default. */\n iconColor?: IconColor\n /** outline only: the quieter, superseded side, e.g. the \"from\" of a stage change. */\n muted?: boolean\n /** soft only. */\n removable?: boolean\n /** The remove button's accessible name. */\n removeLabel?: string\n /** A toggle button for quick choices, bound to `v-model:pressed`. Group several in a `role=\"group\"` with a label. */\n pressable?: boolean\n /** pressable only. */\n disabled?: boolean\n /** pressable only: md is 28px, sm 22px for a dense row of filters. */\n size?: 'sm' | 'md'\n}\n\nwithDefaults(defineProps<TagProps>(), {\n name: undefined,\n variant: 'soft',\n color: undefined,\n icon: undefined,\n iconColor: 'ink-subtle',\n removeLabel: 'Remove tag',\n size: 'md'\n})\n\ndefineEmits<{ remove: [] }>()\n\nconst pressed = defineModel<boolean>('pressed', { default: false })\n\nconst dots: Record<Hue, string> = {\n blue: 'bg-sui-hue-blue-ink',\n green: 'bg-sui-hue-green-ink',\n orange: 'bg-sui-hue-orange-ink',\n pink: 'bg-sui-hue-pink-ink',\n purple: 'bg-sui-hue-purple-ink',\n slate: 'bg-sui-hue-slate-ink',\n red: 'bg-sui-hue-red-ink',\n amber: 'bg-sui-hue-amber-ink',\n gray: 'bg-sui-ink'\n}\n</script>\n\n<!-- A label: soft for the ones people create, outline for a value from a fixed set; or, pressable, a toggle chip. -->\n<template>\n <button\n v-if=\"pressable\"\n :aria-pressed=\"pressed\"\n class=\"inline-flex cursor-pointer items-center rounded-md border leading-none font-medium whitespace-nowrap transition-colors duration-150 outline-hidden focus-visible:sui-ring disabled:cursor-default disabled:opacity-50\"\n :class=\"[\n size === 'sm' ? 'h-5.5 gap-1 px-2 text-xs' : 'h-7 gap-1.5 px-3 text-13',\n pressed\n ? 'border-sui-accent-line bg-sui-accent-wash text-sui-accent enabled:hover:border-sui-accent-bright enabled:hover:bg-sui-accent-soft enabled:active:border-sui-accent-solid enabled:active:bg-sui-accent-soft'\n : 'border-sui-line bg-sui-surface text-sui-ink-body enabled:hover:border-sui-line-strong enabled:hover:bg-sui-canvas enabled:hover:text-sui-ink enabled:active:bg-sui-sunken'\n ]\"\n :disabled=\"disabled\"\n type=\"button\"\n @click=\"pressed = !pressed\"\n >\n <svg\n v-if=\"pressed\"\n aria-hidden=\"true\"\n class=\"-ml-0.5 size-3 shrink-0 fill-none stroke-current\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.75\"\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M3.5 8.25l3 3 6-6.5\" />\n </svg>\n <slot>{{ name }}</slot>\n </button>\n <span\n v-else-if=\"variant === 'outline'\"\n class=\"inline-flex items-center gap-1.5 rounded-md border px-2 py-1 text-xs whitespace-nowrap\"\n :class=\"\n muted ? 'border-sui-line-subtle text-sui-ink-muted' : 'border-sui-line bg-sui-sunken font-medium text-sui-ink'\n \"\n >\n <Icon v-if=\"icon\" class=\"size-3.5 shrink-0\" :color=\"iconColor\" :name=\"icon\" />\n <slot>{{ name }}</slot>\n </span>\n <div\n v-else\n class=\"inline-flex items-center gap-1.5 rounded-md bg-sui-sunken px-2 py-0.5 text-xs font-medium text-sui-ink-body\"\n >\n <Icon v-if=\"icon\" class=\"size-3.5 shrink-0\" :color=\"iconColor\" :name=\"icon\" />\n <span v-else-if=\"color\" class=\"h-1.5 w-1.5 shrink-0 rounded-full\" :class=\"dots[color]\" />\n <span class=\"truncate\"\n ><slot>{{ name }}</slot></span\n >\n <button\n v-if=\"removable\"\n :aria-label=\"removeLabel\"\n class=\"-mr-0.5 inline-flex h-3.5 w-3.5 items-center justify-center rounded-full transition-colors hover:bg-sui-line focus-visible:sui-ring\"\n type=\"button\"\n @click=\"$emit('remove')\"\n >\n <CloseSmallIcon class=\"fill-sui-ink-muted stroke-sui-ink-muted\" />\n </button>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2CA,IAAMwB,IAAUvB,EAAoByB,GAAC,SAA6B,GAE5DC,IAA4B;GAChC,MAAM;GACN,OAAO;GACP,QAAQ;GACR,MAAM;GACN,QAAQ;GACR,OAAO;GACP,KAAK;GACL,OAAO;GACP,MAAM;EACR;E,iBAMUD,EAAA,aADRxB,EAAA,GAAAC,EA0BS,UAAA;;GAxBN,gBAAcqB,EAAA;GACf,OAAKpB,EAAA,CAAC,yNAAuN,CAC7MsB,EAAA,SAAI,OAAA,6BAAA,4BAA2EF,EAAA,Q;GAM9F,UAAUE,EAAA;GACX,MAAK;GACJ,SAAK,AAAAK,EAAA,QAAA,MAAE,EAAA,QAAO,CAAIP,EAAA;E,IAGXA,EAAA,SADRtB,EAAA,GAAAC,EAUM,OAVNc,GAUM,CAAA,GAAA,AAAAc,EAAA,OAAA,CADJ1B,EAAgC,QAAA,EAA1B,GAAE,sBAAqB,GAAA,MAAA,EAAA,C,kBAE/BE,EAAuB4B,EAAA,QAAA,WAAA,CAAA,SAAA,CAAd3B,EAAAC,EAAAiB,EAAA,IAAI,GAAA,CAAA,C,eAGFA,EAAA,YAAO,aADpBxB,EAAA,GAAAC,EASO,QAAA;;GAPL,OAAKC,EAAA,CAAC,0FACSsB,EAAA,QAAK,8CAAA,wD;E,IAIRA,EAAA,QAAZxB,EAAA,GAAAQ,EAA8EC,GAAA;;GAA5D,OAAM;GAAqB,OAAOe,EAAA;GAAY,MAAMA,EAAA;E,6CACtEnB,EAAuB4B,EAAA,QAAA,WAAA,CAAA,SAAA,CAAd3B,EAAAC,EAAAiB,EAAA,IAAI,GAAA,CAAA,C,YAEfxB,EAAA,GAAAC,EAkBM,OAlBNe,GAkBM;GAdQQ,EAAA,QAAZxB,EAAA,GAAAQ,EAA8EC,GAAA;;IAA5D,OAAM;IAAqB,OAAOe,EAAA;IAAY,MAAMA,EAAA;G,kCACrDA,EAAA,SAAjBxB,EAAA,GAAAC,EAAyF,QAAA;;IAAjE,OAAKC,EAAA,CAAC,qCAA4CuB,EAAKD,EAAA,MAAK,CAAA;;GACpFrB,EAEC,QAFDc,GAEC,CADEZ,EAAuB4B,EAAA,QAAA,WAAA,CAAA,SAAA,CAAd3B,EAAAC,EAAAiB,EAAA,IAAI,GAAA,CAAA,C;GAGRA,EAAA,aADRxB,EAAA,GAAAC,EAQS,UAAA;;IANN,cAAYuB,EAAA;IACb,OAAM;IACN,MAAK;IACJ,SAAK,AAAAK,EAAA,QAAA,MAAE/B,EAAAA,MAAK,QAAA;G,IAEbY,EAAkEC,GAAA,EAAlD,OAAM,0CAAyC,CAAA,C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toaster.js","names":["_sfc_main","Toaster_vue_vue_type_script_setup_true_lang_default","Toaster_default"],"sources":["../../../src/components/Toast/Toaster.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { reactive } from 'vue'\n\nimport { ToastProvider, ToastRoot, ToastViewport } from 'reka-ui'\n\nimport {\n type ToastAction,\n type ToastDismissReason,\n type ToastSeverity,\n removeToast,\n toastActions,\n toasts\n} from '../../composables/toast'\nimport ToastMessage from './ToastMessage.vue'\n\nexport interface ToastPreview {\n /** Keeps its place as the list changes, so toasts animate in and out like live ones. Defaults to its index. */\n id?: string | number\n summary: string\n detail?: string\n severity?: ToastSeverity\n closable?: boolean\n action?: ToastAction\n actions?: ToastAction[]\n /** With actions, the countdown bar's length in ms; it emits `close` with `timeout` when it runs out. */\n life?: number\n}\n\nexport interface ToasterProps {\n /** The toast region's name for assistive tech; `{hotkey}` is F8, which focuses it. */\n label?: string\n closeLabel?: string\n /**\n * Toasts drawn in place, for docs, designs and demos, instead of the live ones fixed to the viewport. The list is\n * yours: add and remove items, and handle `close`.\n */\n preview?: ToastPreview[]\n}\n\
|
|
1
|
+
{"version":3,"file":"Toaster.js","names":["_sfc_main","Toaster_vue_vue_type_script_setup_true_lang_default","Toaster_default"],"sources":["../../../src/components/Toast/Toaster.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, reactive } from 'vue'\n\nimport { ToastProvider, ToastRoot, ToastViewport } from 'reka-ui'\n\nimport {\n type ToastAction,\n type ToastDismissReason,\n type ToastSeverity,\n removeToast,\n toastActions,\n toasts\n} from '../../composables/toast'\nimport ToastMessage from './ToastMessage.vue'\n\nexport interface ToastPreview {\n /** Keeps its place as the list changes, so toasts animate in and out like live ones. Defaults to its index. */\n id?: string | number\n summary: string\n detail?: string\n severity?: ToastSeverity\n closable?: boolean\n action?: ToastAction\n actions?: ToastAction[]\n /** With actions, the countdown bar's length in ms; it emits `close` with `timeout` when it runs out. */\n life?: number\n}\n\nexport type ToasterPosition = 'bottom-center' | 'bottom-left' | 'bottom-right' | 'top-center' | 'top-left' | 'top-right'\n\nexport interface ToasterProps {\n /** Where live toasts sit. Move them clear of the app's own chrome with the `--sui-toaster-inset-*` tokens. */\n position?: ToasterPosition\n /** The toast region's name for assistive tech; `{hotkey}` is F8, which focuses it. */\n label?: string\n closeLabel?: string\n /**\n * Toasts drawn in place, for docs, designs and demos, instead of the live ones fixed to the viewport. The list is\n * yours: add and remove items, and handle `close`.\n */\n preview?: ToastPreview[]\n}\n\nconst props = withDefaults(defineProps<ToasterProps>(), {\n position: 'bottom-center',\n label: 'Notifications ({hotkey})',\n closeLabel: 'Close',\n preview: undefined\n})\n\nconst emit = defineEmits<{\n /** A preview toast left, with its `id` (or index): its close button, one of its actions, or its countdown. */\n close: [id: string | number, reason: ToastDismissReason]\n}>()\n\n// Reka pauses every toast's timer while the region is hovered or focused, or the window is in the background; the\n// countdown bars follow it.\nconst paused = reactive(new Set<number>())\n\n// The region sits `--sui-toaster-margin` in from the viewport's edges plus the app's insets, and the safe area\n// beyond them; centred, it centres in what's left between the side insets.\nconst side = (edge: 'left' | 'right') => `calc(var(--sui-toaster-margin) + var(--sui-toaster-inset-${edge}))`\nconst placement = computed(() => {\n const [vertical, horizontal] = props.position.split('-') as ['top' | 'bottom', 'left' | 'center' | 'right']\n return {\n [vertical]: `calc(var(--sui-toaster-margin) + var(--sui-toaster-inset-${vertical}) + env(safe-area-inset-${vertical}))`,\n left: horizontal === 'right' ? 'auto' : side('left'),\n right: horizontal === 'left' ? 'auto' : side('right'),\n width: `min(var(--sui-toaster-width), 100vw - ${side('left')} - ${side('right')})`\n }\n})\nconst fromTop = computed(() => props.position.startsWith('top'))\n\nfunction runLive(id: number, action: ToastAction) {\n action.onClick()\n removeToast(id, 'action')\n}\n\nfunction runPreview(id: string | number, action: ToastAction) {\n action.onClick()\n emit('close', id, 'action')\n}\n</script>\n\n<!-- Mount once near the app root; `toast.info(...)` and friends show here. Swiping is off. -->\n<template>\n <TransitionGroup\n v-if=\"preview\"\n class=\"flex w-full max-w-96 flex-col\"\n enter-active-class=\"animate-sui-toast-in\"\n leave-active-class=\"animate-sui-toast-out overflow-hidden\"\n tag=\"div\"\n >\n <ToastMessage\n v-for=\"(item, index) in preview\"\n :key=\"item.id ?? index\"\n :actions=\"toastActions(item)\"\n :closable=\"item.closable\"\n :close-label=\"closeLabel\"\n :detail=\"item.detail\"\n :life=\"item.life\"\n :severity=\"item.severity\"\n :summary=\"item.summary\"\n @action=\"runPreview(item.id ?? index, $event)\"\n @close=\"emit('close', item.id ?? index, 'close')\"\n @expire=\"emit('close', item.id ?? index, 'timeout')\"\n />\n </TransitionGroup>\n <ToastProvider v-else :swipe-threshold=\"Number.POSITIVE_INFINITY\">\n <ToastRoot\n v-for=\"item in toasts\"\n :key=\"item.id\"\n as-child\n :duration=\"item.life || Number.POSITIVE_INFINITY\"\n :open=\"item.open\"\n :type=\"item.severity === 'error' ? 'foreground' : 'background'\"\n @escape-key-down=\"removeToast(item.id, 'close')\"\n @pause=\"paused.add(item.id)\"\n @resume=\"paused.delete(item.id)\"\n @update:open=\"(open) => !open && removeToast(item.id, 'timeout')\"\n >\n <ToastMessage\n :actions=\"item.actions\"\n class=\"pointer-events-auto data-[state=closed]:overflow-hidden data-[state=closed]:animate-sui-toast-out motion-reduce:data-[state=closed]:animate-sui-toast-fade\"\n :class=\"\n fromTop\n ? 'data-[state=open]:animate-sui-toast-in-top motion-reduce:data-[state=open]:animate-sui-fade-in'\n : 'data-[state=open]:animate-sui-toast-in motion-reduce:data-[state=open]:animate-sui-fade-in'\n \"\n :closable=\"item.closable\"\n :close-label=\"closeLabel\"\n :detail=\"item.detail\"\n :life=\"item.life\"\n :paused=\"paused.has(item.id)\"\n :severity=\"item.severity\"\n :summary=\"item.summary\"\n @action=\"runLive(item.id, $event)\"\n @close=\"removeToast(item.id, 'close')\"\n />\n </ToastRoot>\n <!-- A div, not Reka's default ol: the toasts are divs, so a page can draw one alone. From the top, the newest is\n nearest the edge, as it is at the bottom. -->\n <ToastViewport\n as=\"div\"\n class=\"pointer-events-none fixed z-[1200] mx-auto flex rounded-md outline-hidden\"\n :class=\"fromTop ? 'flex-col-reverse' : 'flex-col'\"\n :data-sui-position=\"position\"\n data-sui-toasts\n :label=\"label\"\n :style=\"placement\"\n />\n </ToastProvider>\n</template>\n"],"mappings":""}
|
|
@@ -11,7 +11,10 @@ export interface ToastPreview {
|
|
|
11
11
|
/** With actions, the countdown bar's length in ms; it emits `close` with `timeout` when it runs out. */
|
|
12
12
|
life?: number;
|
|
13
13
|
}
|
|
14
|
+
export type ToasterPosition = 'bottom-center' | 'bottom-left' | 'bottom-right' | 'top-center' | 'top-left' | 'top-right';
|
|
14
15
|
export interface ToasterProps {
|
|
16
|
+
/** Where live toasts sit. Move them clear of the app's own chrome with the `--sui-toaster-inset-*` tokens. */
|
|
17
|
+
position?: ToasterPosition;
|
|
15
18
|
/** The toast region's name for assistive tech; `{hotkey}` is F8, which focuses it. */
|
|
16
19
|
label?: string;
|
|
17
20
|
closeLabel?: string;
|
|
@@ -28,6 +31,7 @@ declare const __VLS_export: import("vue").DefineComponent<ToasterProps, {}, {},
|
|
|
28
31
|
}>, {
|
|
29
32
|
label: string;
|
|
30
33
|
closeLabel: string;
|
|
34
|
+
position: ToasterPosition;
|
|
31
35
|
preview: ToastPreview[];
|
|
32
36
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
33
37
|
declare const _default: typeof __VLS_export;
|
|
@@ -1,43 +1,52 @@
|
|
|
1
1
|
import { removeToast as e, toastActions as t, toasts as n } from "../../composables/toast.js";
|
|
2
2
|
import r from "./ToastMessage.js";
|
|
3
|
-
import { Fragment as i, TransitionGroup as a,
|
|
4
|
-
import { ToastProvider as
|
|
3
|
+
import { Fragment as i, TransitionGroup as a, computed as o, createBlock as s, createElementBlock as c, createVNode as l, defineComponent as u, normalizeClass as d, normalizeStyle as f, openBlock as p, reactive as m, renderList as h, unref as g, withCtx as _ } from "vue";
|
|
4
|
+
import { ToastProvider as v, ToastRoot as y, ToastViewport as b } from "reka-ui";
|
|
5
5
|
//#region src/components/Toast/Toaster.vue?vue&type=script&setup=true&lang.ts
|
|
6
|
-
var
|
|
6
|
+
var x = /*@__PURE__*/ u({
|
|
7
7
|
__name: "Toaster",
|
|
8
8
|
props: {
|
|
9
|
+
position: { default: "bottom-center" },
|
|
9
10
|
label: { default: "Notifications ({hotkey})" },
|
|
10
11
|
closeLabel: { default: "Close" },
|
|
11
12
|
preview: { default: void 0 }
|
|
12
13
|
},
|
|
13
14
|
emits: ["close"],
|
|
14
|
-
setup(
|
|
15
|
-
let
|
|
16
|
-
|
|
15
|
+
setup(u, { emit: x }) {
|
|
16
|
+
let S = u, C = x, w = m(/* @__PURE__ */ new Set()), T = (e) => `calc(var(--sui-toaster-margin) + var(--sui-toaster-inset-${e}))`, E = o(() => {
|
|
17
|
+
let [e, t] = S.position.split("-");
|
|
18
|
+
return {
|
|
19
|
+
[e]: `calc(var(--sui-toaster-margin) + var(--sui-toaster-inset-${e}) + env(safe-area-inset-${e}))`,
|
|
20
|
+
left: t === "right" ? "auto" : T("left"),
|
|
21
|
+
right: t === "left" ? "auto" : T("right"),
|
|
22
|
+
width: `min(var(--sui-toaster-width), 100vw - ${T("left")} - ${T("right")})`
|
|
23
|
+
};
|
|
24
|
+
}), D = o(() => S.position.startsWith("top"));
|
|
25
|
+
function O(t, n) {
|
|
17
26
|
n.onClick(), e(t, "action");
|
|
18
27
|
}
|
|
19
|
-
function
|
|
20
|
-
t.onClick(),
|
|
28
|
+
function k(e, t) {
|
|
29
|
+
t.onClick(), C("close", e, "action");
|
|
21
30
|
}
|
|
22
|
-
return (
|
|
31
|
+
return (o, m) => u.preview ? (p(), s(a, {
|
|
23
32
|
key: 0,
|
|
24
33
|
class: "flex w-full max-w-96 flex-col",
|
|
25
34
|
"enter-active-class": "animate-sui-toast-in",
|
|
26
35
|
"leave-active-class": "animate-sui-toast-out overflow-hidden",
|
|
27
36
|
tag: "div"
|
|
28
37
|
}, {
|
|
29
|
-
default:
|
|
38
|
+
default: _(() => [(p(!0), c(i, null, h(u.preview, (e, n) => (p(), s(r, {
|
|
30
39
|
key: e.id ?? n,
|
|
31
|
-
actions:
|
|
40
|
+
actions: g(t)(e),
|
|
32
41
|
closable: e.closable,
|
|
33
|
-
"close-label":
|
|
42
|
+
"close-label": u.closeLabel,
|
|
34
43
|
detail: e.detail,
|
|
35
44
|
life: e.life,
|
|
36
45
|
severity: e.severity,
|
|
37
46
|
summary: e.summary,
|
|
38
|
-
onAction: (t) =>
|
|
39
|
-
onClose: (t) =>
|
|
40
|
-
onExpire: (t) =>
|
|
47
|
+
onAction: (t) => k(e.id ?? n, t),
|
|
48
|
+
onClose: (t) => C("close", e.id ?? n, "close"),
|
|
49
|
+
onExpire: (t) => C("close", e.id ?? n, "timeout")
|
|
41
50
|
}, null, 8, [
|
|
42
51
|
"actions",
|
|
43
52
|
"closable",
|
|
@@ -51,35 +60,36 @@ var v = /*@__PURE__*/ l({
|
|
|
51
60
|
"onExpire"
|
|
52
61
|
]))), 128))]),
|
|
53
62
|
_: 1
|
|
54
|
-
})) : (
|
|
63
|
+
})) : (p(), s(g(v), {
|
|
55
64
|
key: 1,
|
|
56
65
|
"swipe-threshold": Infinity
|
|
57
66
|
}, {
|
|
58
|
-
default:
|
|
67
|
+
default: _(() => [(p(!0), c(i, null, h(g(n), (t) => (p(), s(g(y), {
|
|
59
68
|
key: t.id,
|
|
60
69
|
"as-child": "",
|
|
61
70
|
duration: t.life || Infinity,
|
|
62
71
|
open: t.open,
|
|
63
72
|
type: t.severity === "error" ? "foreground" : "background",
|
|
64
|
-
onEscapeKeyDown: (n) =>
|
|
65
|
-
onPause: (e) =>
|
|
66
|
-
onResume: (e) =>
|
|
67
|
-
"onUpdate:open": (n) => !n &&
|
|
73
|
+
onEscapeKeyDown: (n) => g(e)(t.id, "close"),
|
|
74
|
+
onPause: (e) => w.add(t.id),
|
|
75
|
+
onResume: (e) => w.delete(t.id),
|
|
76
|
+
"onUpdate:open": (n) => !n && g(e)(t.id, "timeout")
|
|
68
77
|
}, {
|
|
69
|
-
default:
|
|
78
|
+
default: _(() => [l(r, {
|
|
70
79
|
actions: t.actions,
|
|
71
|
-
class: "pointer-events-auto data-[state=closed]:animate-sui-toast-out data-[state=closed]:
|
|
80
|
+
class: d(["pointer-events-auto data-[state=closed]:overflow-hidden data-[state=closed]:animate-sui-toast-out motion-reduce:data-[state=closed]:animate-sui-toast-fade", D.value ? "data-[state=open]:animate-sui-toast-in-top motion-reduce:data-[state=open]:animate-sui-fade-in" : "data-[state=open]:animate-sui-toast-in motion-reduce:data-[state=open]:animate-sui-fade-in"]),
|
|
72
81
|
closable: t.closable,
|
|
73
|
-
"close-label":
|
|
82
|
+
"close-label": u.closeLabel,
|
|
74
83
|
detail: t.detail,
|
|
75
84
|
life: t.life,
|
|
76
|
-
paused:
|
|
85
|
+
paused: w.has(t.id),
|
|
77
86
|
severity: t.severity,
|
|
78
87
|
summary: t.summary,
|
|
79
|
-
onAction: (e) =>
|
|
80
|
-
onClose: (n) =>
|
|
88
|
+
onAction: (e) => O(t.id, e),
|
|
89
|
+
onClose: (n) => g(e)(t.id, "close")
|
|
81
90
|
}, null, 8, [
|
|
82
91
|
"actions",
|
|
92
|
+
"class",
|
|
83
93
|
"closable",
|
|
84
94
|
"close-label",
|
|
85
95
|
"detail",
|
|
@@ -99,17 +109,24 @@ var v = /*@__PURE__*/ l({
|
|
|
99
109
|
"onPause",
|
|
100
110
|
"onResume",
|
|
101
111
|
"onUpdate:open"
|
|
102
|
-
]))), 128)),
|
|
112
|
+
]))), 128)), l(g(b), {
|
|
103
113
|
as: "div",
|
|
104
|
-
class: "pointer-events-none fixed
|
|
114
|
+
class: d(["pointer-events-none fixed z-[1200] mx-auto flex rounded-md outline-hidden", D.value ? "flex-col-reverse" : "flex-col"]),
|
|
115
|
+
"data-sui-position": u.position,
|
|
105
116
|
"data-sui-toasts": "",
|
|
106
|
-
label:
|
|
107
|
-
|
|
117
|
+
label: u.label,
|
|
118
|
+
style: f(E.value)
|
|
119
|
+
}, null, 8, [
|
|
120
|
+
"class",
|
|
121
|
+
"data-sui-position",
|
|
122
|
+
"label",
|
|
123
|
+
"style"
|
|
124
|
+
])]),
|
|
108
125
|
_: 1
|
|
109
126
|
}, 8, ["swipe-threshold"]));
|
|
110
127
|
}
|
|
111
128
|
});
|
|
112
129
|
//#endregion
|
|
113
|
-
export {
|
|
130
|
+
export { x as default };
|
|
114
131
|
|
|
115
132
|
//# sourceMappingURL=Toaster.vue_vue_type_script_setup_true_lang.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toaster.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","_TransitionGroup","_withCtx","_createElementBlock","_Fragment","_renderList","ToastMessage","_unref","_createVNode","ToastMessage_default","Toaster_vue_vue_type_script_setup_true_lang_default","__emit","emit","paused","reactive","runLive","action","removeToast","id","runPreview","
|
|
1
|
+
{"version":3,"file":"Toaster.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","_TransitionGroup","_withCtx","_createElementBlock","_Fragment","_renderList","ToastMessage","_unref","_createVNode","_normalizeClass","_normalizeStyle","ToastMessage_default","Toaster_vue_vue_type_script_setup_true_lang_default","__emit","props","__props","emit","paused","reactive","side","edge","placement","computed","vertical","horizontal","fromTop","runLive","action","removeToast","id","runPreview","openBlock","createBlock","TransitionGroup","withCtx","createElementBlock","Fragment","renderList","item","index","unref","toastActions","$event","ToastProvider","toasts","ToastRoot","open","createVNode","normalizeClass","ToastViewport","normalizeStyle"],"sources":["../../../src/components/Toast/Toaster.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, reactive } from 'vue'\n\nimport { ToastProvider, ToastRoot, ToastViewport } from 'reka-ui'\n\nimport {\n type ToastAction,\n type ToastDismissReason,\n type ToastSeverity,\n removeToast,\n toastActions,\n toasts\n} from '../../composables/toast'\nimport ToastMessage from './ToastMessage.vue'\n\nexport interface ToastPreview {\n /** Keeps its place as the list changes, so toasts animate in and out like live ones. Defaults to its index. */\n id?: string | number\n summary: string\n detail?: string\n severity?: ToastSeverity\n closable?: boolean\n action?: ToastAction\n actions?: ToastAction[]\n /** With actions, the countdown bar's length in ms; it emits `close` with `timeout` when it runs out. */\n life?: number\n}\n\nexport type ToasterPosition = 'bottom-center' | 'bottom-left' | 'bottom-right' | 'top-center' | 'top-left' | 'top-right'\n\nexport interface ToasterProps {\n /** Where live toasts sit. Move them clear of the app's own chrome with the `--sui-toaster-inset-*` tokens. */\n position?: ToasterPosition\n /** The toast region's name for assistive tech; `{hotkey}` is F8, which focuses it. */\n label?: string\n closeLabel?: string\n /**\n * Toasts drawn in place, for docs, designs and demos, instead of the live ones fixed to the viewport. The list is\n * yours: add and remove items, and handle `close`.\n */\n preview?: ToastPreview[]\n}\n\nconst props = withDefaults(defineProps<ToasterProps>(), {\n position: 'bottom-center',\n label: 'Notifications ({hotkey})',\n closeLabel: 'Close',\n preview: undefined\n})\n\nconst emit = defineEmits<{\n /** A preview toast left, with its `id` (or index): its close button, one of its actions, or its countdown. */\n close: [id: string | number, reason: ToastDismissReason]\n}>()\n\n// Reka pauses every toast's timer while the region is hovered or focused, or the window is in the background; the\n// countdown bars follow it.\nconst paused = reactive(new Set<number>())\n\n// The region sits `--sui-toaster-margin` in from the viewport's edges plus the app's insets, and the safe area\n// beyond them; centred, it centres in what's left between the side insets.\nconst side = (edge: 'left' | 'right') => `calc(var(--sui-toaster-margin) + var(--sui-toaster-inset-${edge}))`\nconst placement = computed(() => {\n const [vertical, horizontal] = props.position.split('-') as ['top' | 'bottom', 'left' | 'center' | 'right']\n return {\n [vertical]: `calc(var(--sui-toaster-margin) + var(--sui-toaster-inset-${vertical}) + env(safe-area-inset-${vertical}))`,\n left: horizontal === 'right' ? 'auto' : side('left'),\n right: horizontal === 'left' ? 'auto' : side('right'),\n width: `min(var(--sui-toaster-width), 100vw - ${side('left')} - ${side('right')})`\n }\n})\nconst fromTop = computed(() => props.position.startsWith('top'))\n\nfunction runLive(id: number, action: ToastAction) {\n action.onClick()\n removeToast(id, 'action')\n}\n\nfunction runPreview(id: string | number, action: ToastAction) {\n action.onClick()\n emit('close', id, 'action')\n}\n</script>\n\n<!-- Mount once near the app root; `toast.info(...)` and friends show here. Swiping is off. -->\n<template>\n <TransitionGroup\n v-if=\"preview\"\n class=\"flex w-full max-w-96 flex-col\"\n enter-active-class=\"animate-sui-toast-in\"\n leave-active-class=\"animate-sui-toast-out overflow-hidden\"\n tag=\"div\"\n >\n <ToastMessage\n v-for=\"(item, index) in preview\"\n :key=\"item.id ?? index\"\n :actions=\"toastActions(item)\"\n :closable=\"item.closable\"\n :close-label=\"closeLabel\"\n :detail=\"item.detail\"\n :life=\"item.life\"\n :severity=\"item.severity\"\n :summary=\"item.summary\"\n @action=\"runPreview(item.id ?? index, $event)\"\n @close=\"emit('close', item.id ?? index, 'close')\"\n @expire=\"emit('close', item.id ?? index, 'timeout')\"\n />\n </TransitionGroup>\n <ToastProvider v-else :swipe-threshold=\"Number.POSITIVE_INFINITY\">\n <ToastRoot\n v-for=\"item in toasts\"\n :key=\"item.id\"\n as-child\n :duration=\"item.life || Number.POSITIVE_INFINITY\"\n :open=\"item.open\"\n :type=\"item.severity === 'error' ? 'foreground' : 'background'\"\n @escape-key-down=\"removeToast(item.id, 'close')\"\n @pause=\"paused.add(item.id)\"\n @resume=\"paused.delete(item.id)\"\n @update:open=\"(open) => !open && removeToast(item.id, 'timeout')\"\n >\n <ToastMessage\n :actions=\"item.actions\"\n class=\"pointer-events-auto data-[state=closed]:overflow-hidden data-[state=closed]:animate-sui-toast-out motion-reduce:data-[state=closed]:animate-sui-toast-fade\"\n :class=\"\n fromTop\n ? 'data-[state=open]:animate-sui-toast-in-top motion-reduce:data-[state=open]:animate-sui-fade-in'\n : 'data-[state=open]:animate-sui-toast-in motion-reduce:data-[state=open]:animate-sui-fade-in'\n \"\n :closable=\"item.closable\"\n :close-label=\"closeLabel\"\n :detail=\"item.detail\"\n :life=\"item.life\"\n :paused=\"paused.has(item.id)\"\n :severity=\"item.severity\"\n :summary=\"item.summary\"\n @action=\"runLive(item.id, $event)\"\n @close=\"removeToast(item.id, 'close')\"\n />\n </ToastRoot>\n <!-- A div, not Reka's default ol: the toasts are divs, so a page can draw one alone. From the top, the newest is\n nearest the edge, as it is at the bottom. -->\n <ToastViewport\n as=\"div\"\n class=\"pointer-events-none fixed z-[1200] mx-auto flex rounded-md outline-hidden\"\n :class=\"fromTop ? 'flex-col-reverse' : 'flex-col'\"\n :data-sui-position=\"position\"\n data-sui-toasts\n :label=\"label\"\n :style=\"placement\"\n />\n </ToastProvider>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;EA2CA,IAAMe,IAAQC,GAORC,IAAOH,GAOPI,IAASC,kBAAS,IAAI,IAAY,CAAC,GAInCC,KAAQ,MAA2B,4DAA4DC,EAAK,KACpGC,IAAYC,QAAe;GAC/B,IAAM,CAACC,GAAUC,KAAcV,EAAM,SAAS,MAAM,GAAG;GACvD,OAAO;KACJS,IAAW,4DAA4DA,EAAS,0BAA0BA,EAAS;IACpH,MAAMC,MAAe,UAAU,SAASL,EAAK,MAAM;IACnD,OAAOK,MAAe,SAAS,SAASL,EAAK,OAAO;IACpD,OAAO,yCAAyCA,EAAK,MAAM,EAAE,KAAKA,EAAK,OAAO,EAAE;GAClF;EACF,CAAC,GACKM,IAAUH,QAAeR,EAAM,SAAS,WAAW,KAAK,CAAC;EAE/D,SAASY,EAAQ,GAAY,GAAqB;GAEhD,AADAC,EAAO,QAAQ,GACfC,EAAYC,GAAI,QAAQ;EAC1B;EAEA,SAASC,EAAW,GAAqB,GAAqB;GAE5D,AADAH,EAAO,QAAQ,GACfX,EAAK,SAASa,GAAI,QAAQ;EAC5B;E,iBAMUd,EAAA,WADRhB,EAAA,GAAAC,EAqBkBC,GAAA;;GAnBhB,OAAM;GACN,sBAAmB;GACnB,sBAAmB;GACnB,KAAI;;GAGF,SAAAC,QAAgC,EADlCH,EAAA,EAAA,GAAAI,EAaEC,GAAA,MAAAC,EAZwBU,EAAA,UAAhB,GAAM,OADhBhB,EAAA,GAAAC,EAaEM,GAAA;IAXC,KAAKgC,EAAK,MAAMC;IAChB,SAAShC,EAAAkC,CAAA,CAAY,CAACH,CAAI;IAC1B,UAAUA,EAAK;IACf,eAAavB,EAAA;IACb,QAAQuB,EAAK;IACb,MAAMA,EAAK;IACX,UAAUA,EAAK;IACf,SAASA,EAAK;IACd,WAAM,MAAER,EAAWQ,EAAK,MAAMC,GAAOG,CAAM;IAC3C,UAAK,MAAE1B,EAAI,SAAUsB,EAAK,MAAMC,GAAK,OAAA;IACrC,WAAM,MAAEvB,EAAI,SAAUsB,EAAK,MAAMC,GAAK,SAAA;;;;;;;;;;;;;;E,OAG3CxC,EAAA,GAAAC,EA2CgBO,EAAAoC,CAAA,GAAA;;GA3CO,mBAAiB;;GAEpC,SAAAzC,QAAsB,EADxBH,EAAA,EAAA,GAAAI,EA8BYC,GAAA,MAAAC,EA7BKE,EAAAqC,CAAA,IAAR,OADT7C,EAAA,GAAAC,EA8BYO,EAAAsC,CAAA,GAAA;IA5BT,KAAKP,EAAK;IACX,YAAA;IACC,UAAUA,EAAK,QAAQ;IACvB,MAAMA,EAAK;IACX,MAAMA,EAAK,aAAQ,UAAA,eAAA;IACnB,kBAAe,MAAE/B,EAAAqB,CAAA,CAAW,CAACU,EAAK,IAAE,OAAA;IACpC,UAAK,MAAErB,EAAO,IAAIqB,EAAK,EAAE;IACzB,WAAM,MAAErB,EAAO,OAAOqB,EAAK,EAAE;IAC7B,kBAAc,MAAI,CAAMQ,KAAQvC,EAAAqB,CAAA,CAAW,CAACU,EAAK,IAAE,SAAA;;IAEpD,SAAApC,QAiBE,CAjBFM,EAiBEF,GAAA;KAhBC,SAASgC,EAAK;KACf,OAAK7B,EAAA,CAAC,8JACagB,EAAA,Q;KAKlB,UAAUa,EAAK;KACf,eAAavB,EAAA;KACb,QAAQuB,EAAK;KACb,MAAMA,EAAK;KACX,QAAQrB,EAAO,IAAIqB,EAAK,EAAE;KAC1B,UAAUA,EAAK;KACf,SAASA,EAAK;KACd,WAAM,MAAEZ,EAAQY,EAAK,IAAII,CAAM;KAC/B,UAAK,MAAEnC,EAAAqB,CAAA,CAAW,CAACU,EAAK,IAAE,OAAA;;;;;;;;;;;;;;;;;;;;;;;G,aAK/B9B,EAQED,EAAA0C,CAAA,GAAA;IAPA,IAAG;IACH,OAAKxC,EAAA,CAAC,6EACEgB,EAAA,QAAO,qBAAA,UAAA,CAAA;IACd,qBAAmBV,EAAA;IACpB,mBAAA;IACC,OAAOA,EAAA;IACP,OAAKL,EAAEW,EAAA,KAAS"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toolbar.js","names":["_sfc_main","Toolbar_vue_vue_type_script_setup_true_lang_default","Toolbar_default"],"sources":["../../../src/components/Toolbar/Toolbar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onMounted, onUpdated, ref, useTemplateRef } from 'vue'\n\nexport interface ToolbarProps {\n /** Its accessible name, e.g. \"Text formatting\". */\n label: string\n orientation?: 'horizontal' | 'vertical'\n /** The arrow keys wrap from the last control to the first. */\n loop?: boolean\n}\n\nconst props = withDefaults(defineProps<ToolbarProps>(), { orientation: 'horizontal', loop: true })\n\nconst root = useTemplateRef<HTMLElement>('root')\n// The control Tab lands on: the last one focused, else the first.\nconst current = ref<HTMLElement | null>(null)\n\nconst controls = () => [...(root.value?.querySelectorAll<HTMLElement>('button, a[href], input, [role=\"button\"]') ?? [])]\nconst items = () => controls().filter((el) => !el.matches(':disabled, [aria-disabled=\"true\"]'))\n\n// The controls are the app's: the toolbar only sets their tabindex, so one of them is in the Tab order.\nfunction rove() {\n const all = items()\n const active = current.value && all.includes(current.value) ? current.value : all[0]\n for (const el of controls()) el.tabIndex = el === active ? 0 : -1\n}\n\nonMounted(rove)\nonUpdated(rove)\n\nfunction onFocusin(event: FocusEvent) {\n const target = items().find((el) => el === event.target)\n if (!target) return\n current.value = target\n rove()\n}\n\nfunction onKeydown(event: KeyboardEvent) {\n const [back, next] = props.orientation === 'vertical' ? ['ArrowUp', 'ArrowDown'] : ['ArrowLeft', 'ArrowRight']\n if (![back, next, 'Home', 'End'].includes(event.key) || event.altKey || event.metaKey || event.ctrlKey) return\n // A field inside keeps its arrow keys.\n if ((event.target as HTMLElement).matches('input, textarea')) return\n const all = items()\n const i = all.indexOf(event.target as HTMLElement)\n if (i < 0) return\n const last = all.length - 1\n let to = event.key === 'Home' ? 0 : event.key === 'End' ? last : i + (event.key === next ? 1 : -1)\n if (to < 0) to = props.loop ? last : 0\n if (to > last) to = props.loop ? 0 : last\n event.preventDefault()\n all[to]?.focus()\n}\n</script>\n\n<!-- A row of controls, such as format toggles, that Tab enters once and the arrow keys move through. -->\n<template>\n <div\n ref=\"root\"\n :aria-label=\"label\"\n :aria-orientation=\"orientation\"\n class=\"flex gap-0.5\"\n :class=\"orientation === 'vertical' ? 'flex-col items-stretch' : 'items-center'\"\n role=\"toolbar\"\n @focusin=\"onFocusin\"\n @keydown=\"onKeydown\"\n >\n <slot />\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface ToolbarProps {
|
|
2
|
+
/** Its accessible name, e.g. "Text formatting". */
|
|
3
|
+
label: string;
|
|
4
|
+
orientation?: 'horizontal' | 'vertical';
|
|
5
|
+
/** The arrow keys wrap from the last control to the first. */
|
|
6
|
+
loop?: boolean;
|
|
7
|
+
}
|
|
8
|
+
declare var __VLS_1: {};
|
|
9
|
+
type __VLS_Slots = {} & {
|
|
10
|
+
default?: (props: typeof __VLS_1) => any;
|
|
11
|
+
};
|
|
12
|
+
declare const __VLS_base: import("vue").DefineComponent<ToolbarProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<ToolbarProps> & Readonly<{}>, {
|
|
13
|
+
loop: boolean;
|
|
14
|
+
orientation: "vertical" | "horizontal";
|
|
15
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
16
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
17
|
+
declare const _default: typeof __VLS_export;
|
|
18
|
+
export default _default;
|
|
19
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
20
|
+
new (): {
|
|
21
|
+
$slots: S;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { createElementBlock as e, defineComponent as t, normalizeClass as n, onMounted as r, onUpdated as i, openBlock as a, ref as o, renderSlot as s, useTemplateRef as c } from "vue";
|
|
2
|
+
//#region src/components/Toolbar/Toolbar.vue?vue&type=script&setup=true&lang.ts
|
|
3
|
+
var l = ["aria-label", "aria-orientation"], u = /*@__PURE__*/ t({
|
|
4
|
+
__name: "Toolbar",
|
|
5
|
+
props: {
|
|
6
|
+
label: {},
|
|
7
|
+
orientation: { default: "horizontal" },
|
|
8
|
+
loop: {
|
|
9
|
+
type: Boolean,
|
|
10
|
+
default: !0
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
setup(t) {
|
|
14
|
+
let u = t, d = c("root"), f = o(null), p = () => [...d.value?.querySelectorAll("button, a[href], input, [role=\"button\"]") ?? []], m = () => p().filter((e) => !e.matches(":disabled, [aria-disabled=\"true\"]"));
|
|
15
|
+
function h() {
|
|
16
|
+
let e = m(), t = f.value && e.includes(f.value) ? f.value : e[0];
|
|
17
|
+
for (let e of p()) e.tabIndex = e === t ? 0 : -1;
|
|
18
|
+
}
|
|
19
|
+
r(h), i(h);
|
|
20
|
+
function g(e) {
|
|
21
|
+
let t = m().find((t) => t === e.target);
|
|
22
|
+
t && (f.value = t, h());
|
|
23
|
+
}
|
|
24
|
+
function _(e) {
|
|
25
|
+
let [t, n] = u.orientation === "vertical" ? ["ArrowUp", "ArrowDown"] : ["ArrowLeft", "ArrowRight"];
|
|
26
|
+
if (![
|
|
27
|
+
t,
|
|
28
|
+
n,
|
|
29
|
+
"Home",
|
|
30
|
+
"End"
|
|
31
|
+
].includes(e.key) || e.altKey || e.metaKey || e.ctrlKey || e.target.matches("input, textarea")) return;
|
|
32
|
+
let r = m(), i = r.indexOf(e.target);
|
|
33
|
+
if (i < 0) return;
|
|
34
|
+
let a = r.length - 1, o = e.key === "Home" ? 0 : e.key === "End" ? a : i + (e.key === n ? 1 : -1);
|
|
35
|
+
o < 0 && (o = u.loop ? a : 0), o > a && (o = u.loop ? 0 : a), e.preventDefault(), r[o]?.focus();
|
|
36
|
+
}
|
|
37
|
+
return (r, i) => (a(), e("div", {
|
|
38
|
+
ref_key: "root",
|
|
39
|
+
ref: d,
|
|
40
|
+
"aria-label": t.label,
|
|
41
|
+
"aria-orientation": t.orientation,
|
|
42
|
+
class: n(["flex gap-0.5", t.orientation === "vertical" ? "flex-col items-stretch" : "items-center"]),
|
|
43
|
+
role: "toolbar",
|
|
44
|
+
onFocusin: g,
|
|
45
|
+
onKeydown: _
|
|
46
|
+
}, [s(r.$slots, "default")], 42, l));
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
//#endregion
|
|
50
|
+
export { u as default };
|
|
51
|
+
|
|
52
|
+
//# sourceMappingURL=Toolbar.vue_vue_type_script_setup_true_lang.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toolbar.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_normalizeClass","_renderSlot","_hoisted_1","Toolbar_vue_vue_type_script_setup_true_lang_default","props","__props","root","useTemplateRef","current","ref","controls","items","el","rove","all","active","onMounted","onUpdated","onFocusin","target","event","onKeydown","back","next","last","to","openBlock","createElementBlock","normalizeClass","renderSlot","_ctx"],"sources":["../../../src/components/Toolbar/Toolbar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onMounted, onUpdated, ref, useTemplateRef } from 'vue'\n\nexport interface ToolbarProps {\n /** Its accessible name, e.g. \"Text formatting\". */\n label: string\n orientation?: 'horizontal' | 'vertical'\n /** The arrow keys wrap from the last control to the first. */\n loop?: boolean\n}\n\nconst props = withDefaults(defineProps<ToolbarProps>(), { orientation: 'horizontal', loop: true })\n\nconst root = useTemplateRef<HTMLElement>('root')\n// The control Tab lands on: the last one focused, else the first.\nconst current = ref<HTMLElement | null>(null)\n\nconst controls = () => [...(root.value?.querySelectorAll<HTMLElement>('button, a[href], input, [role=\"button\"]') ?? [])]\nconst items = () => controls().filter((el) => !el.matches(':disabled, [aria-disabled=\"true\"]'))\n\n// The controls are the app's: the toolbar only sets their tabindex, so one of them is in the Tab order.\nfunction rove() {\n const all = items()\n const active = current.value && all.includes(current.value) ? current.value : all[0]\n for (const el of controls()) el.tabIndex = el === active ? 0 : -1\n}\n\nonMounted(rove)\nonUpdated(rove)\n\nfunction onFocusin(event: FocusEvent) {\n const target = items().find((el) => el === event.target)\n if (!target) return\n current.value = target\n rove()\n}\n\nfunction onKeydown(event: KeyboardEvent) {\n const [back, next] = props.orientation === 'vertical' ? ['ArrowUp', 'ArrowDown'] : ['ArrowLeft', 'ArrowRight']\n if (![back, next, 'Home', 'End'].includes(event.key) || event.altKey || event.metaKey || event.ctrlKey) return\n // A field inside keeps its arrow keys.\n if ((event.target as HTMLElement).matches('input, textarea')) return\n const all = items()\n const i = all.indexOf(event.target as HTMLElement)\n if (i < 0) return\n const last = all.length - 1\n let to = event.key === 'Home' ? 0 : event.key === 'End' ? last : i + (event.key === next ? 1 : -1)\n if (to < 0) to = props.loop ? last : 0\n if (to > last) to = props.loop ? 0 : last\n event.preventDefault()\n all[to]?.focus()\n}\n</script>\n\n<!-- A row of controls, such as format toggles, that Tab enters once and the arrow keys move through. -->\n<template>\n <div\n ref=\"root\"\n :aria-label=\"label\"\n :aria-orientation=\"orientation\"\n class=\"flex gap-0.5\"\n :class=\"orientation === 'vertical' ? 'flex-col items-stretch' : 'items-center'\"\n role=\"toolbar\"\n @focusin=\"onFocusin\"\n @keydown=\"onKeydown\"\n >\n <slot />\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;EAWA,IAAMM,IAAQC,GAERC,IAAOC,EAA4B,MAAM,GAEzCC,IAAUC,EAAwB,IAAI,GAEtCC,UAAiB,CAAC,GAAIJ,EAAK,OAAO,iBAA8B,2CAAyC,KAAK,CAAC,CAAE,GACjHK,UAAcD,EAAS,CAAC,CAAC,QAAQ,MAAO,CAACE,EAAG,QAAQ,qCAAmC,CAAC;EAG9F,SAASC,IAAO;GACd,IAAMC,IAAMH,EAAM,GACZI,IAASP,EAAQ,SAASM,EAAI,SAASN,EAAQ,KAAK,IAAIA,EAAQ,QAAQM,EAAI;GAClF,KAAK,IAAMF,KAAMF,EAAS,GAAG,EAAG,WAAWE,MAAOG,IAAS,IAAI;EACjE;EAGA,AADAC,EAAUH,CAAI,GACdI,EAAUJ,CAAI;EAEd,SAASK,EAAU,GAAmB;GACpC,IAAMC,IAASR,EAAM,CAAC,CAAC,MAAM,MAAOC,MAAOQ,EAAM,MAAM;GACvD,AAAKD,MACL,EAAQ,QAAQA,GAChBN,EAAK;EACP;EAEA,SAASQ,EAAU,GAAsB;GACvC,IAAM,CAACC,GAAMC,KAAQnB,EAAM,gBAAgB,aAAa,CAAC,WAAW,WAAW,IAAI,CAAC,aAAa,YAAY;GAG7G,IAFI,CAAC;IAACkB;IAAMC;IAAM;IAAQ;GAAK,CAAC,CAAC,SAASH,EAAM,GAAG,KAAKA,EAAM,UAAUA,EAAM,WAAWA,EAAM,WAE1FA,EAAM,OAAuB,QAAQ,iBAAiB,GAAG;GAC9D,IAAMN,IAAMH,EAAM,GACZ,IAAIG,EAAI,QAAQM,EAAM,MAAqB;GACjD,IAAI,IAAI,GAAG;GACX,IAAMI,IAAOV,EAAI,SAAS,GACtBW,IAAKL,EAAM,QAAQ,SAAS,IAAIA,EAAM,QAAQ,QAAQI,IAAO,KAAKJ,EAAM,QAAQG,IAAO,IAAI;GAI/F,AAHIE,IAAK,MAAG,IAAKrB,EAAM,OAAOoB,IAAO,IACjCC,IAAKD,MAAM,IAAKpB,EAAM,OAAO,IAAIoB,IACrCJ,EAAM,eAAe,GACrBN,EAAIW,EAAG,EAAE,MAAM;EACjB;E,kBAKE3B,EAAA,GAAAC,EAWM,OAAA;GAVA,SAAA;GAAJ,KAAIO;GACH,cAAYD,EAAA;GACZ,oBAAkBA,EAAA;GACnB,OAAKL,EAAA,CAAC,gBACEK,EAAA,gBAAW,aAAA,2BAAA,cAAA,CAAA;GACnB,MAAK;GACK;GACA;E,IAEVJ,EAAQ6B,EAAA,QAAA,SAAA,C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MenuItemContent.js","names":["_sfc_main","MenuItemContent_vue_vue_type_script_setup_true_lang_default","MenuItemContent_default"],"sources":["../../../src/components/internal/MenuItemContent.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport Icon from '../Icon/Icon.vue'\nimport type { DropdownMenuAction } from './menu'\n\ndefineProps<{ item: DropdownMenuAction }>()\n</script>\n\n<!-- One menu item as drawn: an icon, the label and a shortcut. -->\n<template>\n <div\n class=\"flex
|
|
1
|
+
{"version":3,"file":"MenuItemContent.js","names":["_sfc_main","MenuItemContent_vue_vue_type_script_setup_true_lang_default","MenuItemContent_default"],"sources":["../../../src/components/internal/MenuItemContent.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport Icon from '../Icon/Icon.vue'\nimport type { DropdownMenuAction } from './menu'\n\n// Reka's item attributes come first, so a disabled item's own win over its `aria-disabled`.\ndefineOptions({ inheritAttrs: false })\n\ndefineProps<{ item: DropdownMenuAction; reasonId?: string }>()\n</script>\n\n<!-- One menu item as drawn: an icon, the label and a shortcut; disabled, dimmed, with its reason underneath. It's the\n menu item itself (its Reka item renders as-child). A disabled item isn't Reka's `disabled`, which arrow keys skip:\n the WAI-ARIA menu pattern keeps it reachable, and the menu's `select` ignores it. -->\n<template>\n <div\n v-bind=\"$attrs\"\n :aria-describedby=\"item.disabled && item.disabledReason ? reasonId : undefined\"\n :aria-disabled=\"item.disabled ? 'true' : undefined\"\n class=\"flex items-center gap-2.5 px-2.5 py-1.5\"\n :class=\"[\n item.variant === 'danger' ? 'text-sui-danger' : 'text-sui-ink',\n item.disabled ? 'cursor-default' : 'cursor-pointer'\n ]\"\n >\n <Icon\n v-if=\"item.icon\"\n class=\"h-4 w-4 shrink-0\"\n :class=\"item.disabled && 'opacity-50'\"\n :color=\"item.variant === 'danger' ? 'danger' : 'ink-muted'\"\n :name=\"item.icon\"\n />\n <span class=\"flex min-w-0 flex-1 flex-col\">\n <span class=\"text-13\" :class=\"item.disabled && 'opacity-50'\">{{ item.label }}</span>\n <span v-if=\"item.disabled && item.disabledReason\" :id=\"reasonId\" class=\"text-xs text-sui-ink-muted\">{{\n item.disabledReason\n }}</span>\n </span>\n <span v-if=\"item.shortcut\" class=\"text-11 text-sui-ink-muted\" :class=\"item.disabled && 'opacity-50'\">{{\n item.shortcut\n }}</span>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { DropdownMenuAction } from './menu';
|
|
2
2
|
type __VLS_Props = {
|
|
3
3
|
item: DropdownMenuAction;
|
|
4
|
+
reasonId?: string;
|
|
4
5
|
};
|
|
5
6
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
6
7
|
declare const _default: typeof __VLS_export;
|
|
@@ -1,26 +1,42 @@
|
|
|
1
1
|
import e from "../Icon/Icon.js";
|
|
2
|
-
import { createBlock as t, createCommentVNode as n, createElementBlock as r, createElementVNode as i, defineComponent as a,
|
|
2
|
+
import { createBlock as t, createCommentVNode as n, createElementBlock as r, createElementVNode as i, defineComponent as a, mergeProps as o, normalizeClass as s, openBlock as c, toDisplayString as l } from "vue";
|
|
3
3
|
//#region src/components/internal/MenuItemContent.vue?vue&type=script&setup=true&lang.ts
|
|
4
|
-
var
|
|
5
|
-
|
|
6
|
-
class: "text-11 text-sui-ink-muted"
|
|
7
|
-
}, d = /*@__PURE__*/ a({
|
|
4
|
+
var u = ["aria-describedby", "aria-disabled"], d = { class: "flex min-w-0 flex-1 flex-col" }, f = ["id"], p = /*@__PURE__*/ a({
|
|
5
|
+
inheritAttrs: !1,
|
|
8
6
|
__name: "MenuItemContent",
|
|
9
|
-
props: {
|
|
7
|
+
props: {
|
|
8
|
+
item: {},
|
|
9
|
+
reasonId: {}
|
|
10
|
+
},
|
|
10
11
|
setup(a) {
|
|
11
|
-
return (
|
|
12
|
-
a.item.
|
|
12
|
+
return (p, m) => (c(), r("div", o(p.$attrs, {
|
|
13
|
+
"aria-describedby": a.item.disabled && a.item.disabledReason ? a.reasonId : void 0,
|
|
14
|
+
"aria-disabled": a.item.disabled ? "true" : void 0,
|
|
15
|
+
class: ["flex items-center gap-2.5 px-2.5 py-1.5", [a.item.variant === "danger" ? "text-sui-danger" : "text-sui-ink", a.item.disabled ? "cursor-default" : "cursor-pointer"]]
|
|
16
|
+
}), [
|
|
17
|
+
a.item.icon ? (c(), t(e, {
|
|
13
18
|
key: 0,
|
|
14
|
-
class: "h-4 w-4 shrink-0",
|
|
19
|
+
class: s(["h-4 w-4 shrink-0", a.item.disabled && "opacity-50"]),
|
|
15
20
|
color: a.item.variant === "danger" ? "danger" : "ink-muted",
|
|
16
21
|
name: a.item.icon
|
|
17
|
-
}, null, 8, [
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
}, null, 8, [
|
|
23
|
+
"class",
|
|
24
|
+
"color",
|
|
25
|
+
"name"
|
|
26
|
+
])) : n("", !0),
|
|
27
|
+
i("span", d, [i("span", { class: s(["text-13", a.item.disabled && "opacity-50"]) }, l(a.item.label), 3), a.item.disabled && a.item.disabledReason ? (c(), r("span", {
|
|
28
|
+
key: 0,
|
|
29
|
+
id: a.reasonId,
|
|
30
|
+
class: "text-xs text-sui-ink-muted"
|
|
31
|
+
}, l(a.item.disabledReason), 9, f)) : n("", !0)]),
|
|
32
|
+
a.item.shortcut ? (c(), r("span", {
|
|
33
|
+
key: 1,
|
|
34
|
+
class: s(["text-11 text-sui-ink-muted", a.item.disabled && "opacity-50"])
|
|
35
|
+
}, l(a.item.shortcut), 3)) : n("", !0)
|
|
36
|
+
], 16, u));
|
|
21
37
|
}
|
|
22
38
|
});
|
|
23
39
|
//#endregion
|
|
24
|
-
export {
|
|
40
|
+
export { p as default };
|
|
25
41
|
|
|
26
42
|
//# sourceMappingURL=MenuItemContent.vue_vue_type_script_setup_true_lang.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MenuItemContent.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","
|
|
1
|
+
{"version":3,"file":"MenuItemContent.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_openBlock","_createElementBlock","_mergeProps","_createBlock","Icon","_normalizeClass","_createCommentVNode","_createElementVNode","_toDisplayString","Icon_default","_hoisted_1","_hoisted_2","_hoisted_3","MenuItemContent_vue_vue_type_script_setup_true_lang_default","openBlock","createElementBlock","mergeProps","_ctx","__props","createBlock","normalizeClass","createCommentVNode","createElementVNode","toDisplayString"],"sources":["../../../src/components/internal/MenuItemContent.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport Icon from '../Icon/Icon.vue'\nimport type { DropdownMenuAction } from './menu'\n\n// Reka's item attributes come first, so a disabled item's own win over its `aria-disabled`.\ndefineOptions({ inheritAttrs: false })\n\ndefineProps<{ item: DropdownMenuAction; reasonId?: string }>()\n</script>\n\n<!-- One menu item as drawn: an icon, the label and a shortcut; disabled, dimmed, with its reason underneath. It's the\n menu item itself (its Reka item renders as-child). A disabled item isn't Reka's `disabled`, which arrow keys skip:\n the WAI-ARIA menu pattern keeps it reachable, and the menu's `select` ignores it. -->\n<template>\n <div\n v-bind=\"$attrs\"\n :aria-describedby=\"item.disabled && item.disabledReason ? reasonId : undefined\"\n :aria-disabled=\"item.disabled ? 'true' : undefined\"\n class=\"flex items-center gap-2.5 px-2.5 py-1.5\"\n :class=\"[\n item.variant === 'danger' ? 'text-sui-danger' : 'text-sui-ink',\n item.disabled ? 'cursor-default' : 'cursor-pointer'\n ]\"\n >\n <Icon\n v-if=\"item.icon\"\n class=\"h-4 w-4 shrink-0\"\n :class=\"item.disabled && 'opacity-50'\"\n :color=\"item.variant === 'danger' ? 'danger' : 'ink-muted'\"\n :name=\"item.icon\"\n />\n <span class=\"flex min-w-0 flex-1 flex-col\">\n <span class=\"text-13\" :class=\"item.disabled && 'opacity-50'\">{{ item.label }}</span>\n <span v-if=\"item.disabled && item.disabledReason\" :id=\"reasonId\" class=\"text-xs text-sui-ink-muted\">{{\n item.disabledReason\n }}</span>\n </span>\n <span v-if=\"item.shortcut\" class=\"text-11 text-sui-ink-muted\" :class=\"item.disabled && 'opacity-50'\">{{\n item.shortcut\n }}</span>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;E,kBAcEC,EAAA,GAAAC,EA0BM,OA1BNC,EACUH,EAyBJ,QAzBU;GACb,oBAAkBmB,EAAA,KAAK,YAAYA,EAAA,KAAK,iBAAiBA,EAAA,WAAW,KAAA;GACpE,iBAAeA,EAAA,KAAK,WAAQ,SAAY,KAAA;GACzC,OAAK,CAAC,2CAAyC,CAC/BA,EAAA,KAAK,YAAO,WAAA,oBAAA,gBAA0DA,EAAA,KAAK,WAAQ,mBAAA,gB;;GAM3FA,EAAA,KAAK,QADblB,EAAA,GAAAG,EAMEC,GAAA;;IAJA,OAAKC,EAAA,CAAC,oBACEa,EAAA,KAAK,YAAQ,YAAA,CAAA;IACpB,OAAOA,EAAA,KAAK,YAAO,WAAA,WAAA;IACnB,MAAMA,EAAA,KAAK;;;;;;GAEdX,EAKO,QALPI,GAKO,CAJLJ,EAAoF,QAAA,EAA9E,OAAKF,EAAA,CAAC,WAAkBa,EAAA,KAAK,YAAQ,YAAA,CAAA,EAAqB,GAAAV,EAAAU,EAAA,KAAK,KAAK,GAAA,CAAA,GAC9DA,EAAA,KAAK,YAAYA,EAAA,KAAK,kBAAlClB,EAAA,GAAAC,EAES,QAAA;;IAF0C,IAAIiB,EAAA;IAAU,OAAM;GACrE,GAAAV,EAAAU,EAAA,KAAK,cAAc,GAAA,GAAAN,CAAA,K;GAGXM,EAAA,KAAK,YAAjBlB,EAAA,GAAAC,EAES,QAAA;;IAFkB,OAAKI,EAAA,CAAC,8BAAqCa,EAAA,KAAK,YAAQ,YAAA,CAAA;GACjF,GAAAV,EAAAU,EAAA,KAAK,QAAQ,GAAA,CAAA,K"}
|
|
@@ -12,6 +12,10 @@ export interface DropdownMenuAction {
|
|
|
12
12
|
acceptLabel?: string;
|
|
13
13
|
};
|
|
14
14
|
confirmed?: boolean;
|
|
15
|
+
/** Dimmed and inert, but still reached with the arrow keys and announced as unavailable. */
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
/** Why it's disabled, shown under its label. */
|
|
18
|
+
disabledReason?: string;
|
|
15
19
|
[key: string]: unknown;
|
|
16
20
|
}
|
|
17
21
|
export type DropdownMenuEntry = DropdownMenuAction | {
|
|
@@ -43,4 +47,4 @@ export declare function useMenuSelect(props: Required<Omit<MenuConfirmLabels, 'i
|
|
|
43
47
|
id?: string;
|
|
44
48
|
}, emit: (item: DropdownMenuAction & {
|
|
45
49
|
id?: string;
|
|
46
|
-
}) => void): (item: DropdownMenuAction) => Promise<void>;
|
|
50
|
+
}) => void): (item: DropdownMenuAction, event?: Event) => Promise<void>;
|
|
@@ -10,21 +10,24 @@ var t = {
|
|
|
10
10
|
}, n = "z-[1100] rounded-xl border border-sui-line-subtle bg-sui-surface p-1 shadow-lg outline-hidden data-[state=open]:animate-sui-menu-in", r = "relative rounded-lg text-sm text-sui-ink transition-colors duration-150 outline-hidden hover:bg-sui-sunken focus-visible:sui-ring-inset data-highlighted:bg-sui-sunken", i = "my-1 border-t border-sui-line-subtle";
|
|
11
11
|
function a(t, n) {
|
|
12
12
|
let r = e();
|
|
13
|
-
return async function(e) {
|
|
14
|
-
if (e.
|
|
15
|
-
|
|
16
|
-
if (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
return async function(e, i) {
|
|
14
|
+
if (e.disabled) i?.preventDefault();
|
|
15
|
+
else {
|
|
16
|
+
if (e.confirm || e.confirmed) {
|
|
17
|
+
let n = e.variant === "danger" || e.action === "delete";
|
|
18
|
+
if (!await r({
|
|
19
|
+
title: e.confirm?.title ?? t.confirmTitle,
|
|
20
|
+
message: e.confirm?.message ?? t.confirmMessage,
|
|
21
|
+
cancelLabel: t.cancelLabel,
|
|
22
|
+
confirmLabel: e.confirm?.acceptLabel ?? (e.action === "delete" ? t.deleteLabel : t.confirmLabel),
|
|
23
|
+
confirmVariant: n ? "danger" : "primary"
|
|
24
|
+
})) return;
|
|
25
|
+
}
|
|
26
|
+
n({
|
|
27
|
+
id: t.id,
|
|
28
|
+
...e
|
|
29
|
+
});
|
|
23
30
|
}
|
|
24
|
-
n({
|
|
25
|
-
id: t.id,
|
|
26
|
-
...e
|
|
27
|
-
});
|
|
28
31
|
};
|
|
29
32
|
}
|
|
30
33
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menu.js","names":["menuConfirmDefaults","menuContentClass","menuItemClass","menuSeparatorClass","useMenuSelect","confirm","useConfirm","item","destructive","props"],"sources":["../../../src/components/internal/menu.ts"],"sourcesContent":["import { useConfirm } from '../../composables/useConfirm'\n\nexport interface DropdownMenuAction {\n type: 'action'\n label: string\n action?: string\n icon?: string\n variant?: 'danger'\n shortcut?: string\n /** Asks first, with this wording; `confirmed: true` asks with the generic wording. */\n confirm?: { message: string; title?: string; acceptLabel?: string }\n confirmed?: boolean\n [key: string]: unknown\n}\n\nexport type DropdownMenuEntry = DropdownMenuAction | { type: 'separator' }\n\n/** The confirm step's wording, shared by DropdownMenu and ContextMenu. */\nexport interface MenuConfirmLabels {\n /** Passed back with every clicked item, e.g. the record the menu acts on. */\n id?: string\n confirmTitle?: string\n confirmMessage?: string\n confirmLabel?: string\n deleteLabel?: string\n cancelLabel?: string\n}\n\nexport const menuConfirmDefaults = {\n id: undefined,\n confirmTitle: 'Are you sure?',\n confirmMessage: \"This can't be undone.\",\n confirmLabel: 'Confirm',\n deleteLabel: 'Delete',\n cancelLabel: 'Cancel'\n}\n\nexport const menuContentClass =\n 'z-[1100] rounded-xl border border-sui-line-subtle bg-sui-surface p-1 shadow-lg outline-hidden data-[state=open]:animate-sui-menu-in'\nexport const menuItemClass =\n 'relative rounded-lg text-sm text-sui-ink transition-colors duration-150 outline-hidden hover:bg-sui-sunken focus-visible:sui-ring-inset data-highlighted:bg-sui-sunken'\nexport const menuSeparatorClass = 'my-1 border-t border-sui-line-subtle'\n\n/** Runs an item: asks first when it says so, then emits it with the menu's `id`. */\nexport function useMenuSelect(\n props: Required<Omit<MenuConfirmLabels, 'id'>> & { id?: string },\n emit: (item: DropdownMenuAction & { id?: string }) => void\n) {\n const confirm = useConfirm()\n\n return async function select(item: DropdownMenuAction) {\n if (item.confirm || item.confirmed) {\n const destructive = item.variant === 'danger' || item.action === 'delete'\n const confirmed = await confirm({\n title: item.confirm?.title ?? props.confirmTitle,\n message: item.confirm?.message ?? props.confirmMessage,\n cancelLabel: props.cancelLabel,\n confirmLabel: item.confirm?.acceptLabel ?? (item.action === 'delete' ? props.deleteLabel : props.confirmLabel),\n confirmVariant: destructive ? 'danger' : 'primary'\n })\n if (!confirmed) return\n }\n emit({ id: props.id, ...item })\n }\n}\n"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"menu.js","names":["menuConfirmDefaults","menuContentClass","menuItemClass","menuSeparatorClass","useMenuSelect","confirm","useConfirm","item","destructive","props"],"sources":["../../../src/components/internal/menu.ts"],"sourcesContent":["import { useConfirm } from '../../composables/useConfirm'\n\nexport interface DropdownMenuAction {\n type: 'action'\n label: string\n action?: string\n icon?: string\n variant?: 'danger'\n shortcut?: string\n /** Asks first, with this wording; `confirmed: true` asks with the generic wording. */\n confirm?: { message: string; title?: string; acceptLabel?: string }\n confirmed?: boolean\n /** Dimmed and inert, but still reached with the arrow keys and announced as unavailable. */\n disabled?: boolean\n /** Why it's disabled, shown under its label. */\n disabledReason?: string\n [key: string]: unknown\n}\n\nexport type DropdownMenuEntry = DropdownMenuAction | { type: 'separator' }\n\n/** The confirm step's wording, shared by DropdownMenu and ContextMenu. */\nexport interface MenuConfirmLabels {\n /** Passed back with every clicked item, e.g. the record the menu acts on. */\n id?: string\n confirmTitle?: string\n confirmMessage?: string\n confirmLabel?: string\n deleteLabel?: string\n cancelLabel?: string\n}\n\nexport const menuConfirmDefaults = {\n id: undefined,\n confirmTitle: 'Are you sure?',\n confirmMessage: \"This can't be undone.\",\n confirmLabel: 'Confirm',\n deleteLabel: 'Delete',\n cancelLabel: 'Cancel'\n}\n\nexport const menuContentClass =\n 'z-[1100] rounded-xl border border-sui-line-subtle bg-sui-surface p-1 shadow-lg outline-hidden data-[state=open]:animate-sui-menu-in'\nexport const menuItemClass =\n 'relative rounded-lg text-sm text-sui-ink transition-colors duration-150 outline-hidden hover:bg-sui-sunken focus-visible:sui-ring-inset data-highlighted:bg-sui-sunken'\nexport const menuSeparatorClass = 'my-1 border-t border-sui-line-subtle'\n\n/** Runs an item: asks first when it says so, then emits it with the menu's `id`. */\nexport function useMenuSelect(\n props: Required<Omit<MenuConfirmLabels, 'id'>> & { id?: string },\n emit: (item: DropdownMenuAction & { id?: string }) => void\n) {\n const confirm = useConfirm()\n\n return async function select(item: DropdownMenuAction, event?: Event) {\n if (item.disabled) {\n // Keeps the menu open.\n event?.preventDefault()\n return\n }\n if (item.confirm || item.confirmed) {\n const destructive = item.variant === 'danger' || item.action === 'delete'\n const confirmed = await confirm({\n title: item.confirm?.title ?? props.confirmTitle,\n message: item.confirm?.message ?? props.confirmMessage,\n cancelLabel: props.cancelLabel,\n confirmLabel: item.confirm?.acceptLabel ?? (item.action === 'delete' ? props.deleteLabel : props.confirmLabel),\n confirmVariant: destructive ? 'danger' : 'primary'\n })\n if (!confirmed) return\n }\n emit({ id: props.id, ...item })\n }\n}\n"],"mappings":";;AAgCA,IAAaA,IAAsB;CACjC,IAAI,KAAA;CACJ,cAAc;CACd,gBAAgB;CAChB,cAAc;CACd,aAAa;CACb,aAAa;AACf,GAEaC,IACX,uIACWC,IACX,0KACWC,IAAqB;AAGlC,SAAgBC,EACd,GACA,GACA;CACA,IAAMC,IAAUC,EAAW;CAE3B,OAAO,eAAsB,GAA0B,GAAe;EACpE,IAAIC,EAAK,UAEP,GAAO,eAAe;OAGxB;OAAIA,EAAK,WAAWA,EAAK,WAAW;IAClC,IAAMC,IAAcD,EAAK,YAAY,YAAYA,EAAK,WAAW;IAQjE,IAAI,CAAC,MAPmBF,EAAQ;KAC9B,OAAOE,EAAK,SAAS,SAASE,EAAM;KACpC,SAASF,EAAK,SAAS,WAAWE,EAAM;KACxC,aAAaA,EAAM;KACnB,cAAcF,EAAK,SAAS,gBAAgBA,EAAK,WAAW,WAAWE,EAAM,cAAcA,EAAM;KACjG,gBAAgBD,IAAc,WAAW;IAC3C,CAAC,GACe;GAClB;GACA,EAAK;IAAE,IAAIC,EAAM;IAAI,GAAGF;GAAK,CAAC;EAD9B;CAEF;AACF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -32,6 +32,7 @@ export * from './components/Table';
|
|
|
32
32
|
export * from './components/Tag';
|
|
33
33
|
export * from './components/Textarea';
|
|
34
34
|
export * from './components/Toast';
|
|
35
|
+
export * from './components/Toolbar';
|
|
35
36
|
export * from './components/Tooltip';
|
|
36
37
|
export * from './components/TypingIndicator';
|
|
37
38
|
export { hueFor, type Hue } from './utils/hues';
|