@sparklingopinions/sparkling-ui 0.14.0 → 0.15.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_vue_type_script_setup_true_lang.js +5 -5
- 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 +74 -12
package/README.md
CHANGED
|
@@ -67,7 +67,7 @@ The package is published to npm as `@sparklingopinions/sparkling-ui`. Apps insta
|
|
|
67
67
|
import { Button } from 'sparkling-ui'
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
5. `Icon` draws the library's set of
|
|
70
|
+
5. `Icon` draws the library's set of 141 icons by name: `<Icon name="users" color="ink-muted" />`. Older names (`people`, `companies`, `dot-vertical`...) resolve as aliases, and `iconNames` lists the set. To add icons or replace some of the set, register a resolver once, before mounting; names it returns a component for win. With SVG files imported as components (e.g. `vite-svg-loader`):
|
|
71
71
|
|
|
72
72
|
```ts
|
|
73
73
|
import { type Component, defineAsyncComponent } from 'vue'
|
package/dist/aliases.d.ts
CHANGED
|
@@ -352,6 +352,8 @@ export declare const Modal: {
|
|
|
352
352
|
sheetBelow: number;
|
|
353
353
|
}, {}, string, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, import("vue").ComponentProvideOptions> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & (new () => {
|
|
354
354
|
$slots: {
|
|
355
|
+
context?: (props: {}) => any;
|
|
356
|
+
} & {
|
|
355
357
|
title?: (props: {}) => any;
|
|
356
358
|
} & {
|
|
357
359
|
default?: (props: {}) => any;
|
|
@@ -361,6 +363,8 @@ export declare const Modal: {
|
|
|
361
363
|
'footer-start'?: (props: {}) => any;
|
|
362
364
|
} & {
|
|
363
365
|
hero?: (props: {}) => any;
|
|
366
|
+
} & {
|
|
367
|
+
context?: (props: {}) => any;
|
|
364
368
|
} & {
|
|
365
369
|
title?: (props: {}) => any;
|
|
366
370
|
} & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionBar.js","names":["_sfc_main","ActionBar_vue_vue_type_script_setup_true_lang_default","ActionBar_default"],"sources":["../../../src/components/ActionBar/ActionBar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, watch } from 'vue'\n\nimport Button from '../Button/Button.vue'\nimport Icon from '../Icon/Icon.vue'\nimport Tooltip from '../Tooltip/Tooltip.vue'\nimport CloseIcon from '../internal/CloseIcon.vue'\n\nexport interface ActionBarAction {\n label: string\n /** Passed back with `click-item`, to tell the actions apart. */\n action?: string\n icon?: string\n variant?: 'danger'\n disabled?: boolean\n [key: string]: unknown\n}\n\nexport interface ActionBarProps {\n /** How many records are selected; it shows only while there are some. */\n count: number\n /** Two or three; put the rest in an DropdownMenu in the default slot. */\n actions?: ActionBarAction[]\n /** Adds a clear button, and Escape clears (`@clear`). */\n onClear?: () => void\n /** `{count}` is the number selected. */\n label?: string\n clearLabel?: string\n /** Fixed to the foot of the viewport. False draws it in place. */\n floating?: boolean\n}\n\nconst props = withDefaults(defineProps<ActionBarProps>(), {\n actions: () => [],\n onClear: undefined,\n label: '{count} selected',\n clearLabel: 'Clear selection',\n floating: true\n})\n\nconst emit = defineEmits<{ 'click-item': [action: ActionBarAction] }>()\n\ndefineSlots<{\n /** More controls after the actions, e.g. an DropdownMenu. */\n default?: () => unknown\n}>()\n\nconst text = computed(() => props.label.replace('{count}', String(props.count)))\n\n// Escape clears the selection, unless a dialog is open and takes it.\nfunction onKeydown(event: KeyboardEvent) {\n if (\n event.key !== 'Escape' ||\n event.defaultPrevented ||\n document.querySelector('[role=\"dialog\"], [role=\"alertdialog\"]')\n )\n return\n props.onClear?.()\n}\n\nwatch(\n () => props.count > 0 && !!props.onClear,\n (listening) => {\n if (listening) document.addEventListener('keydown', onKeydown)\n else document.removeEventListener('keydown', onKeydown)\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => document.removeEventListener('keydown', onKeydown))\n</script>\n\n<!-- Actions on the selected records: a floating pill with the count, the actions and a clear button. -->\n<template>\n <div\n v-if=\"count > 0\"\n :aria-label=\"text\"\n class=\"pointer-events-none flex justify-center\"\n :class=\"floating && 'fixed inset-x-0 bottom-4 z-[1150]'\"\n role=\"toolbar\"\n >\n <div\n class=\"pointer-events-auto flex animate-sui-toast-in items-center gap-2 rounded-
|
|
1
|
+
{"version":3,"file":"ActionBar.js","names":["_sfc_main","ActionBar_vue_vue_type_script_setup_true_lang_default","ActionBar_default"],"sources":["../../../src/components/ActionBar/ActionBar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, watch } from 'vue'\n\nimport Button from '../Button/Button.vue'\nimport Icon from '../Icon/Icon.vue'\nimport Tooltip from '../Tooltip/Tooltip.vue'\nimport CloseIcon from '../internal/CloseIcon.vue'\n\nexport interface ActionBarAction {\n label: string\n /** Passed back with `click-item`, to tell the actions apart. */\n action?: string\n icon?: string\n variant?: 'danger'\n disabled?: boolean\n [key: string]: unknown\n}\n\nexport interface ActionBarProps {\n /** How many records are selected; it shows only while there are some. */\n count: number\n /** Two or three; put the rest in an DropdownMenu in the default slot. */\n actions?: ActionBarAction[]\n /** Adds a clear button, and Escape clears (`@clear`). */\n onClear?: () => void\n /** `{count}` is the number selected. */\n label?: string\n clearLabel?: string\n /** Fixed to the foot of the viewport. False draws it in place. */\n floating?: boolean\n}\n\nconst props = withDefaults(defineProps<ActionBarProps>(), {\n actions: () => [],\n onClear: undefined,\n label: '{count} selected',\n clearLabel: 'Clear selection',\n floating: true\n})\n\nconst emit = defineEmits<{ 'click-item': [action: ActionBarAction] }>()\n\ndefineSlots<{\n /** More controls after the actions, e.g. an DropdownMenu. */\n default?: () => unknown\n}>()\n\nconst text = computed(() => props.label.replace('{count}', String(props.count)))\n\n// Escape clears the selection, unless a dialog is open and takes it.\nfunction onKeydown(event: KeyboardEvent) {\n if (\n event.key !== 'Escape' ||\n event.defaultPrevented ||\n document.querySelector('[role=\"dialog\"], [role=\"alertdialog\"]')\n )\n return\n props.onClear?.()\n}\n\nwatch(\n () => props.count > 0 && !!props.onClear,\n (listening) => {\n if (listening) document.addEventListener('keydown', onKeydown)\n else document.removeEventListener('keydown', onKeydown)\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => document.removeEventListener('keydown', onKeydown))\n</script>\n\n<!-- Actions on the selected records: a floating pill with the count, the actions and a clear button. -->\n<template>\n <div\n v-if=\"count > 0\"\n :aria-label=\"text\"\n class=\"pointer-events-none flex justify-center\"\n :class=\"floating && 'fixed inset-x-0 bottom-4 z-[1150]'\"\n role=\"toolbar\"\n >\n <div\n class=\"pointer-events-auto flex animate-sui-toast-in items-center gap-2 rounded-xl border border-sui-edge bg-sui-raised py-1.5 pr-2 pl-4 text-sm text-sui-ink shadow-(--sui-shadow-floating)\"\n >\n <span aria-live=\"polite\" class=\"whitespace-nowrap tabular-nums\">{{ text }}</span>\n <span aria-hidden=\"true\" class=\"mx-1 h-4 w-px bg-sui-line\" />\n <Button\n v-for=\"(item, i) in actions\"\n :key=\"item.action ?? i\"\n :disabled=\"item.disabled\"\n size=\"sm\"\n :variant=\"item.variant === 'danger' ? 'danger-outline' : 'secondary'\"\n @click=\"emit('click-item', item)\"\n >\n <Icon v-if=\"item.icon\" :name=\"item.icon\" />\n {{ item.label }}\n </Button>\n <slot />\n <Tooltip v-if=\"onClear\" :text=\"clearLabel\">\n <Button :aria-label=\"clearLabel\" icon-only size=\"xs\" variant=\"ghost\" @click=\"onClear()\">\n <CloseIcon class=\"fill-sui-ink-subtle stroke-sui-ink-subtle\" />\n </Button>\n </Tooltip>\n </div>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -4,7 +4,7 @@ import n from "../Tooltip/Tooltip.js";
|
|
|
4
4
|
import r from "../internal/CloseIcon.js";
|
|
5
5
|
import { Fragment as i, computed as a, createBlock as o, createCommentVNode as s, createElementBlock as c, createElementVNode as l, createTextVNode as u, createVNode as d, defineComponent as f, normalizeClass as p, onBeforeUnmount as m, openBlock as h, renderList as g, renderSlot as _, toDisplayString as v, watch as y, withCtx as b } from "vue";
|
|
6
6
|
//#region src/components/ActionBar/ActionBar.vue?vue&type=script&setup=true&lang.ts
|
|
7
|
-
var x = ["aria-label"], S = { class: "pointer-events-auto flex animate-sui-toast-in items-center gap-2 rounded-
|
|
7
|
+
var x = ["aria-label"], S = { class: "pointer-events-auto flex animate-sui-toast-in items-center gap-2 rounded-xl border border-sui-edge bg-sui-raised py-1.5 pr-2 pl-4 text-sm text-sui-ink shadow-(--sui-shadow-floating)" }, C = {
|
|
8
8
|
"aria-live": "polite",
|
|
9
9
|
class: "whitespace-nowrap tabular-nums"
|
|
10
10
|
}, w = /*@__PURE__*/ f({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionBar.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_normalizeClass","_createElementVNode","_toDisplayString","_Fragment","_renderList","_createBlock","Button","_withCtx","Icon","_createCommentVNode","_createTextVNode","_renderSlot","Tooltip","_createVNode","CloseIcon","Button_default","Icon_default","Tooltip_default","CloseIcon_default","_hoisted_1","_hoisted_2","_hoisted_3","ActionBar_vue_vue_type_script_setup_true_lang_default","__emit","props","__props","emit","text","computed","onKeydown","event","watch","listening","onBeforeUnmount","openBlock","createElementBlock","normalizeClass","createElementVNode","toDisplayString","_cache","Fragment","renderList","createBlock","item","i","withCtx","createCommentVNode","createTextVNode","renderSlot","_ctx","createVNode"],"sources":["../../../src/components/ActionBar/ActionBar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, watch } from 'vue'\n\nimport Button from '../Button/Button.vue'\nimport Icon from '../Icon/Icon.vue'\nimport Tooltip from '../Tooltip/Tooltip.vue'\nimport CloseIcon from '../internal/CloseIcon.vue'\n\nexport interface ActionBarAction {\n label: string\n /** Passed back with `click-item`, to tell the actions apart. */\n action?: string\n icon?: string\n variant?: 'danger'\n disabled?: boolean\n [key: string]: unknown\n}\n\nexport interface ActionBarProps {\n /** How many records are selected; it shows only while there are some. */\n count: number\n /** Two or three; put the rest in an DropdownMenu in the default slot. */\n actions?: ActionBarAction[]\n /** Adds a clear button, and Escape clears (`@clear`). */\n onClear?: () => void\n /** `{count}` is the number selected. */\n label?: string\n clearLabel?: string\n /** Fixed to the foot of the viewport. False draws it in place. */\n floating?: boolean\n}\n\nconst props = withDefaults(defineProps<ActionBarProps>(), {\n actions: () => [],\n onClear: undefined,\n label: '{count} selected',\n clearLabel: 'Clear selection',\n floating: true\n})\n\nconst emit = defineEmits<{ 'click-item': [action: ActionBarAction] }>()\n\ndefineSlots<{\n /** More controls after the actions, e.g. an DropdownMenu. */\n default?: () => unknown\n}>()\n\nconst text = computed(() => props.label.replace('{count}', String(props.count)))\n\n// Escape clears the selection, unless a dialog is open and takes it.\nfunction onKeydown(event: KeyboardEvent) {\n if (\n event.key !== 'Escape' ||\n event.defaultPrevented ||\n document.querySelector('[role=\"dialog\"], [role=\"alertdialog\"]')\n )\n return\n props.onClear?.()\n}\n\nwatch(\n () => props.count > 0 && !!props.onClear,\n (listening) => {\n if (listening) document.addEventListener('keydown', onKeydown)\n else document.removeEventListener('keydown', onKeydown)\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => document.removeEventListener('keydown', onKeydown))\n</script>\n\n<!-- Actions on the selected records: a floating pill with the count, the actions and a clear button. -->\n<template>\n <div\n v-if=\"count > 0\"\n :aria-label=\"text\"\n class=\"pointer-events-none flex justify-center\"\n :class=\"floating && 'fixed inset-x-0 bottom-4 z-[1150]'\"\n role=\"toolbar\"\n >\n <div\n class=\"pointer-events-auto flex animate-sui-toast-in items-center gap-2 rounded-
|
|
1
|
+
{"version":3,"file":"ActionBar.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_normalizeClass","_createElementVNode","_toDisplayString","_Fragment","_renderList","_createBlock","Button","_withCtx","Icon","_createCommentVNode","_createTextVNode","_renderSlot","Tooltip","_createVNode","CloseIcon","Button_default","Icon_default","Tooltip_default","CloseIcon_default","_hoisted_1","_hoisted_2","_hoisted_3","ActionBar_vue_vue_type_script_setup_true_lang_default","__emit","props","__props","emit","text","computed","onKeydown","event","watch","listening","onBeforeUnmount","openBlock","createElementBlock","normalizeClass","createElementVNode","toDisplayString","_cache","Fragment","renderList","createBlock","item","i","withCtx","createCommentVNode","createTextVNode","renderSlot","_ctx","createVNode"],"sources":["../../../src/components/ActionBar/ActionBar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, watch } from 'vue'\n\nimport Button from '../Button/Button.vue'\nimport Icon from '../Icon/Icon.vue'\nimport Tooltip from '../Tooltip/Tooltip.vue'\nimport CloseIcon from '../internal/CloseIcon.vue'\n\nexport interface ActionBarAction {\n label: string\n /** Passed back with `click-item`, to tell the actions apart. */\n action?: string\n icon?: string\n variant?: 'danger'\n disabled?: boolean\n [key: string]: unknown\n}\n\nexport interface ActionBarProps {\n /** How many records are selected; it shows only while there are some. */\n count: number\n /** Two or three; put the rest in an DropdownMenu in the default slot. */\n actions?: ActionBarAction[]\n /** Adds a clear button, and Escape clears (`@clear`). */\n onClear?: () => void\n /** `{count}` is the number selected. */\n label?: string\n clearLabel?: string\n /** Fixed to the foot of the viewport. False draws it in place. */\n floating?: boolean\n}\n\nconst props = withDefaults(defineProps<ActionBarProps>(), {\n actions: () => [],\n onClear: undefined,\n label: '{count} selected',\n clearLabel: 'Clear selection',\n floating: true\n})\n\nconst emit = defineEmits<{ 'click-item': [action: ActionBarAction] }>()\n\ndefineSlots<{\n /** More controls after the actions, e.g. an DropdownMenu. */\n default?: () => unknown\n}>()\n\nconst text = computed(() => props.label.replace('{count}', String(props.count)))\n\n// Escape clears the selection, unless a dialog is open and takes it.\nfunction onKeydown(event: KeyboardEvent) {\n if (\n event.key !== 'Escape' ||\n event.defaultPrevented ||\n document.querySelector('[role=\"dialog\"], [role=\"alertdialog\"]')\n )\n return\n props.onClear?.()\n}\n\nwatch(\n () => props.count > 0 && !!props.onClear,\n (listening) => {\n if (listening) document.addEventListener('keydown', onKeydown)\n else document.removeEventListener('keydown', onKeydown)\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => document.removeEventListener('keydown', onKeydown))\n</script>\n\n<!-- Actions on the selected records: a floating pill with the count, the actions and a clear button. -->\n<template>\n <div\n v-if=\"count > 0\"\n :aria-label=\"text\"\n class=\"pointer-events-none flex justify-center\"\n :class=\"floating && 'fixed inset-x-0 bottom-4 z-[1150]'\"\n role=\"toolbar\"\n >\n <div\n class=\"pointer-events-auto flex animate-sui-toast-in items-center gap-2 rounded-xl border border-sui-edge bg-sui-raised py-1.5 pr-2 pl-4 text-sm text-sui-ink shadow-(--sui-shadow-floating)\"\n >\n <span aria-live=\"polite\" class=\"whitespace-nowrap tabular-nums\">{{ text }}</span>\n <span aria-hidden=\"true\" class=\"mx-1 h-4 w-px bg-sui-line\" />\n <Button\n v-for=\"(item, i) in actions\"\n :key=\"item.action ?? i\"\n :disabled=\"item.disabled\"\n size=\"sm\"\n :variant=\"item.variant === 'danger' ? 'danger-outline' : 'secondary'\"\n @click=\"emit('click-item', item)\"\n >\n <Icon v-if=\"item.icon\" :name=\"item.icon\" />\n {{ item.label }}\n </Button>\n <slot />\n <Tooltip v-if=\"onClear\" :text=\"clearLabel\">\n <Button :aria-label=\"clearLabel\" icon-only size=\"xs\" variant=\"ghost\" @click=\"onClear()\">\n <CloseIcon class=\"fill-sui-ink-subtle stroke-sui-ink-subtle\" />\n </Button>\n </Tooltip>\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;EAgCA,IAAM0B,IAAQC,GAQRC,IAAOH,GAOPI,IAAOC,QAAeJ,EAAM,MAAM,QAAQ,WAAW,OAAOA,EAAM,KAAK,CAAC,CAAC;EAG/E,SAASK,EAAU,GAAsB;GACvC,AACEC,EAAM,QAAQ,YACdA,EAAM,oBACN,SAAS,cAAc,2CAAuC,KAGhEN,EAAM,UAAU;EAClB;E,OAEAO,QACQP,EAAM,QAAQ,KAAK,CAAC,CAACA,EAAM,UAChC,MAAc;GACb,AAAIQ,IAAW,SAAS,iBAAiB,WAAWH,CAAS,IACxD,SAAS,oBAAoB,WAAWA,CAAS;EACxD,GACA,EAAE,WAAW,GAAK,CACpB,GAEAI,QAAsB,SAAS,oBAAoB,WAAWJ,CAAS,CAAC,I,SAM9DJ,EAAA,QAAK,KADb3B,EAAA,GAAAC,EA8BM,OAAA;;GA5BH,cAAY4B,EAAA;GACb,OAAK3B,EAAA,CAAC,2CACEyB,EAAA,YAAQ,mCAAA,CAAA;GAChB,MAAK;E,IAELxB,EAsBM,OAtBNmB,GAsBM;GAnBJnB,EAAiF,QAAjFoB,GAAiFnB,EAAdyB,EAAA,KAAI,GAAA,CAAA;GACvE,AAAAY,EAAA,OAAAtC,EAA6D,QAAA;IAAvD,eAAY;IAAO,OAAM;;IAC/BH,EAAA,EAAA,GAAAC,EAUSI,GAAA,MAAAC,EATaqB,EAAA,UAAZ,GAAM,OADhB3B,EAAA,GAAAO,EAUSC,GAAA;IARN,KAAKqC,EAAK,UAAUC;IACpB,UAAUD,EAAK;IAChB,MAAK;IACJ,SAASA,EAAK,YAAO,WAAA,mBAAA;IACrB,UAAK,MAAEjB,EAAI,cAAeiB,CAAI;;IAE/B,SAAApC,QAA2C,CAA/BoC,EAAK,QAAjB7C,EAAA,GAAAO,EAA2CG,GAAA;;KAAnB,MAAMmC,EAAK;I,oCAAQjC,EAAA,MAC3CR,EAAGyC,EAAK,KAAK,GAAA,CAAA,C;;;;;;;GAEfhC,EAAQsC,EAAA,QAAA,SAAA;GACOxB,EAAA,WAAf3B,EAAA,GAAAO,EAIUO,GAAA;;IAJe,MAAMa,EAAA;;IAC7B,SAAAlB,QAES,CAFTM,EAESP,GAAA;KAFA,cAAYmB,EAAA;KAAY,aAAA;KAAU,MAAK;KAAK,SAAQ;KAAS,SAAK,AAAAc,EAAA,QAAA,MAAEd,EAAA,QAAO;;KAClF,SAAAlB,QAA+D,CAA/DM,EAA+DC,GAAA,EAApD,OAAM,4CAA2C,CAAA,C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Alert.js","names":["_sfc_main","Alert_vue_vue_type_script_setup_true_lang_default","Alert_default"],"sources":["../../../src/components/Alert/Alert.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport Icon from '../Icon/Icon.vue'\nimport type { IconColor } from '../Icon/colors'\n\nexport type AlertTone = 'danger' | 'warning' | 'info' | 'neutral'\n\nexport interface AlertProps {\n tone?: AlertTone\n /** An icon for the tile; without one, the banner shows a dot. */\n icon?: string\n dismissible?: boolean\n /** The dismiss button's accessible name. */\n dismissLabel?: string\n /** A rounded notice inside a card or form, instead of a full-width bar. */\n inset?: boolean\n}\n\nconst props = withDefaults(defineProps<AlertProps>(), { tone: 'warning', icon: undefined, dismissLabel: 'Dismiss' })\n\ndefineEmits<{ dismiss: [] }>()\n\n// The tile is a soft filled chip, its alpha tuned so each tone reads with equal weight on its own tinted ground.\nconst tones: Record<AlertTone, { bar: string; line: string; tile: string; icon: IconColor; dot: string }> = {\n danger: {\n bar: 'bg-sui-danger-soft',\n line: 'border-sui-danger-line',\n tile: 'bg-sui-danger-solid/20',\n icon: 'danger',\n dot: 'bg-sui-danger-solid'\n },\n warning: {\n bar: 'bg-sui-warning-soft',\n line: 'border-sui-warning-line',\n tile: 'bg-sui-warning-bright/20',\n icon: 'warning-mid',\n dot: 'bg-sui-warning-mid'\n },\n info: {\n bar: 'bg-sui-accent-soft',\n line: 'border-sui-accent-line',\n tile: 'bg-sui-accent-solid/20',\n icon: 'accent',\n dot: 'bg-sui-accent-solid'\n },\n neutral: {\n bar: 'bg-sui-canvas',\n line: 'border-sui-line-subtle',\n tile: 'bg-sui-line-subtle',\n icon: 'ink-muted',\n dot: 'bg-sui-mark-faint'\n }\n}\n\nconst tone = computed(() => tones[props.tone])\n</script>\n\n<template>\n <div\n :class=\"[\n tone.bar,\n inset\n ? ['flex w-full items-center gap-2.5 rounded-xl border px-3 py-2.5', tone.line]\n : 'flex w-full items-center gap-3 border-b border-sui-line-subtle px-6 py-3'\n ]\"\n >\n <slot v-if=\"$slots.leading\" name=\"leading\" />\n <span v-else-if=\"icon\" class=\"flex h-7 w-7 shrink-0 items-center justify-center rounded-lg\" :class=\"tone.tile\">\n <Icon class=\"h-4 w-4\" :color=\"tone.icon\" :name=\"icon\" />\n </span>\n <span v-else class=\"h-1.5 w-1.5 shrink-0 rounded-full\" :class=\"tone.dot\" />\n\n <div class=\"min-w-0 flex-1 text-sm leading-snug text-sui-ink-body\">\n <slot />\n </div>\n\n <div v-if=\"$slots.action\" class=\"shrink-0\">\n <slot name=\"action\" />\n </div>\n\n <button\n v-if=\"dismissible\"\n :aria-label=\"dismissLabel\"\n class=\"flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-sui-ink-faint transition-colors hover:bg-sui-
|
|
1
|
+
{"version":3,"file":"Alert.js","names":["_sfc_main","Alert_vue_vue_type_script_setup_true_lang_default","Alert_default"],"sources":["../../../src/components/Alert/Alert.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport Icon from '../Icon/Icon.vue'\nimport type { IconColor } from '../Icon/colors'\n\nexport type AlertTone = 'danger' | 'warning' | 'info' | 'neutral'\n\nexport interface AlertProps {\n tone?: AlertTone\n /** An icon for the tile; without one, the banner shows a dot. */\n icon?: string\n dismissible?: boolean\n /** The dismiss button's accessible name. */\n dismissLabel?: string\n /** A rounded notice inside a card or form, instead of a full-width bar. */\n inset?: boolean\n}\n\nconst props = withDefaults(defineProps<AlertProps>(), { tone: 'warning', icon: undefined, dismissLabel: 'Dismiss' })\n\ndefineEmits<{ dismiss: [] }>()\n\n// The tile is a soft filled chip, its alpha tuned so each tone reads with equal weight on its own tinted ground.\nconst tones: Record<AlertTone, { bar: string; line: string; tile: string; icon: IconColor; dot: string }> = {\n danger: {\n bar: 'bg-sui-danger-soft',\n line: 'border-sui-danger-line',\n tile: 'bg-sui-danger-solid/20',\n icon: 'danger',\n dot: 'bg-sui-danger-solid'\n },\n warning: {\n bar: 'bg-sui-warning-soft',\n line: 'border-sui-warning-line',\n tile: 'bg-sui-warning-bright/20',\n icon: 'warning-mid',\n dot: 'bg-sui-warning-mid'\n },\n info: {\n bar: 'bg-sui-accent-soft',\n line: 'border-sui-accent-line',\n tile: 'bg-sui-accent-solid/20',\n icon: 'accent',\n dot: 'bg-sui-accent-solid'\n },\n neutral: {\n bar: 'bg-sui-canvas',\n line: 'border-sui-line-subtle',\n tile: 'bg-sui-line-subtle',\n icon: 'ink-muted',\n dot: 'bg-sui-mark-faint'\n }\n}\n\nconst tone = computed(() => tones[props.tone])\n</script>\n\n<template>\n <div\n :class=\"[\n tone.bar,\n inset\n ? ['flex w-full items-center gap-2.5 rounded-xl border px-3 py-2.5', tone.line]\n : 'flex w-full items-center gap-3 border-b border-sui-line-subtle px-6 py-3'\n ]\"\n >\n <slot v-if=\"$slots.leading\" name=\"leading\" />\n <span v-else-if=\"icon\" class=\"flex h-7 w-7 shrink-0 items-center justify-center rounded-lg\" :class=\"tone.tile\">\n <Icon class=\"h-4 w-4\" :color=\"tone.icon\" :name=\"icon\" />\n </span>\n <span v-else class=\"h-1.5 w-1.5 shrink-0 rounded-full\" :class=\"tone.dot\" />\n\n <div class=\"min-w-0 flex-1 text-sm leading-snug text-sui-ink-body\">\n <slot />\n </div>\n\n <div v-if=\"$slots.action\" class=\"shrink-0\">\n <slot name=\"action\" />\n </div>\n\n <button\n v-if=\"dismissible\"\n :aria-label=\"dismissLabel\"\n class=\"flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-sui-ink-faint transition-colors hover:bg-sui-fill-hover hover:text-sui-ink-body focus-visible:sui-ring\"\n type=\"button\"\n @click=\"$emit('dismiss')\"\n >\n <svg\n aria-hidden=\"true\"\n class=\"h-3 w-3\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-width=\"1.5\"\n viewBox=\"0 0 12 12\"\n >\n <path d=\"M9 3 3 9M3 3l6 6\" />\n </svg>\n </button>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -62,7 +62,7 @@ var u = { class: "min-w-0 flex-1 text-sm leading-snug text-sui-ink-body" }, d =
|
|
|
62
62
|
o.dismissible ? (c(), r("button", {
|
|
63
63
|
key: 4,
|
|
64
64
|
"aria-label": o.dismissLabel,
|
|
65
|
-
class: "flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-sui-ink-faint transition-colors hover:bg-sui-
|
|
65
|
+
class: "flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-sui-ink-faint transition-colors hover:bg-sui-fill-hover hover:text-sui-ink-body focus-visible:sui-ring",
|
|
66
66
|
type: "button",
|
|
67
67
|
onClick: p[0] ||= (e) => t.$emit("dismiss")
|
|
68
68
|
}, [...p[1] ||= [i("svg", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Alert.vue_vue_type_script_setup_true_lang.js","names":["$slots","$emit","_openBlock","_createElementBlock","_normalizeClass","_renderSlot","_createVNode","Icon","_createElementVNode","_createCommentVNode","Icon_default","_hoisted_1","_hoisted_2","_hoisted_3","Alert_vue_vue_type_script_setup_true_lang_default","props","__props","tones","tone","computed","openBlock","createElementBlock","normalizeClass","_ctx","renderSlot","createVNode","createElementVNode","createCommentVNode","_cache"],"sources":["../../../src/components/Alert/Alert.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport Icon from '../Icon/Icon.vue'\nimport type { IconColor } from '../Icon/colors'\n\nexport type AlertTone = 'danger' | 'warning' | 'info' | 'neutral'\n\nexport interface AlertProps {\n tone?: AlertTone\n /** An icon for the tile; without one, the banner shows a dot. */\n icon?: string\n dismissible?: boolean\n /** The dismiss button's accessible name. */\n dismissLabel?: string\n /** A rounded notice inside a card or form, instead of a full-width bar. */\n inset?: boolean\n}\n\nconst props = withDefaults(defineProps<AlertProps>(), { tone: 'warning', icon: undefined, dismissLabel: 'Dismiss' })\n\ndefineEmits<{ dismiss: [] }>()\n\n// The tile is a soft filled chip, its alpha tuned so each tone reads with equal weight on its own tinted ground.\nconst tones: Record<AlertTone, { bar: string; line: string; tile: string; icon: IconColor; dot: string }> = {\n danger: {\n bar: 'bg-sui-danger-soft',\n line: 'border-sui-danger-line',\n tile: 'bg-sui-danger-solid/20',\n icon: 'danger',\n dot: 'bg-sui-danger-solid'\n },\n warning: {\n bar: 'bg-sui-warning-soft',\n line: 'border-sui-warning-line',\n tile: 'bg-sui-warning-bright/20',\n icon: 'warning-mid',\n dot: 'bg-sui-warning-mid'\n },\n info: {\n bar: 'bg-sui-accent-soft',\n line: 'border-sui-accent-line',\n tile: 'bg-sui-accent-solid/20',\n icon: 'accent',\n dot: 'bg-sui-accent-solid'\n },\n neutral: {\n bar: 'bg-sui-canvas',\n line: 'border-sui-line-subtle',\n tile: 'bg-sui-line-subtle',\n icon: 'ink-muted',\n dot: 'bg-sui-mark-faint'\n }\n}\n\nconst tone = computed(() => tones[props.tone])\n</script>\n\n<template>\n <div\n :class=\"[\n tone.bar,\n inset\n ? ['flex w-full items-center gap-2.5 rounded-xl border px-3 py-2.5', tone.line]\n : 'flex w-full items-center gap-3 border-b border-sui-line-subtle px-6 py-3'\n ]\"\n >\n <slot v-if=\"$slots.leading\" name=\"leading\" />\n <span v-else-if=\"icon\" class=\"flex h-7 w-7 shrink-0 items-center justify-center rounded-lg\" :class=\"tone.tile\">\n <Icon class=\"h-4 w-4\" :color=\"tone.icon\" :name=\"icon\" />\n </span>\n <span v-else class=\"h-1.5 w-1.5 shrink-0 rounded-full\" :class=\"tone.dot\" />\n\n <div class=\"min-w-0 flex-1 text-sm leading-snug text-sui-ink-body\">\n <slot />\n </div>\n\n <div v-if=\"$slots.action\" class=\"shrink-0\">\n <slot name=\"action\" />\n </div>\n\n <button\n v-if=\"dismissible\"\n :aria-label=\"dismissLabel\"\n class=\"flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-sui-ink-faint transition-colors hover:bg-sui-
|
|
1
|
+
{"version":3,"file":"Alert.vue_vue_type_script_setup_true_lang.js","names":["$slots","$emit","_openBlock","_createElementBlock","_normalizeClass","_renderSlot","_createVNode","Icon","_createElementVNode","_createCommentVNode","Icon_default","_hoisted_1","_hoisted_2","_hoisted_3","Alert_vue_vue_type_script_setup_true_lang_default","props","__props","tones","tone","computed","openBlock","createElementBlock","normalizeClass","_ctx","renderSlot","createVNode","createElementVNode","createCommentVNode","_cache"],"sources":["../../../src/components/Alert/Alert.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport Icon from '../Icon/Icon.vue'\nimport type { IconColor } from '../Icon/colors'\n\nexport type AlertTone = 'danger' | 'warning' | 'info' | 'neutral'\n\nexport interface AlertProps {\n tone?: AlertTone\n /** An icon for the tile; without one, the banner shows a dot. */\n icon?: string\n dismissible?: boolean\n /** The dismiss button's accessible name. */\n dismissLabel?: string\n /** A rounded notice inside a card or form, instead of a full-width bar. */\n inset?: boolean\n}\n\nconst props = withDefaults(defineProps<AlertProps>(), { tone: 'warning', icon: undefined, dismissLabel: 'Dismiss' })\n\ndefineEmits<{ dismiss: [] }>()\n\n// The tile is a soft filled chip, its alpha tuned so each tone reads with equal weight on its own tinted ground.\nconst tones: Record<AlertTone, { bar: string; line: string; tile: string; icon: IconColor; dot: string }> = {\n danger: {\n bar: 'bg-sui-danger-soft',\n line: 'border-sui-danger-line',\n tile: 'bg-sui-danger-solid/20',\n icon: 'danger',\n dot: 'bg-sui-danger-solid'\n },\n warning: {\n bar: 'bg-sui-warning-soft',\n line: 'border-sui-warning-line',\n tile: 'bg-sui-warning-bright/20',\n icon: 'warning-mid',\n dot: 'bg-sui-warning-mid'\n },\n info: {\n bar: 'bg-sui-accent-soft',\n line: 'border-sui-accent-line',\n tile: 'bg-sui-accent-solid/20',\n icon: 'accent',\n dot: 'bg-sui-accent-solid'\n },\n neutral: {\n bar: 'bg-sui-canvas',\n line: 'border-sui-line-subtle',\n tile: 'bg-sui-line-subtle',\n icon: 'ink-muted',\n dot: 'bg-sui-mark-faint'\n }\n}\n\nconst tone = computed(() => tones[props.tone])\n</script>\n\n<template>\n <div\n :class=\"[\n tone.bar,\n inset\n ? ['flex w-full items-center gap-2.5 rounded-xl border px-3 py-2.5', tone.line]\n : 'flex w-full items-center gap-3 border-b border-sui-line-subtle px-6 py-3'\n ]\"\n >\n <slot v-if=\"$slots.leading\" name=\"leading\" />\n <span v-else-if=\"icon\" class=\"flex h-7 w-7 shrink-0 items-center justify-center rounded-lg\" :class=\"tone.tile\">\n <Icon class=\"h-4 w-4\" :color=\"tone.icon\" :name=\"icon\" />\n </span>\n <span v-else class=\"h-1.5 w-1.5 shrink-0 rounded-full\" :class=\"tone.dot\" />\n\n <div class=\"min-w-0 flex-1 text-sm leading-snug text-sui-ink-body\">\n <slot />\n </div>\n\n <div v-if=\"$slots.action\" class=\"shrink-0\">\n <slot name=\"action\" />\n </div>\n\n <button\n v-if=\"dismissible\"\n :aria-label=\"dismissLabel\"\n class=\"flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-sui-ink-faint transition-colors hover:bg-sui-fill-hover hover:text-sui-ink-body focus-visible:sui-ring\"\n type=\"button\"\n @click=\"$emit('dismiss')\"\n >\n <svg\n aria-hidden=\"true\"\n class=\"h-3 w-3\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-width=\"1.5\"\n viewBox=\"0 0 12 12\"\n >\n <path d=\"M9 3 3 9M3 3l6 6\" />\n </svg>\n </button>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;EAmBA,IAAMe,IAAQC,GAKRC,IAAsG;GAC1G,QAAQ;IACN,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,KAAK;GACP;GACA,SAAS;IACP,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,KAAK;GACP;GACA,MAAM;IACJ,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,KAAK;GACP;GACA,SAAS;IACP,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,KAAK;GACP;EACF,GAEMC,IAAOC,QAAeF,EAAMF,EAAM,KAAK;E,kBAI3Cb,EAAA,GAAAC,EAyCM,OAAA,EAxCH,OAAKC,EAAA,CAAUc,EAAA,MAAK,KAAWF,EAAA,QAAmF,CAAA,kEAAAE,EAAA,MAAK,IAAI,I;GAOhHlB,EAAAA,OAAO,UAAnBK,EAA6CkB,EAAA,QAAA,WAAA,CAAA,GAAA,KAAA,GAAA,KAAA,GAAA,CAAA,IAC5BP,EAAA,QAAjBd,EAAA,GAAAC,EAEO,QAAA;;IAFgB,OAAKC,EAAA,CAAC,gEAAuEc,EAAA,MAAK,IAAI,CAAA;G,IAC3GZ,EAAwDC,GAAA;IAAlD,OAAM;IAAW,OAAOW,EAAA,MAAK;IAAO,MAAMF,EAAA;G,wCAElDd,EAAA,GAAAC,EAA2E,QAAA;;IAA9D,OAAKC,EAAA,CAAC,qCAA4Cc,EAAA,MAAK,GAAG,CAAA;;GAEvEV,EAEM,OAFNG,GAEM,CADJN,EAAQkB,EAAA,QAAA,SAAA,C;GAGCvB,EAAAA,OAAO,UAAlBE,EAAA,GAAAC,EAEM,OAFNS,GAEM,CADJP,EAAsBkB,EAAA,QAAA,QAAA,C;GAIhBP,EAAA,eADRd,EAAA,GAAAC,EAkBS,UAAA;;IAhBN,cAAYa,EAAA;IACb,OAAM;IACN,MAAK;IACJ,SAAK,AAAAY,EAAA,QAAA,MAAE3B,EAAAA,MAAK,SAAA;G,iBAEbO,EAUM,OAAA;IATJ,eAAY;IACZ,OAAM;IACN,MAAK;IACL,QAAO;IACP,kBAAe;IACf,gBAAa;IACb,SAAQ;G,IAERA,EAA6B,QAAA,EAAvB,GAAE,mBAAkB,CAAA,C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AlertDialog.js","names":["_sfc_main","AlertDialog_vue_vue_type_script_setup_true_lang_default","AlertDialog_default"],"sources":["../../../src/components/AlertDialog/AlertDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\n\nimport {\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogOverlay,\n AlertDialogPortal,\n AlertDialogRoot,\n AlertDialogTitle\n} from 'reka-ui'\n\nimport { type ConfirmRequest, confirmRequest } from '../../composables/useConfirm'\nimport Button from '../Button/Button.vue'\n\nexport interface AlertDialogProps {\n /** Defaults for every confirmation; each call can override them. */\n confirmLabel?: string\n cancelLabel?: string\n}\n\nwithDefaults(defineProps<AlertDialogProps>(), { confirmLabel: 'Confirm', cancelLabel: 'Cancel' })\n\n// Kept while it animates out, after the request is answered. Plain buttons, not Reka's Action and Cancel: those\n// close the dialog themselves, which would answer before the click does.\nconst shown = ref<ConfirmRequest | null>(null)\nconst open = computed({\n get: () => !!confirmRequest.value,\n set: (value) => !value && answer(false)\n})\n\nwatch(confirmRequest, (request) => {\n if (request) shown.value = request\n})\n\nfunction answer(confirmed: boolean) {\n confirmRequest.value?.resolve(confirmed)\n confirmRequest.value = null\n}\n</script>\n\n<template>\n <AlertDialogRoot v-model:open=\"open\">\n <AlertDialogPortal>\n <AlertDialogOverlay\n class=\"fixed inset-0 z-[1160] flex items-
|
|
1
|
+
{"version":3,"file":"AlertDialog.js","names":["_sfc_main","AlertDialog_vue_vue_type_script_setup_true_lang_default","AlertDialog_default"],"sources":["../../../src/components/AlertDialog/AlertDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\n\nimport {\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogOverlay,\n AlertDialogPortal,\n AlertDialogRoot,\n AlertDialogTitle\n} from 'reka-ui'\n\nimport { type ConfirmRequest, confirmRequest } from '../../composables/useConfirm'\nimport Button from '../Button/Button.vue'\n\nexport interface AlertDialogProps {\n /** Defaults for every confirmation; each call can override them. */\n confirmLabel?: string\n cancelLabel?: string\n}\n\nwithDefaults(defineProps<AlertDialogProps>(), { confirmLabel: 'Confirm', cancelLabel: 'Cancel' })\n\n// Kept while it animates out, after the request is answered. Plain buttons, not Reka's Action and Cancel: those\n// close the dialog themselves, which would answer before the click does.\nconst shown = ref<ConfirmRequest | null>(null)\nconst open = computed({\n get: () => !!confirmRequest.value,\n set: (value) => !value && answer(false)\n})\n\nwatch(confirmRequest, (request) => {\n if (request) shown.value = request\n})\n\nfunction answer(confirmed: boolean) {\n confirmRequest.value?.resolve(confirmed)\n confirmRequest.value = null\n}\n</script>\n\n<template>\n <AlertDialogRoot v-model:open=\"open\">\n <AlertDialogPortal>\n <AlertDialogOverlay\n class=\"fixed inset-0 z-[1160] flex items-start justify-center bg-[rgb(var(--sui-scrim)/var(--sui-scrim-alpha))] px-4 pt-(--sui-dialog-offset) pb-4 data-[state=closed]:animate-sui-scrim-out data-[state=open]:animate-sui-scrim-in\"\n >\n <AlertDialogContent\n v-if=\"shown\"\n class=\"flex w-[27rem] max-w-full flex-col overflow-hidden rounded-xl border border-sui-edge bg-sui-raised shadow-(--sui-shadow-floating) outline-hidden data-[state=closed]:animate-sui-dialog-out data-[state=open]:animate-sui-dialog-in\"\n @open-auto-focus.prevent=\"($event.target as HTMLElement).focus()\"\n >\n <div class=\"px-5 pt-4\">\n <AlertDialogTitle class=\"truncate text-sm font-semibold text-sui-ink\">{{ shown.title }}</AlertDialogTitle>\n </div>\n <AlertDialogDescription class=\"px-5 pt-2 pb-5 text-sm leading-relaxed text-sui-ink-emphasis\">\n {{ shown.message }}\n </AlertDialogDescription>\n <div class=\"flex items-center justify-end gap-2.5 px-4 pb-4\">\n <Button type=\"button\" :variant=\"shown.cancelVariant ?? 'ghost'\" @click=\"answer(false)\">\n {{ shown.cancelLabel ?? cancelLabel }}\n </Button>\n <Button type=\"button\" :variant=\"shown.confirmVariant ?? 'primary'\" @click=\"answer(true)\">\n {{ shown.confirmLabel ?? confirmLabel }}\n </Button>\n </div>\n </AlertDialogContent>\n </AlertDialogOverlay>\n </AlertDialogPortal>\n </AlertDialogRoot>\n</template>\n"],"mappings":""}
|
|
@@ -3,7 +3,7 @@ import { confirmRequest as t } from "../../composables/useConfirm.js";
|
|
|
3
3
|
import { computed as n, createBlock as r, createCommentVNode as i, createElementVNode as a, createTextVNode as o, createVNode as s, defineComponent as c, openBlock as l, ref as u, toDisplayString as d, unref as f, watch as p, withCtx as m, withModifiers as h } from "vue";
|
|
4
4
|
import { AlertDialogContent as g, AlertDialogDescription as _, AlertDialogOverlay as v, AlertDialogPortal as y, AlertDialogRoot as b, AlertDialogTitle as x } from "reka-ui";
|
|
5
5
|
//#region src/components/AlertDialog/AlertDialog.vue?vue&type=script&setup=true&lang.ts
|
|
6
|
-
var S = { class: "
|
|
6
|
+
var S = { class: "px-5 pt-4" }, C = { class: "flex items-center justify-end gap-2.5 px-4 pb-4" }, w = /*@__PURE__*/ c({
|
|
7
7
|
__name: "AlertDialog",
|
|
8
8
|
props: {
|
|
9
9
|
confirmLabel: { default: "Confirm" },
|
|
@@ -25,18 +25,18 @@ var S = { class: "border-b border-sui-line-subtle px-5 py-4" }, C = { class: "fl
|
|
|
25
25
|
"onUpdate:open": n[3] ||= (e) => T.value = e
|
|
26
26
|
}, {
|
|
27
27
|
default: m(() => [s(f(y), null, {
|
|
28
|
-
default: m(() => [s(f(v), { class: "fixed inset-0 z-[1160] flex items-
|
|
28
|
+
default: m(() => [s(f(v), { class: "fixed inset-0 z-[1160] flex items-start justify-center bg-[rgb(var(--sui-scrim)/var(--sui-scrim-alpha))] px-4 pt-(--sui-dialog-offset) pb-4 data-[state=closed]:animate-sui-scrim-out data-[state=open]:animate-sui-scrim-in" }, {
|
|
29
29
|
default: m(() => [w.value ? (l(), r(f(g), {
|
|
30
30
|
key: 0,
|
|
31
|
-
class: "flex w-[27rem] max-w-
|
|
31
|
+
class: "flex w-[27rem] max-w-full flex-col overflow-hidden rounded-xl border border-sui-edge bg-sui-raised shadow-(--sui-shadow-floating) outline-hidden data-[state=closed]:animate-sui-dialog-out data-[state=open]:animate-sui-dialog-in",
|
|
32
32
|
onOpenAutoFocus: n[2] ||= h((e) => e.target.focus(), ["prevent"])
|
|
33
33
|
}, {
|
|
34
34
|
default: m(() => [
|
|
35
|
-
a("div", S, [s(f(x), { class: "truncate text-
|
|
35
|
+
a("div", S, [s(f(x), { class: "truncate text-sm font-semibold text-sui-ink" }, {
|
|
36
36
|
default: m(() => [o(d(w.value.title), 1)]),
|
|
37
37
|
_: 1
|
|
38
38
|
})]),
|
|
39
|
-
s(f(_), { class: "px-5
|
|
39
|
+
s(f(_), { class: "px-5 pt-2 pb-5 text-sm leading-relaxed text-sui-ink-emphasis" }, {
|
|
40
40
|
default: m(() => [o(d(w.value.message), 1)]),
|
|
41
41
|
_: 1
|
|
42
42
|
}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AlertDialog.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","_unref","_withCtx","_createVNode","_withModifiers","_createElementVNode","_createTextVNode","_toDisplayString","Button","_createCommentVNode","Button_default","_hoisted_1","_hoisted_2","AlertDialog_vue_vue_type_script_setup_true_lang_default","shown","ref","open","computed","confirmRequest","value","answer","request","confirmed","openBlock","createBlock","unref","AlertDialogRoot","_cache","$event","withCtx","createVNode","AlertDialogPortal","AlertDialogOverlay","AlertDialogContent","withModifiers","createElementVNode","AlertDialogTitle","createTextVNode","toDisplayString","AlertDialogDescription","__props","createCommentVNode"],"sources":["../../../src/components/AlertDialog/AlertDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\n\nimport {\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogOverlay,\n AlertDialogPortal,\n AlertDialogRoot,\n AlertDialogTitle\n} from 'reka-ui'\n\nimport { type ConfirmRequest, confirmRequest } from '../../composables/useConfirm'\nimport Button from '../Button/Button.vue'\n\nexport interface AlertDialogProps {\n /** Defaults for every confirmation; each call can override them. */\n confirmLabel?: string\n cancelLabel?: string\n}\n\nwithDefaults(defineProps<AlertDialogProps>(), { confirmLabel: 'Confirm', cancelLabel: 'Cancel' })\n\n// Kept while it animates out, after the request is answered. Plain buttons, not Reka's Action and Cancel: those\n// close the dialog themselves, which would answer before the click does.\nconst shown = ref<ConfirmRequest | null>(null)\nconst open = computed({\n get: () => !!confirmRequest.value,\n set: (value) => !value && answer(false)\n})\n\nwatch(confirmRequest, (request) => {\n if (request) shown.value = request\n})\n\nfunction answer(confirmed: boolean) {\n confirmRequest.value?.resolve(confirmed)\n confirmRequest.value = null\n}\n</script>\n\n<template>\n <AlertDialogRoot v-model:open=\"open\">\n <AlertDialogPortal>\n <AlertDialogOverlay\n class=\"fixed inset-0 z-[1160] flex items-
|
|
1
|
+
{"version":3,"file":"AlertDialog.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","_unref","_withCtx","_createVNode","_withModifiers","_createElementVNode","_createTextVNode","_toDisplayString","Button","_createCommentVNode","Button_default","_hoisted_1","_hoisted_2","AlertDialog_vue_vue_type_script_setup_true_lang_default","shown","ref","open","computed","confirmRequest","value","answer","request","confirmed","openBlock","createBlock","unref","AlertDialogRoot","_cache","$event","withCtx","createVNode","AlertDialogPortal","AlertDialogOverlay","AlertDialogContent","withModifiers","createElementVNode","AlertDialogTitle","createTextVNode","toDisplayString","AlertDialogDescription","__props","createCommentVNode"],"sources":["../../../src/components/AlertDialog/AlertDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\n\nimport {\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogOverlay,\n AlertDialogPortal,\n AlertDialogRoot,\n AlertDialogTitle\n} from 'reka-ui'\n\nimport { type ConfirmRequest, confirmRequest } from '../../composables/useConfirm'\nimport Button from '../Button/Button.vue'\n\nexport interface AlertDialogProps {\n /** Defaults for every confirmation; each call can override them. */\n confirmLabel?: string\n cancelLabel?: string\n}\n\nwithDefaults(defineProps<AlertDialogProps>(), { confirmLabel: 'Confirm', cancelLabel: 'Cancel' })\n\n// Kept while it animates out, after the request is answered. Plain buttons, not Reka's Action and Cancel: those\n// close the dialog themselves, which would answer before the click does.\nconst shown = ref<ConfirmRequest | null>(null)\nconst open = computed({\n get: () => !!confirmRequest.value,\n set: (value) => !value && answer(false)\n})\n\nwatch(confirmRequest, (request) => {\n if (request) shown.value = request\n})\n\nfunction answer(confirmed: boolean) {\n confirmRequest.value?.resolve(confirmed)\n confirmRequest.value = null\n}\n</script>\n\n<template>\n <AlertDialogRoot v-model:open=\"open\">\n <AlertDialogPortal>\n <AlertDialogOverlay\n class=\"fixed inset-0 z-[1160] flex items-start justify-center bg-[rgb(var(--sui-scrim)/var(--sui-scrim-alpha))] px-4 pt-(--sui-dialog-offset) pb-4 data-[state=closed]:animate-sui-scrim-out data-[state=open]:animate-sui-scrim-in\"\n >\n <AlertDialogContent\n v-if=\"shown\"\n class=\"flex w-[27rem] max-w-full flex-col overflow-hidden rounded-xl border border-sui-edge bg-sui-raised shadow-(--sui-shadow-floating) outline-hidden data-[state=closed]:animate-sui-dialog-out data-[state=open]:animate-sui-dialog-in\"\n @open-auto-focus.prevent=\"($event.target as HTMLElement).focus()\"\n >\n <div class=\"px-5 pt-4\">\n <AlertDialogTitle class=\"truncate text-sm font-semibold text-sui-ink\">{{ shown.title }}</AlertDialogTitle>\n </div>\n <AlertDialogDescription class=\"px-5 pt-2 pb-5 text-sm leading-relaxed text-sui-ink-emphasis\">\n {{ shown.message }}\n </AlertDialogDescription>\n <div class=\"flex items-center justify-end gap-2.5 px-4 pb-4\">\n <Button type=\"button\" :variant=\"shown.cancelVariant ?? 'ghost'\" @click=\"answer(false)\">\n {{ shown.cancelLabel ?? cancelLabel }}\n </Button>\n <Button type=\"button\" :variant=\"shown.confirmVariant ?? 'primary'\" @click=\"answer(true)\">\n {{ shown.confirmLabel ?? confirmLabel }}\n </Button>\n </div>\n </AlertDialogContent>\n </AlertDialogOverlay>\n </AlertDialogPortal>\n </AlertDialogRoot>\n</template>\n"],"mappings":";;;;;;;;;;;;EAyBA,IAAMe,IAAQC,EAA2B,IAAI,GACvCC,IAAOC,EAAS;GACpB,WAAW,CAAC,CAACC,EAAe;GAC5B,MAAM,MAAU,CAACC,KAASC,EAAO,EAAK;EACxC,CAAC;EAED,EAAMF,IAAiB,MAAY;GACjC,AAAIG,MAAS,EAAM,QAAQA;EAC7B,CAAC;EAED,SAASD,EAAO,GAAoB;GAElC,AADAF,EAAe,OAAO,QAAQI,CAAS,GACvC,EAAe,QAAQ;EACzB;E,kBAIEvB,EAAA,GAAAC,EA2BkBC,EAAAyB,CAAA,GAAA;GA3BO,MAAMV,EAAA;GAAA,iBAAA,AAAAW,EAAA,QAAA,MAAA,EAAI,QAAAC;;GACjC,SAAA1B,QAyBoB,CAzBpBC,EAyBoBF,EAAA8B,CAAA,GAAA,MAAA;IAxBlB,SAAA7B,QAuBqB,CAvBrBC,EAuBqBF,EAAA+B,CAAA,GAAA,EAtBnB,OAAM,+NAA8N,GAAA;KAEpO,SAAA9B,QAmBqB,CAlBbY,EAAA,SADRf,EAAA,GAAAC,EAmBqBC,EAAAgC,CAAA,GAAA;;MAjBnB,OAAM;MACL,iBAAe,AAAAN,EAAA,OAAAvB,GAAA,MAAWwB,EAAO,OAAuB,MAAK,GAAA,CAAA,SAAA,CAAA;;MAE9D,SAAA1B,QAEM;OAFNG,EAEM,OAFNM,GAEM,CADJR,EAA0GF,EAAAmC,CAAA,GAAA,EAAxF,OAAM,8CAA6C,GAAA;QAAC,SAAAlC,QAAiB,CAAdI,EAAAC,EAAAO,EAAA,MAAM,KAAK,GAAA,CAAA,C;;;OAEtFX,EAEyBF,EAAAsC,CAAA,GAAA,EAFD,OAAM,+DAA8D,GAAA;QAC1F,SAAArC,QAAmB,CAAhBI,EAAAC,EAAAO,EAAA,MAAM,OAAO,GAAA,CAAA,C;;;OAElBT,EAOM,OAPNO,GAOM,CANJT,EAESK,GAAA;QAFD,MAAK;QAAU,SAASM,EAAA,MAAM,iBAAa;QAAc,SAAK,AAAAa,EAAA,QAAA,MAAEP,EAAM,EAAA;;QAC5E,SAAAlB,QAAsC,CAAnCI,EAAAC,EAAAO,EAAA,MAAM,eAAe0B,EAAA,WAAW,GAAA,CAAA,C;;O,oBAErCrC,EAESK,GAAA;QAFD,MAAK;QAAU,SAASM,EAAA,MAAM,kBAAc;QAAgB,SAAK,AAAAa,EAAA,QAAA,MAAEP,EAAM,EAAA;;QAC/E,SAAAlB,QAAwC,CAArCI,EAAAC,EAAAO,EAAA,MAAM,gBAAgB0B,EAAA,YAAY,GAAA,CAAA,C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Avatar.js","names":["_sfc_main","Avatar_vue_vue_type_script_setup_true_lang_default","Avatar_default"],"sources":["../../../src/components/Avatar/Avatar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport { type Hue, hueFor } from '../../utils/hues'\n\nexport interface AvatarProps {\n name?: string | null\n image?: string | null\n /** xs 16, sm 24, md 32, lg 40, xl 64; or a number of px, 20 for list rows and activity feeds. */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | number\n shape?: 'circle' | 'square'\n /** An attention dot, e.g. unread. */\n badge?: boolean\n /** Pins the colour when it means something; otherwise it comes from the name, stable per person. */\n hue?: Hue\n}\n\nconst props = withDefaults(defineProps<AvatarProps>(), {\n name: undefined,\n image: undefined,\n size: 'sm',\n shape: 'circle',\n hue: undefined\n})\n\n// One uppercased initial reads cleaner than two letters.\nconst initial = computed(() => (props.name || '?').trim().charAt(0).toUpperCase() || '?')\n\nconst sizes = {\n xs: 'h-4 w-4 text-10',\n sm: 'h-6 w-6 text-11',\n md: 'h-8 w-8 text-xs',\n lg: 'h-10 w-10 text-sm',\n xl: 'h-16 w-16 text-2xl'\n}\n\n// A soft coin of one hue: tinted fill, saturated text, a hairline of the hue.\nconst hues: Record<Hue, string> = {\n blue: 'border-sui-hue-blue-line bg-sui-hue-blue-soft text-sui-hue-blue-ink',\n green: 'border-sui-hue-green-line bg-sui-hue-green-soft text-sui-hue-green-ink',\n orange: 'border-sui-hue-orange-line bg-sui-hue-orange-soft text-sui-hue-orange-ink',\n pink: 'border-sui-hue-pink-line bg-sui-hue-pink-soft text-sui-hue-pink-ink',\n purple: 'border-sui-hue-purple-line bg-sui-hue-purple-soft text-sui-hue-purple-ink',\n slate: 'border-sui-hue-slate-line bg-sui-hue-slate-soft text-sui-hue-slate-ink',\n red: 'border-sui-hue-red-line bg-sui-hue-red-soft text-sui-hue-red-ink',\n amber: 'border-sui-hue-amber-line bg-sui-hue-amber-soft text-sui-hue-amber-ink',\n gray: 'border-sui-line
|
|
1
|
+
{"version":3,"file":"Avatar.js","names":["_sfc_main","Avatar_vue_vue_type_script_setup_true_lang_default","Avatar_default"],"sources":["../../../src/components/Avatar/Avatar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport { type Hue, hueFor } from '../../utils/hues'\n\nexport interface AvatarProps {\n name?: string | null\n image?: string | null\n /** xs 16, sm 24, md 32, lg 40, xl 64; or a number of px, 20 for list rows and activity feeds. */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | number\n shape?: 'circle' | 'square'\n /** An attention dot, e.g. unread. */\n badge?: boolean\n /** Pins the colour when it means something; otherwise it comes from the name, stable per person. */\n hue?: Hue\n}\n\nconst props = withDefaults(defineProps<AvatarProps>(), {\n name: undefined,\n image: undefined,\n size: 'sm',\n shape: 'circle',\n hue: undefined\n})\n\n// One uppercased initial reads cleaner than two letters.\nconst initial = computed(() => (props.name || '?').trim().charAt(0).toUpperCase() || '?')\n\nconst sizes = {\n xs: 'h-4 w-4 text-10',\n sm: 'h-6 w-6 text-11',\n md: 'h-8 w-8 text-xs',\n lg: 'h-10 w-10 text-sm',\n xl: 'h-16 w-16 text-2xl'\n}\n\n// A soft coin of one hue: tinted fill, saturated text, a hairline of the hue.\nconst hues: Record<Hue, string> = {\n blue: 'border-sui-hue-blue-line bg-sui-hue-blue-soft text-sui-hue-blue-ink',\n green: 'border-sui-hue-green-line bg-sui-hue-green-soft text-sui-hue-green-ink',\n orange: 'border-sui-hue-orange-line bg-sui-hue-orange-soft text-sui-hue-orange-ink',\n pink: 'border-sui-hue-pink-line bg-sui-hue-pink-soft text-sui-hue-pink-ink',\n purple: 'border-sui-hue-purple-line bg-sui-hue-purple-soft text-sui-hue-purple-ink',\n slate: 'border-sui-hue-slate-line bg-sui-hue-slate-soft text-sui-hue-slate-ink',\n red: 'border-sui-hue-red-line bg-sui-hue-red-soft text-sui-hue-red-ink',\n amber: 'border-sui-hue-amber-line bg-sui-hue-amber-soft text-sui-hue-amber-ink',\n gray: 'border-sui-line sui-band text-sui-ink-body'\n}\n\n// A number of px: the initial steps down with the coin.\nconst sizeClass = computed(() => {\n if (typeof props.size !== 'number') return sizes[props.size]\n if (props.size <= 20) return 'text-10'\n if (props.size <= 28) return 'text-11'\n return props.size <= 36 ? 'text-xs' : 'text-sm'\n})\nconst sizeStyle = computed(() =>\n typeof props.size === 'number' ? { width: `${props.size}px`, height: `${props.size}px` } : undefined\n)\n\nconst shapeClass = computed(() => (props.shape === 'square' ? 'rounded-lg' : 'rounded-full'))\n\n// A photo gets a neutral hairline, so it reads as a crisp coin too.\nconst colorClass = computed(() => (props.image ? 'border-sui-line-subtle' : hues[props.hue ?? hueFor(props.name)]))\n</script>\n\n<template>\n <div\n class=\"relative inline-flex shrink-0 items-center justify-center border font-semibold\"\n :class=\"[sizeClass, shapeClass, colorClass]\"\n :style=\"sizeStyle\"\n >\n <img v-if=\"image\" alt=\"\" class=\"h-full w-full object-cover\" :class=\"shapeClass\" :src=\"image\" />\n <template v-else>{{ initial }}</template>\n <span\n v-if=\"badge\"\n class=\"absolute -top-0.5 -right-0.5 h-2 w-2 rounded-full bg-sui-accent-solid ring-2 ring-sui-surface\"\n />\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -30,7 +30,7 @@ var d = ["src"], f = {
|
|
|
30
30
|
slate: "border-sui-hue-slate-line bg-sui-hue-slate-soft text-sui-hue-slate-ink",
|
|
31
31
|
red: "border-sui-hue-red-line bg-sui-hue-red-soft text-sui-hue-red-ink",
|
|
32
32
|
amber: "border-sui-hue-amber-line bg-sui-hue-amber-soft text-sui-hue-amber-ink",
|
|
33
|
-
gray: "border-sui-line
|
|
33
|
+
gray: "border-sui-line sui-band text-sui-ink-body"
|
|
34
34
|
}, _ = n(() => typeof p.size == "number" ? p.size <= 20 ? "text-10" : p.size <= 28 ? "text-11" : p.size <= 36 ? "text-xs" : "text-sm" : h[p.size]), v = n(() => typeof p.size == "number" ? {
|
|
35
35
|
width: `${p.size}px`,
|
|
36
36
|
height: `${p.size}px`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Avatar.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_normalizeClass","_normalizeStyle","_Fragment","_createTextVNode","_toDisplayString","_createCommentVNode","_hoisted_1","_hoisted_2","Avatar_vue_vue_type_script_setup_true_lang_default","props","__props","initial","computed","sizes","hues","sizeClass","sizeStyle","shapeClass","colorClass","hueFor","openBlock","createElementBlock","normalizeClass","normalizeStyle","Fragment","createTextVNode","toDisplayString","createCommentVNode"],"sources":["../../../src/components/Avatar/Avatar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport { type Hue, hueFor } from '../../utils/hues'\n\nexport interface AvatarProps {\n name?: string | null\n image?: string | null\n /** xs 16, sm 24, md 32, lg 40, xl 64; or a number of px, 20 for list rows and activity feeds. */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | number\n shape?: 'circle' | 'square'\n /** An attention dot, e.g. unread. */\n badge?: boolean\n /** Pins the colour when it means something; otherwise it comes from the name, stable per person. */\n hue?: Hue\n}\n\nconst props = withDefaults(defineProps<AvatarProps>(), {\n name: undefined,\n image: undefined,\n size: 'sm',\n shape: 'circle',\n hue: undefined\n})\n\n// One uppercased initial reads cleaner than two letters.\nconst initial = computed(() => (props.name || '?').trim().charAt(0).toUpperCase() || '?')\n\nconst sizes = {\n xs: 'h-4 w-4 text-10',\n sm: 'h-6 w-6 text-11',\n md: 'h-8 w-8 text-xs',\n lg: 'h-10 w-10 text-sm',\n xl: 'h-16 w-16 text-2xl'\n}\n\n// A soft coin of one hue: tinted fill, saturated text, a hairline of the hue.\nconst hues: Record<Hue, string> = {\n blue: 'border-sui-hue-blue-line bg-sui-hue-blue-soft text-sui-hue-blue-ink',\n green: 'border-sui-hue-green-line bg-sui-hue-green-soft text-sui-hue-green-ink',\n orange: 'border-sui-hue-orange-line bg-sui-hue-orange-soft text-sui-hue-orange-ink',\n pink: 'border-sui-hue-pink-line bg-sui-hue-pink-soft text-sui-hue-pink-ink',\n purple: 'border-sui-hue-purple-line bg-sui-hue-purple-soft text-sui-hue-purple-ink',\n slate: 'border-sui-hue-slate-line bg-sui-hue-slate-soft text-sui-hue-slate-ink',\n red: 'border-sui-hue-red-line bg-sui-hue-red-soft text-sui-hue-red-ink',\n amber: 'border-sui-hue-amber-line bg-sui-hue-amber-soft text-sui-hue-amber-ink',\n gray: 'border-sui-line
|
|
1
|
+
{"version":3,"file":"Avatar.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_normalizeClass","_normalizeStyle","_Fragment","_createTextVNode","_toDisplayString","_createCommentVNode","_hoisted_1","_hoisted_2","Avatar_vue_vue_type_script_setup_true_lang_default","props","__props","initial","computed","sizes","hues","sizeClass","sizeStyle","shapeClass","colorClass","hueFor","openBlock","createElementBlock","normalizeClass","normalizeStyle","Fragment","createTextVNode","toDisplayString","createCommentVNode"],"sources":["../../../src/components/Avatar/Avatar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport { type Hue, hueFor } from '../../utils/hues'\n\nexport interface AvatarProps {\n name?: string | null\n image?: string | null\n /** xs 16, sm 24, md 32, lg 40, xl 64; or a number of px, 20 for list rows and activity feeds. */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | number\n shape?: 'circle' | 'square'\n /** An attention dot, e.g. unread. */\n badge?: boolean\n /** Pins the colour when it means something; otherwise it comes from the name, stable per person. */\n hue?: Hue\n}\n\nconst props = withDefaults(defineProps<AvatarProps>(), {\n name: undefined,\n image: undefined,\n size: 'sm',\n shape: 'circle',\n hue: undefined\n})\n\n// One uppercased initial reads cleaner than two letters.\nconst initial = computed(() => (props.name || '?').trim().charAt(0).toUpperCase() || '?')\n\nconst sizes = {\n xs: 'h-4 w-4 text-10',\n sm: 'h-6 w-6 text-11',\n md: 'h-8 w-8 text-xs',\n lg: 'h-10 w-10 text-sm',\n xl: 'h-16 w-16 text-2xl'\n}\n\n// A soft coin of one hue: tinted fill, saturated text, a hairline of the hue.\nconst hues: Record<Hue, string> = {\n blue: 'border-sui-hue-blue-line bg-sui-hue-blue-soft text-sui-hue-blue-ink',\n green: 'border-sui-hue-green-line bg-sui-hue-green-soft text-sui-hue-green-ink',\n orange: 'border-sui-hue-orange-line bg-sui-hue-orange-soft text-sui-hue-orange-ink',\n pink: 'border-sui-hue-pink-line bg-sui-hue-pink-soft text-sui-hue-pink-ink',\n purple: 'border-sui-hue-purple-line bg-sui-hue-purple-soft text-sui-hue-purple-ink',\n slate: 'border-sui-hue-slate-line bg-sui-hue-slate-soft text-sui-hue-slate-ink',\n red: 'border-sui-hue-red-line bg-sui-hue-red-soft text-sui-hue-red-ink',\n amber: 'border-sui-hue-amber-line bg-sui-hue-amber-soft text-sui-hue-amber-ink',\n gray: 'border-sui-line sui-band text-sui-ink-body'\n}\n\n// A number of px: the initial steps down with the coin.\nconst sizeClass = computed(() => {\n if (typeof props.size !== 'number') return sizes[props.size]\n if (props.size <= 20) return 'text-10'\n if (props.size <= 28) return 'text-11'\n return props.size <= 36 ? 'text-xs' : 'text-sm'\n})\nconst sizeStyle = computed(() =>\n typeof props.size === 'number' ? { width: `${props.size}px`, height: `${props.size}px` } : undefined\n)\n\nconst shapeClass = computed(() => (props.shape === 'square' ? 'rounded-lg' : 'rounded-full'))\n\n// A photo gets a neutral hairline, so it reads as a crisp coin too.\nconst colorClass = computed(() => (props.image ? 'border-sui-line-subtle' : hues[props.hue ?? hueFor(props.name)]))\n</script>\n\n<template>\n <div\n class=\"relative inline-flex shrink-0 items-center justify-center border font-semibold\"\n :class=\"[sizeClass, shapeClass, colorClass]\"\n :style=\"sizeStyle\"\n >\n <img v-if=\"image\" alt=\"\" class=\"h-full w-full object-cover\" :class=\"shapeClass\" :src=\"image\" />\n <template v-else>{{ initial }}</template>\n <span\n v-if=\"badge\"\n class=\"absolute -top-0.5 -right-0.5 h-2 w-2 rounded-full bg-sui-accent-solid ring-2 ring-sui-surface\"\n />\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;EAiBA,IAAMW,IAAQC,GASRC,IAAUC,SAAgBH,EAAM,QAAQ,IAAA,CAAK,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,KAAK,GAAG,GAElFI,IAAQ;GACZ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN,GAGMC,IAA4B;GAChC,MAAM;GACN,OAAO;GACP,QAAQ;GACR,MAAM;GACN,QAAQ;GACR,OAAO;GACP,KAAK;GACL,OAAO;GACP,MAAM;EACR,GAGMC,IAAYH,QACZ,OAAOH,EAAM,QAAS,WACtBA,EAAM,QAAQ,KAAW,YACzBA,EAAM,QAAQ,KAAW,YACtBA,EAAM,QAAQ,KAAK,YAAY,YAHKI,EAAMJ,EAAM,KAIxD,GACKO,IAAYJ,QAChB,OAAOH,EAAM,QAAS,WAAW;GAAE,OAAO,GAAGA,EAAM,KAAK;GAAK,QAAQ,GAAGA,EAAM,KAAK;EAAI,IAAI,KAAA,CAC7F,GAEMQ,IAAaL,QAAgBH,EAAM,UAAU,WAAW,eAAe,cAAe,GAGtFS,IAAaN,QAAgBH,EAAM,QAAQ,2BAA2BK,EAAKL,EAAM,OAAOU,EAAOV,EAAM,IAAI,EAAG;E,kBAIhHX,EAAA,GAAAC,EAWM,OAAA;GAVJ,OAAKC,EAAA,CAAC,kFAAgF;IAC7Ee,EAAA;IAAWE,EAAA;IAAYC,EAAA;GAAU,CAAA,CAAA;GACzC,OAAKjB,EAAEe,EAAA,KAAS;E,IAENN,EAAA,SAAXZ,EAAA,GAAAC,EAA+F,OAAA;;GAA7E,KAAI;GAAG,OAAKC,EAAA,CAAC,8BAAqCiB,EAAA,KAAU,CAAA;GAAG,KAAKP,EAAA;E,oBACtFZ,EAAA,GAAAC,EAAyCG,GAAA,EAAA,KAAA,EAAA,GAAA,CAArBC,EAAAC,EAAAO,EAAA,KAAO,GAAA,CAAA,C,SAEnBD,EAAA,SADRZ,EAAA,GAAAC,EAGE,QAHFQ,CAGE,K"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Badge.js","names":["_sfc_main","Badge_vue_vue_type_script_setup_true_lang_default","Badge_default"],"sources":["../../../src/components/Badge/Badge.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nexport type BadgeTone = 'neutral' | 'accent' | 'success' | 'warning' | 'info' | 'danger'\n\nexport interface BadgeProps {\n tone?: BadgeTone\n /**\n * `soft` is a tinted chip; `text` is a dot and a coloured label, lighter; `outline` is a small\n * neutral pill (the dot carries the tone) for a count that isn't the page's own.\n */\n variant?: 'soft' | 'text' | 'outline'\n dot?: boolean\n label?: string\n}\n\nconst props = withDefaults(defineProps<BadgeProps>(), { tone: 'neutral', variant: 'soft', dot: true, label: undefined })\n\nconst tones: Record<BadgeTone, { chip: string; text: string; dot: string }> = {\n neutral: { chip: 'bg-sui-
|
|
1
|
+
{"version":3,"file":"Badge.js","names":["_sfc_main","Badge_vue_vue_type_script_setup_true_lang_default","Badge_default"],"sources":["../../../src/components/Badge/Badge.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nexport type BadgeTone = 'neutral' | 'accent' | 'success' | 'warning' | 'info' | 'danger'\n\nexport interface BadgeProps {\n tone?: BadgeTone\n /**\n * `soft` is a tinted chip; `text` is a dot and a coloured label, lighter; `outline` is a small\n * neutral pill (the dot carries the tone) for a count that isn't the page's own.\n */\n variant?: 'soft' | 'text' | 'outline'\n dot?: boolean\n label?: string\n}\n\nconst props = withDefaults(defineProps<BadgeProps>(), { tone: 'neutral', variant: 'soft', dot: true, label: undefined })\n\nconst tones: Record<BadgeTone, { chip: string; text: string; dot: string }> = {\n neutral: { chip: 'bg-sui-fill text-sui-ink-subtle', text: 'text-sui-ink-muted', dot: 'bg-sui-mark-faint' },\n accent: { chip: 'bg-sui-accent-wash text-sui-accent', text: 'text-sui-accent', dot: 'bg-sui-accent-solid' },\n success: {\n chip: 'bg-sui-success-soft text-sui-success',\n text: 'text-sui-success',\n dot: 'bg-sui-success-mid'\n },\n warning: {\n chip: 'bg-sui-warning-soft text-sui-warning',\n text: 'text-sui-warning',\n dot: 'bg-sui-warning-bright'\n },\n info: { chip: 'bg-sui-info-soft text-sui-info', text: 'text-sui-info', dot: 'bg-sui-info-mid' },\n danger: { chip: 'bg-sui-danger-soft text-sui-danger', text: 'text-sui-danger', dot: 'bg-sui-danger-solid' }\n}\n\nconst tone = computed(() => tones[props.tone])\n\nconst shape = computed(() => {\n if (props.variant === 'soft') return ['h-6 gap-1.5 rounded-md px-2.5 text-xs font-medium', tone.value.chip]\n if (props.variant === 'outline')\n return 'h-5 gap-1.25 rounded-full border border-sui-line bg-sui-surface pr-1.75 pl-1.5 text-11.5 leading-none font-semibold text-sui-ink-emphasis tabular-nums'\n return ['gap-1.5 text-xs font-medium', tone.value.text]\n})\n</script>\n\n<template>\n <span class=\"inline-flex items-center whitespace-nowrap\" :class=\"shape\">\n <span v-if=\"dot\" class=\"h-1.5 w-1.5 shrink-0 rounded-full\" :class=\"tone.dot\" />\n <slot>{{ label }}</slot>\n </span>\n</template>\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Badge.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_normalizeClass","_createCommentVNode","_renderSlot","_createTextVNode","_toDisplayString","Badge_vue_vue_type_script_setup_true_lang_default","props","__props","tones","tone","computed","shape","openBlock","createElementBlock","normalizeClass","createCommentVNode","renderSlot","_ctx","createTextVNode","toDisplayString"],"sources":["../../../src/components/Badge/Badge.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nexport type BadgeTone = 'neutral' | 'accent' | 'success' | 'warning' | 'info' | 'danger'\n\nexport interface BadgeProps {\n tone?: BadgeTone\n /**\n * `soft` is a tinted chip; `text` is a dot and a coloured label, lighter; `outline` is a small\n * neutral pill (the dot carries the tone) for a count that isn't the page's own.\n */\n variant?: 'soft' | 'text' | 'outline'\n dot?: boolean\n label?: string\n}\n\nconst props = withDefaults(defineProps<BadgeProps>(), { tone: 'neutral', variant: 'soft', dot: true, label: undefined })\n\nconst tones: Record<BadgeTone, { chip: string; text: string; dot: string }> = {\n neutral: { chip: 'bg-sui-
|
|
1
|
+
{"version":3,"file":"Badge.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_normalizeClass","_createCommentVNode","_renderSlot","_createTextVNode","_toDisplayString","Badge_vue_vue_type_script_setup_true_lang_default","props","__props","tones","tone","computed","shape","openBlock","createElementBlock","normalizeClass","createCommentVNode","renderSlot","_ctx","createTextVNode","toDisplayString"],"sources":["../../../src/components/Badge/Badge.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nexport type BadgeTone = 'neutral' | 'accent' | 'success' | 'warning' | 'info' | 'danger'\n\nexport interface BadgeProps {\n tone?: BadgeTone\n /**\n * `soft` is a tinted chip; `text` is a dot and a coloured label, lighter; `outline` is a small\n * neutral pill (the dot carries the tone) for a count that isn't the page's own.\n */\n variant?: 'soft' | 'text' | 'outline'\n dot?: boolean\n label?: string\n}\n\nconst props = withDefaults(defineProps<BadgeProps>(), { tone: 'neutral', variant: 'soft', dot: true, label: undefined })\n\nconst tones: Record<BadgeTone, { chip: string; text: string; dot: string }> = {\n neutral: { chip: 'bg-sui-fill text-sui-ink-subtle', text: 'text-sui-ink-muted', dot: 'bg-sui-mark-faint' },\n accent: { chip: 'bg-sui-accent-wash text-sui-accent', text: 'text-sui-accent', dot: 'bg-sui-accent-solid' },\n success: {\n chip: 'bg-sui-success-soft text-sui-success',\n text: 'text-sui-success',\n dot: 'bg-sui-success-mid'\n },\n warning: {\n chip: 'bg-sui-warning-soft text-sui-warning',\n text: 'text-sui-warning',\n dot: 'bg-sui-warning-bright'\n },\n info: { chip: 'bg-sui-info-soft text-sui-info', text: 'text-sui-info', dot: 'bg-sui-info-mid' },\n danger: { chip: 'bg-sui-danger-soft text-sui-danger', text: 'text-sui-danger', dot: 'bg-sui-danger-solid' }\n}\n\nconst tone = computed(() => tones[props.tone])\n\nconst shape = computed(() => {\n if (props.variant === 'soft') return ['h-6 gap-1.5 rounded-md px-2.5 text-xs font-medium', tone.value.chip]\n if (props.variant === 'outline')\n return 'h-5 gap-1.25 rounded-full border border-sui-line bg-sui-surface pr-1.75 pl-1.5 text-11.5 leading-none font-semibold text-sui-ink-emphasis tabular-nums'\n return ['gap-1.5 text-xs font-medium', tone.value.text]\n})\n</script>\n\n<template>\n <span class=\"inline-flex items-center whitespace-nowrap\" :class=\"shape\">\n <span v-if=\"dot\" class=\"h-1.5 w-1.5 shrink-0 rounded-full\" :class=\"tone.dot\" />\n <slot>{{ label }}</slot>\n </span>\n</template>\n"],"mappings":";;;;;;;;;;;;;;EAgBA,IAAMQ,IAAQC,GAERC,IAAwE;GAC5E,SAAS;IAAE,MAAM;IAAmC,MAAM;IAAsB,KAAK;GAAoB;GACzG,QAAQ;IAAE,MAAM;IAAsC,MAAM;IAAmB,KAAK;GAAsB;GAC1G,SAAS;IACP,MAAM;IACN,MAAM;IACN,KAAK;GACP;GACA,SAAS;IACP,MAAM;IACN,MAAM;IACN,KAAK;GACP;GACA,MAAM;IAAE,MAAM;IAAkC,MAAM;IAAiB,KAAK;GAAkB;GAC9F,QAAQ;IAAE,MAAM;IAAsC,MAAM;IAAmB,KAAK;GAAsB;EAC5G,GAEMC,IAAOC,QAAeF,EAAMF,EAAM,KAAK,GAEvCK,IAAQD,QACRJ,EAAM,YAAY,SAAe,CAAC,qDAAqDG,EAAK,MAAM,IAAI,IACtGH,EAAM,YAAY,YACb,2JACF,CAAC,+BAA+BG,EAAK,MAAM,IAAI,CACvD;E,kBAICX,EAAA,GAAAC,EAGO,QAAA,EAHD,OAAKC,EAAA,CAAC,8CAAqDW,EAAA,KAAK,CAAA,E,IACxDJ,EAAA,OAAZT,EAAA,GAAAC,EAA+E,QAAA;;GAA9D,OAAKC,EAAA,CAAC,qCAA4CS,EAAA,MAAK,GAAG,CAAA;E,0BAC3EP,EAAwBe,EAAA,QAAA,WAAA,CAAA,SAAA,CAAfd,EAAAC,EAAAG,EAAA,KAAK,GAAA,CAAA,C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Board.js","names":["_sfc_main","Board_vue_vue_type_script_setup_true_lang_default","Board_default"],"sources":["../../../src/components/Board/Board.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"T extends Record<string, any>\">\nimport { onBeforeUnmount, ref, useId } from 'vue'\n\nimport Icon from '../Icon/Icon.vue'\nimport Skeleton from '../Skeleton/Skeleton.vue'\nimport type { BoardColumn } from './types'\n\nexport interface BoardProps<T> {\n columns: BoardColumn<T>[]\n /** The item field that identifies it. */\n rowKey?: keyof T & string\n /** Cards also reorder within a column, for records that carry a position. */\n sortable?: boolean\n /** Columns run to the bottom of the parent and scroll inside it; give the parent a height. False sizes them to their cards. */\n fill?: boolean\n loading?: boolean\n /** The columns' heading level, to fit the page's outline. */\n headingLevel?: 2 | 3 | 4 | 5 | 6\n /** Draws each card's border, padding and surface. False when the `card` slot draws its own. */\n cardFrame?: boolean\n /** Makes a card a button that opens on click, Enter and Space (`@card-click`). Without it, the card slot carries its\n * own link or buttons. */\n onCardClick?: (item: T) => void\n /** Adds a dashed \"New\" button at the foot of each column, shown on hover (`@new`). */\n onNew?: (column: BoardColumn<T>) => void\n newLabel?: string\n emptyLabel?: string\n}\n\nconst props = withDefaults(defineProps<BoardProps<T>>(), {\n rowKey: 'id' as never,\n fill: true,\n headingLevel: 3,\n cardFrame: true,\n onCardClick: undefined,\n onNew: undefined,\n newLabel: 'New',\n emptyLabel: 'No cards'\n})\n\nconst emit = defineEmits<{\n /** A card dropped into a column, at its new index there. Show it moved at once; put it back if saving fails. */\n move: [id: unknown, column: string, index: number]\n}>()\n\ndefineSlots<{\n /** A card's content; `item.name` as a title by default. */\n card?: (props: { item: T; column: BoardColumn<T> }) => unknown\n /** Replaces a column's count, e.g. its summed deal value. */\n count?: (props: { column: BoardColumn<T> }) => unknown\n}>()\n\nconst id = useId()\nconst idOf = (item: T): unknown => item[props.rowKey ?? 'id']\nconst root = ref<HTMLElement>()\n\nconst dragged = ref<{ id: unknown; column: string; index: number } | null>(null)\nconst target = ref<{ column: string; index: number } | null>(null)\n\n// Dragging runs on pointer events, so it works with a mouse, a pen and a finger. A mouse drags once it moves a few\n// pixels, so a click still clicks; a finger after a short press, so a swipe still scrolls.\nconst MOUSE_SLOP = 4\nconst TOUCH_SLOP = 8\nconst TOUCH_DELAY = 250\nconst EDGE = 48\n\nlet pending: {\n item: T\n column: string\n index: number\n x: number\n y: number\n card: HTMLElement\n touch: boolean\n} | null = null\nlet pressTimer: number | undefined\nlet ghost: HTMLElement | null = null\nlet grab = { x: 0, y: 0 }\nlet justDragged = false\n\nfunction onPointerDown(event: PointerEvent, item: T, column: string, index: number) {\n if (event.button !== 0 || (event.target as HTMLElement).closest('input, textarea, select, [contenteditable]')) return\n const touch = event.pointerType === 'touch'\n pending = { item, column, index, x: event.clientX, y: event.clientY, card: event.currentTarget as HTMLElement, touch }\n if (touch) pressTimer = window.setTimeout(() => pending && start(), TOUCH_DELAY)\n window.addEventListener('pointermove', onPointerMove)\n window.addEventListener('pointerup', onPointerUp)\n window.addEventListener('pointercancel', stop)\n window.addEventListener('touchmove', holdScroll, { passive: false })\n window.addEventListener('keydown', onEscape)\n}\n\nfunction start() {\n if (!pending) return\n const rect = pending.card.getBoundingClientRect()\n grab = { x: pending.x - rect.left, y: pending.y - rect.top }\n ghost = pending.card.cloneNode(true) as HTMLElement\n ghost.removeAttribute('id')\n ghost.setAttribute('aria-hidden', 'true')\n ghost.classList.add('pointer-events-none', 'fixed', 'top-0', 'left-0', 'z-[1300]', 'shadow-lg', 'opacity-95')\n ghost.style.width = `${rect.width}px`\n document.body.appendChild(ghost)\n follow(pending.x, pending.y)\n dragged.value = { id: idOf(pending.item), column: pending.column, index: pending.index }\n}\n\nfunction onPointerMove(event: PointerEvent) {\n if (!pending) return\n if (!dragged.value) {\n const moved = Math.hypot(event.clientX - pending.x, event.clientY - pending.y)\n // A finger that moves before the press is long enough is scrolling.\n if (pending.touch) return moved > TOUCH_SLOP ? stop() : undefined\n if (moved < MOUSE_SLOP) return\n start()\n }\n event.preventDefault()\n follow(event.clientX, event.clientY)\n aim(event.clientX, event.clientY)\n scrollNear(event.clientX, event.clientY)\n}\n\nfunction follow(x: number, y: number) {\n if (ghost) ghost.style.transform = `translate(${x - grab.x}px, ${y - grab.y}px) rotate(1.5deg)`\n}\n\n// What's under the pointer: a card's top half drops before it, the bottom half after; an empty spot, at the end.\nfunction aim(x: number, y: number) {\n const under = document.elementFromPoint(x, y)\n const body = under?.closest<HTMLElement>('[data-board-column]')\n if (!body || !root.value?.contains(body)) {\n target.value = null\n return\n }\n const column = body.dataset.boardColumn!\n const card = under!.closest<HTMLElement>('[data-board-index]')\n let index = props.columns.find((c) => c.id === column)?.items.length ?? 0\n if (card && body.contains(card)) {\n const rect = card.getBoundingClientRect()\n index = Number(card.dataset.boardIndex) + (y < rect.top + rect.height / 2 ? 0 : 1)\n }\n if (target.value?.column !== column || target.value.index !== index) target.value = { column, index }\n}\n\n// Near a column's top or bottom, or the board's sides, it scrolls that way.\nfunction scrollNear(x: number, y: number) {\n const body = document.elementFromPoint(x, y)?.closest<HTMLElement>('[data-board-column]')\n if (body) {\n const rect = body.getBoundingClientRect()\n if (y < rect.top + EDGE) body.scrollTop -= 12\n else if (y > rect.bottom - EDGE) body.scrollTop += 12\n }\n const board = root.value?.getBoundingClientRect()\n if (board && root.value) {\n if (x < board.left + EDGE) root.value.scrollLeft -= 12\n else if (x > board.right - EDGE) root.value.scrollLeft += 12\n }\n}\n\nfunction onPointerUp() {\n const from = dragged.value\n const to = target.value\n if (from && to) {\n let index = to.index\n if (from.column === to.column) {\n // Within a column the dragged card leaves its old slot first.\n if (index > from.index) index--\n if (props.sortable && index !== from.index) emit('move', from.id, to.column, index)\n } else {\n emit('move', from.id, to.column, index)\n }\n }\n stop()\n}\n\nfunction holdScroll(event: TouchEvent) {\n if (dragged.value) event.preventDefault()\n}\n\nfunction onEscape(event: KeyboardEvent) {\n if (event.key === 'Escape' && dragged.value) {\n event.preventDefault()\n stop()\n }\n}\n\nfunction stop() {\n window.clearTimeout(pressTimer)\n window.removeEventListener('pointermove', onPointerMove)\n window.removeEventListener('pointerup', onPointerUp)\n window.removeEventListener('pointercancel', stop)\n window.removeEventListener('touchmove', holdScroll)\n window.removeEventListener('keydown', onEscape)\n ghost?.remove()\n ghost = null\n // The click that ends a drag isn't a click on the card.\n if (dragged.value) {\n justDragged = true\n window.setTimeout(() => (justDragged = false))\n }\n pending = null\n dragged.value = null\n target.value = null\n}\n\nonBeforeUnmount(stop)\n\nfunction clickCard(event: MouseEvent, item: T) {\n if (justDragged) {\n event.preventDefault()\n event.stopPropagation()\n return\n }\n props.onCardClick?.(item)\n}\n\nfunction onCardKeydown(event: KeyboardEvent, item: T) {\n if (!props.onCardClick || event.target !== event.currentTarget || (event.key !== 'Enter' && event.key !== ' ')) return\n event.preventDefault()\n props.onCardClick(item)\n}\n\nconst isTarget = (column: string, index: number, item: T) =>\n target.value?.column === column && target.value.index === index && dragged.value?.id !== idOf(item)\n\nconst frame =\n 'border border-sui-line-subtle bg-sui-surface p-4 transition-[border-color,opacity] duration-150 hover:border-sui-line'\n</script>\n\n<!-- A board: cards in columns by a field (a stage, a status), dragged between columns. -->\n<template>\n <div\n ref=\"root\"\n class=\"flex items-stretch gap-5 overflow-x-auto pb-2 after:w-1 after:shrink-0 after:content-['']\"\n :class=\"fill && 'h-full min-h-0 flex-1'\"\n >\n <section\n v-for=\"column in columns\"\n :key=\"column.id\"\n :aria-labelledby=\"`${id}-${column.id}`\"\n class=\"flex min-h-0 w-full max-w-xs min-w-[16rem] shrink-0 flex-col\"\n >\n <header class=\"flex items-center justify-between px-1 pb-2.5\">\n <component\n :is=\"`h${headingLevel}`\"\n :id=\"`${id}-${column.id}`\"\n class=\"m-0 flex items-center gap-2 text-sm font-semibold text-sui-ink\"\n >\n <Icon v-if=\"column.icon\" :color=\"column.iconColor ?? 'ink-subtle'\" :name=\"column.icon\" />\n {{ column.name }}\n </component>\n <span\n class=\"ml-2 inline-flex h-5 items-center justify-center rounded-full bg-sui-sunken px-2 text-xs text-sui-ink-muted tabular-nums\"\n >\n <slot :column=\"column\" name=\"count\">{{ column.items.length }}</slot>\n </span>\n </header>\n <div\n class=\"group/body flex min-h-[120px] flex-1 flex-col gap-2.5 overflow-y-auto rounded-xl bg-sui-sunken p-2.5 transition-shadow duration-150\"\n :class=\"target?.column === column.id && 'ring-2 ring-sui-accent-line ring-inset'\"\n :data-board-column=\"column.id\"\n >\n <template v-if=\"loading\">\n <div\n v-for=\"i in 3\"\n :key=\"i\"\n aria-hidden=\"true\"\n class=\"rounded-xl border border-sui-line-subtle bg-sui-surface p-4\"\n >\n <Skeleton class=\"mb-3\" />\n <Skeleton height=\"0.75rem\" width=\"70%\" />\n </div>\n </template>\n <p\n v-else-if=\"column.items.length === 0 && !dragged\"\n class=\"m-0 px-1 py-3 text-center text-13 text-sui-ink-muted\"\n >\n {{ emptyLabel }}\n </p>\n <ul v-else class=\"m-0 flex list-none flex-col gap-2.5 p-0\">\n <li v-for=\"(item, index) in column.items\" :key=\"idOf(item) as PropertyKey\">\n <div\n class=\"relative rounded-xl outline-hidden transition-opacity duration-150 select-none\"\n :class=\"[\n cardFrame && frame,\n onCardClick && 'cursor-pointer focus-visible:sui-ring',\n dragged?.id === idOf(item) && 'opacity-40',\n isTarget(column.id, index, item) && 'shadow-[0_-6px_0_-4px_rgb(var(--sui-accent-solid))]'\n ]\"\n :data-board-index=\"index\"\n :role=\"onCardClick ? 'button' : undefined\"\n :tabindex=\"onCardClick ? 0 : undefined\"\n @click.capture=\"clickCard($event, item)\"\n @contextmenu=\"dragged && $event.preventDefault()\"\n @dragstart.prevent\n @keydown=\"onCardKeydown($event, item)\"\n @pointerdown=\"onPointerDown($event, item, column.id, index)\"\n >\n <slot :column=\"column\" :item=\"item\" name=\"card\">\n <p class=\"m-0 text-sm font-semibold text-sui-ink\">{{ item.name }}</p>\n </slot>\n </div>\n </li>\n </ul>\n <button\n v-if=\"onNew && !loading\"\n class=\"flex h-9 w-full shrink-0 items-center justify-center gap-1.5 rounded-lg border border-dashed border-sui-line-strong text-xs font-medium text-sui-ink-muted opacity-0 outline-hidden transition-all duration-150 group-hover/body:opacity-100 hover:border-sui-ink-muted hover:bg-sui-surface/60 hover:text-sui-ink-body focus-visible:opacity-100 focus-visible:sui-ring\"\n type=\"button\"\n @click=\"onNew(column)\"\n >\n <svg\n aria-hidden=\"true\"\n class=\"size-3.5 fill-none stroke-current\"\n stroke-linecap=\"round\"\n stroke-width=\"1.5\"\n viewBox=\"0 0 14 14\"\n >\n <path d=\"M7 2.5v9M2.5 7h9\" />\n </svg>\n {{ newLabel }}\n </button>\n </div>\n </section>\n </div>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"Board.js","names":["_sfc_main","Board_vue_vue_type_script_setup_true_lang_default","Board_default"],"sources":["../../../src/components/Board/Board.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"T extends Record<string, any>\">\nimport { onBeforeUnmount, ref, useId } from 'vue'\n\nimport Icon from '../Icon/Icon.vue'\nimport Skeleton from '../Skeleton/Skeleton.vue'\nimport type { BoardColumn } from './types'\n\nexport interface BoardProps<T> {\n columns: BoardColumn<T>[]\n /** The item field that identifies it. */\n rowKey?: keyof T & string\n /** Cards also reorder within a column, for records that carry a position. */\n sortable?: boolean\n /** Columns run to the bottom of the parent and scroll inside it; give the parent a height. False sizes them to their cards. */\n fill?: boolean\n loading?: boolean\n /** The columns' heading level, to fit the page's outline. */\n headingLevel?: 2 | 3 | 4 | 5 | 6\n /** Draws each card's border, padding and surface. False when the `card` slot draws its own. */\n cardFrame?: boolean\n /** Makes a card a button that opens on click, Enter and Space (`@card-click`). Without it, the card slot carries its\n * own link or buttons. */\n onCardClick?: (item: T) => void\n /** Adds a dashed \"New\" button at the foot of each column, shown on hover (`@new`). */\n onNew?: (column: BoardColumn<T>) => void\n newLabel?: string\n emptyLabel?: string\n}\n\nconst props = withDefaults(defineProps<BoardProps<T>>(), {\n rowKey: 'id' as never,\n fill: true,\n headingLevel: 3,\n cardFrame: true,\n onCardClick: undefined,\n onNew: undefined,\n newLabel: 'New',\n emptyLabel: 'No cards'\n})\n\nconst emit = defineEmits<{\n /** A card dropped into a column, at its new index there. Show it moved at once; put it back if saving fails. */\n move: [id: unknown, column: string, index: number]\n}>()\n\ndefineSlots<{\n /** A card's content; `item.name` as a title by default. */\n card?: (props: { item: T; column: BoardColumn<T> }) => unknown\n /** Replaces a column's count, e.g. its summed deal value. */\n count?: (props: { column: BoardColumn<T> }) => unknown\n}>()\n\nconst id = useId()\nconst idOf = (item: T): unknown => item[props.rowKey ?? 'id']\nconst root = ref<HTMLElement>()\n\nconst dragged = ref<{ id: unknown; column: string; index: number } | null>(null)\nconst target = ref<{ column: string; index: number } | null>(null)\n\n// Dragging runs on pointer events, so it works with a mouse, a pen and a finger. A mouse drags once it moves a few\n// pixels, so a click still clicks; a finger after a short press, so a swipe still scrolls.\nconst MOUSE_SLOP = 4\nconst TOUCH_SLOP = 8\nconst TOUCH_DELAY = 250\nconst EDGE = 48\n\nlet pending: {\n item: T\n column: string\n index: number\n x: number\n y: number\n card: HTMLElement\n touch: boolean\n} | null = null\nlet pressTimer: number | undefined\nlet ghost: HTMLElement | null = null\nlet grab = { x: 0, y: 0 }\nlet justDragged = false\n\nfunction onPointerDown(event: PointerEvent, item: T, column: string, index: number) {\n if (event.button !== 0 || (event.target as HTMLElement).closest('input, textarea, select, [contenteditable]')) return\n const touch = event.pointerType === 'touch'\n pending = { item, column, index, x: event.clientX, y: event.clientY, card: event.currentTarget as HTMLElement, touch }\n if (touch) pressTimer = window.setTimeout(() => pending && start(), TOUCH_DELAY)\n window.addEventListener('pointermove', onPointerMove)\n window.addEventListener('pointerup', onPointerUp)\n window.addEventListener('pointercancel', stop)\n window.addEventListener('touchmove', holdScroll, { passive: false })\n window.addEventListener('keydown', onEscape)\n}\n\nfunction start() {\n if (!pending) return\n const rect = pending.card.getBoundingClientRect()\n grab = { x: pending.x - rect.left, y: pending.y - rect.top }\n ghost = pending.card.cloneNode(true) as HTMLElement\n ghost.removeAttribute('id')\n ghost.setAttribute('aria-hidden', 'true')\n ghost.classList.add('pointer-events-none', 'fixed', 'top-0', 'left-0', 'z-[1300]', 'shadow-lg', 'opacity-95')\n ghost.style.width = `${rect.width}px`\n document.body.appendChild(ghost)\n follow(pending.x, pending.y)\n dragged.value = { id: idOf(pending.item), column: pending.column, index: pending.index }\n}\n\nfunction onPointerMove(event: PointerEvent) {\n if (!pending) return\n if (!dragged.value) {\n const moved = Math.hypot(event.clientX - pending.x, event.clientY - pending.y)\n // A finger that moves before the press is long enough is scrolling.\n if (pending.touch) return moved > TOUCH_SLOP ? stop() : undefined\n if (moved < MOUSE_SLOP) return\n start()\n }\n event.preventDefault()\n follow(event.clientX, event.clientY)\n aim(event.clientX, event.clientY)\n scrollNear(event.clientX, event.clientY)\n}\n\nfunction follow(x: number, y: number) {\n if (ghost) ghost.style.transform = `translate(${x - grab.x}px, ${y - grab.y}px) rotate(1.5deg)`\n}\n\n// What's under the pointer: a card's top half drops before it, the bottom half after; an empty spot, at the end.\nfunction aim(x: number, y: number) {\n const under = document.elementFromPoint(x, y)\n const body = under?.closest<HTMLElement>('[data-board-column]')\n if (!body || !root.value?.contains(body)) {\n target.value = null\n return\n }\n const column = body.dataset.boardColumn!\n const card = under!.closest<HTMLElement>('[data-board-index]')\n let index = props.columns.find((c) => c.id === column)?.items.length ?? 0\n if (card && body.contains(card)) {\n const rect = card.getBoundingClientRect()\n index = Number(card.dataset.boardIndex) + (y < rect.top + rect.height / 2 ? 0 : 1)\n }\n if (target.value?.column !== column || target.value.index !== index) target.value = { column, index }\n}\n\n// Near a column's top or bottom, or the board's sides, it scrolls that way.\nfunction scrollNear(x: number, y: number) {\n const body = document.elementFromPoint(x, y)?.closest<HTMLElement>('[data-board-column]')\n if (body) {\n const rect = body.getBoundingClientRect()\n if (y < rect.top + EDGE) body.scrollTop -= 12\n else if (y > rect.bottom - EDGE) body.scrollTop += 12\n }\n const board = root.value?.getBoundingClientRect()\n if (board && root.value) {\n if (x < board.left + EDGE) root.value.scrollLeft -= 12\n else if (x > board.right - EDGE) root.value.scrollLeft += 12\n }\n}\n\nfunction onPointerUp() {\n const from = dragged.value\n const to = target.value\n if (from && to) {\n let index = to.index\n if (from.column === to.column) {\n // Within a column the dragged card leaves its old slot first.\n if (index > from.index) index--\n if (props.sortable && index !== from.index) emit('move', from.id, to.column, index)\n } else {\n emit('move', from.id, to.column, index)\n }\n }\n stop()\n}\n\nfunction holdScroll(event: TouchEvent) {\n if (dragged.value) event.preventDefault()\n}\n\nfunction onEscape(event: KeyboardEvent) {\n if (event.key === 'Escape' && dragged.value) {\n event.preventDefault()\n stop()\n }\n}\n\nfunction stop() {\n window.clearTimeout(pressTimer)\n window.removeEventListener('pointermove', onPointerMove)\n window.removeEventListener('pointerup', onPointerUp)\n window.removeEventListener('pointercancel', stop)\n window.removeEventListener('touchmove', holdScroll)\n window.removeEventListener('keydown', onEscape)\n ghost?.remove()\n ghost = null\n // The click that ends a drag isn't a click on the card.\n if (dragged.value) {\n justDragged = true\n window.setTimeout(() => (justDragged = false))\n }\n pending = null\n dragged.value = null\n target.value = null\n}\n\nonBeforeUnmount(stop)\n\nfunction clickCard(event: MouseEvent, item: T) {\n if (justDragged) {\n event.preventDefault()\n event.stopPropagation()\n return\n }\n props.onCardClick?.(item)\n}\n\nfunction onCardKeydown(event: KeyboardEvent, item: T) {\n if (!props.onCardClick || event.target !== event.currentTarget || (event.key !== 'Enter' && event.key !== ' ')) return\n event.preventDefault()\n props.onCardClick(item)\n}\n\nconst isTarget = (column: string, index: number, item: T) =>\n target.value?.column === column && target.value.index === index && dragged.value?.id !== idOf(item)\n\nconst frame =\n 'border border-sui-edge bg-sui-raised p-4 transition-[border-color,opacity] duration-150 hover:border-sui-line-strong'\n</script>\n\n<!-- A board: cards in columns by a field (a stage, a status), dragged between columns. -->\n<template>\n <div\n ref=\"root\"\n class=\"flex items-stretch gap-5 overflow-x-auto pb-2 after:w-1 after:shrink-0 after:content-['']\"\n :class=\"fill && 'h-full min-h-0 flex-1'\"\n >\n <section\n v-for=\"column in columns\"\n :key=\"column.id\"\n :aria-labelledby=\"`${id}-${column.id}`\"\n class=\"flex min-h-0 w-full max-w-xs min-w-[16rem] shrink-0 flex-col\"\n >\n <header class=\"flex items-center justify-between px-1 pb-2.5\">\n <component\n :is=\"`h${headingLevel}`\"\n :id=\"`${id}-${column.id}`\"\n class=\"m-0 flex items-center gap-2 text-sm font-semibold text-sui-ink\"\n >\n <Icon v-if=\"column.icon\" :color=\"column.iconColor ?? 'ink-subtle'\" :name=\"column.icon\" />\n {{ column.name }}\n </component>\n <span\n class=\"ml-2 inline-flex h-5 items-center justify-center rounded-full bg-sui-fill px-2 text-xs text-sui-ink-muted tabular-nums\"\n >\n <slot :column=\"column\" name=\"count\">{{ column.items.length }}</slot>\n </span>\n </header>\n <div\n class=\"group/body flex min-h-[120px] flex-1 flex-col gap-2.5 overflow-y-auto rounded-xl bg-sui-fill p-2.5 transition-shadow duration-150\"\n :class=\"target?.column === column.id && 'ring-2 ring-sui-accent-line ring-inset'\"\n :data-board-column=\"column.id\"\n >\n <template v-if=\"loading\">\n <div v-for=\"i in 3\" :key=\"i\" aria-hidden=\"true\" class=\"rounded-xl border border-sui-edge bg-sui-raised p-4\">\n <Skeleton class=\"mb-3\" />\n <Skeleton height=\"0.75rem\" width=\"70%\" />\n </div>\n </template>\n <p\n v-else-if=\"column.items.length === 0 && !dragged\"\n class=\"m-0 px-1 py-3 text-center text-13 text-sui-ink-muted\"\n >\n {{ emptyLabel }}\n </p>\n <ul v-else class=\"m-0 flex list-none flex-col gap-2.5 p-0\">\n <li v-for=\"(item, index) in column.items\" :key=\"idOf(item) as PropertyKey\">\n <div\n class=\"relative rounded-xl outline-hidden transition-opacity duration-150 select-none\"\n :class=\"[\n cardFrame && frame,\n onCardClick && 'cursor-pointer focus-visible:sui-ring',\n dragged?.id === idOf(item) && 'opacity-40',\n isTarget(column.id, index, item) && 'shadow-[0_-6px_0_-4px_rgb(var(--sui-accent-solid))]'\n ]\"\n :data-board-index=\"index\"\n :role=\"onCardClick ? 'button' : undefined\"\n :tabindex=\"onCardClick ? 0 : undefined\"\n @click.capture=\"clickCard($event, item)\"\n @contextmenu=\"dragged && $event.preventDefault()\"\n @dragstart.prevent\n @keydown=\"onCardKeydown($event, item)\"\n @pointerdown=\"onPointerDown($event, item, column.id, index)\"\n >\n <slot :column=\"column\" :item=\"item\" name=\"card\">\n <p class=\"m-0 text-sm font-semibold text-sui-ink\">{{ item.name }}</p>\n </slot>\n </div>\n </li>\n </ul>\n <button\n v-if=\"onNew && !loading\"\n class=\"flex h-(--sui-control-height) w-full shrink-0 items-center justify-center gap-1.5 rounded-lg border border-dashed border-sui-line-strong text-xs font-medium text-sui-ink-muted opacity-0 outline-hidden transition-all duration-150 group-hover/body:opacity-100 hover:border-sui-ink-muted hover:bg-sui-surface/60 hover:text-sui-ink-body focus-visible:opacity-100 focus-visible:sui-ring\"\n type=\"button\"\n @click=\"onNew(column)\"\n >\n <svg\n aria-hidden=\"true\"\n class=\"size-3.5 fill-none stroke-current\"\n stroke-linecap=\"round\"\n stroke-width=\"1.5\"\n viewBox=\"0 0 14 14\"\n >\n <path d=\"M7 2.5v9M2.5 7h9\" />\n </svg>\n {{ newLabel }}\n </button>\n </div>\n </section>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -2,7 +2,7 @@ import e from "../Icon/Icon.js";
|
|
|
2
2
|
import t from "../Skeleton/Skeleton.js";
|
|
3
3
|
import { Fragment as n, createBlock as r, createCommentVNode as i, createElementBlock as a, createElementVNode as o, createTextVNode as s, createVNode as c, defineComponent as l, normalizeClass as u, onBeforeUnmount as d, openBlock as f, ref as p, renderList as m, renderSlot as h, resolveDynamicComponent as g, toDisplayString as _, unref as v, useId as y, withCtx as b, withModifiers as ee } from "vue";
|
|
4
4
|
//#region src/components/Board/Board.vue?vue&type=script&setup=true&lang.ts
|
|
5
|
-
var te = ["aria-labelledby"], ne = { class: "flex items-center justify-between px-1 pb-2.5" }, re = { class: "ml-2 inline-flex h-5 items-center justify-center rounded-full bg-sui-
|
|
5
|
+
var te = ["aria-labelledby"], ne = { class: "flex items-center justify-between px-1 pb-2.5" }, re = { class: "ml-2 inline-flex h-5 items-center justify-center rounded-full bg-sui-fill px-2 text-xs text-sui-ink-muted tabular-nums" }, x = ["data-board-column"], S = {
|
|
6
6
|
key: 1,
|
|
7
7
|
class: "m-0 px-1 py-3 text-center text-13 text-sui-ink-muted"
|
|
8
8
|
}, C = {
|
|
@@ -15,7 +15,7 @@ var te = ["aria-labelledby"], ne = { class: "flex items-center justify-between p
|
|
|
15
15
|
"onClickCapture",
|
|
16
16
|
"onKeydown",
|
|
17
17
|
"onPointerdown"
|
|
18
|
-
], T = { class: "m-0 text-sm font-semibold text-sui-ink" }, E = ["onClick"], D = 4, O = 8, k = 250, A = 48, j = "border border-sui-
|
|
18
|
+
], T = { class: "m-0 text-sm font-semibold text-sui-ink" }, E = ["onClick"], D = 4, O = 8, k = 250, A = 48, j = "border border-sui-edge bg-sui-raised p-4 transition-[border-color,opacity] duration-150 hover:border-sui-line-strong", M = /*@__PURE__*/ l({
|
|
19
19
|
__name: "Board",
|
|
20
20
|
props: {
|
|
21
21
|
columns: {},
|
|
@@ -156,12 +156,12 @@ var te = ["aria-labelledby"], ne = { class: "flex items-center justify-between p
|
|
|
156
156
|
}, null, 8, ["color", "name"])) : i("", !0), s(" " + _(y.name), 1)]),
|
|
157
157
|
_: 2
|
|
158
158
|
}, 1032, ["id"])), o("span", re, [h(d.$slots, "count", { column: y }, () => [s(_(y.items.length), 1)])])]), o("div", {
|
|
159
|
-
class: u(["group/body flex min-h-[120px] flex-1 flex-col gap-2.5 overflow-y-auto rounded-xl bg-sui-
|
|
159
|
+
class: u(["group/body flex min-h-[120px] flex-1 flex-col gap-2.5 overflow-y-auto rounded-xl bg-sui-fill p-2.5 transition-shadow duration-150", z.value?.column === y.id && "ring-2 ring-sui-accent-line ring-inset"]),
|
|
160
160
|
"data-board-column": y.id
|
|
161
161
|
}, [l.loading ? (f(), a(n, { key: 0 }, m(3, (e) => o("div", {
|
|
162
162
|
key: e,
|
|
163
163
|
"aria-hidden": "true",
|
|
164
|
-
class: "rounded-xl border border-sui-
|
|
164
|
+
class: "rounded-xl border border-sui-edge bg-sui-raised p-4"
|
|
165
165
|
}, [c(t, { class: "mb-3" }), c(t, {
|
|
166
166
|
height: "0.75rem",
|
|
167
167
|
width: "70%"
|
|
@@ -185,7 +185,7 @@ var te = ["aria-labelledby"], ne = { class: "flex items-center justify-between p
|
|
|
185
185
|
item: e
|
|
186
186
|
}, () => [o("p", T, _(e.name), 1)])], 42, w)]))), 128))])), l.onNew && !l.loading ? (f(), a("button", {
|
|
187
187
|
key: 3,
|
|
188
|
-
class: "flex h-
|
|
188
|
+
class: "flex h-(--sui-control-height) w-full shrink-0 items-center justify-center gap-1.5 rounded-lg border border-dashed border-sui-line-strong text-xs font-medium text-sui-ink-muted opacity-0 outline-hidden transition-all duration-150 group-hover/body:opacity-100 hover:border-sui-ink-muted hover:bg-sui-surface/60 hover:text-sui-ink-body focus-visible:opacity-100 focus-visible:sui-ring",
|
|
189
189
|
type: "button",
|
|
190
190
|
onClick: (e) => l.onNew(y)
|
|
191
191
|
}, [p[2] ||= o("svg", {
|