@xleddyl/443-components-vue 0.3.0 → 0.5.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 +52 -25
- package/dist/components/core/FieldBoundary.vue +14 -0
- package/dist/components/core/FieldBoundary.vue.d.ts +15 -0
- package/dist/components/core/Form.vue +91 -12
- package/dist/components/core/Form.vue.d.ts +27 -2
- package/dist/components/core/FormAlerts.vue +30 -0
- package/dist/{internal/forms → components/core}/FormAlerts.vue.d.ts +4 -4
- package/dist/components/core/FormField.vue +18 -3
- package/dist/components/core/index.d.ts +2 -0
- package/dist/components/core/index.mjs +2 -0
- package/dist/components/data/FilterPills.vue +82 -37
- package/dist/components/data/FilterPills.vue.d.ts +46 -427
- package/dist/components/data/SelectionBar.vue +7 -4
- package/dist/components/data/Tree.vue +9 -4
- package/dist/components/data/Tree.vue.d.ts +4 -1
- package/dist/components/data/types.d.ts +7 -2
- package/dist/components/forms/CheckboxGroup.vue +2 -1
- package/dist/components/forms/FileInput.vue +98 -26
- package/dist/components/forms/FileInput.vue.d.ts +28 -10
- package/dist/components/forms/RadioGroup.vue +2 -1
- package/dist/components/forms/SegmentedControl.vue +2 -1
- package/dist/components/forms/types.d.ts +3 -0
- package/dist/components/layout/Accordion.vue.d.ts +4 -4
- package/dist/components/layout/AppShell.vue +1 -1
- package/dist/components/layout/AppShell.vue.d.ts +2 -2
- package/dist/components/layout/Tabs.vue +10 -1
- package/dist/components/layout/Tabs.vue.d.ts +4 -0
- package/dist/components/layout/types.d.ts +1 -0
- package/dist/components/overlays/CommandPalette.vue +10 -4
- package/dist/components/overlays/CommandPalette.vue.d.ts +273 -511
- package/dist/components/overlays/HoverCard.vue +1 -1
- package/dist/components/overlays/HoverCard.vue.d.ts +2 -2
- package/dist/components/overlays/Popover.vue +1 -1
- package/dist/components/overlays/Popover.vue.d.ts +2 -2
- package/dist/components/overlays/Toaster.vue +35 -4
- package/dist/components/overlays/Toaster.vue.d.ts +3 -0
- package/dist/components/overlays/types.d.ts +8 -4
- package/dist/components/templates/DashboardLayout.vue +21 -18
- package/dist/components/templates/DashboardLayout.vue.d.ts +332 -565
- package/dist/components/templates/ListPage.vue +1 -1
- package/dist/components/templates/ListPage.vue.d.ts +3 -3
- package/dist/components/templates/types.d.ts +4 -4
- package/dist/composables/useField.d.ts +6 -1
- package/dist/composables/useField.mjs +40 -12
- package/dist/composables/useFieldBoundary.d.ts +1 -0
- package/dist/composables/useFieldBoundary.mjs +5 -1
- package/dist/composables/useFileDrop.d.ts +14 -1
- package/dist/composables/useFileDrop.mjs +21 -20
- package/dist/composables/useForm.d.ts +4 -0
- package/dist/composables/useForm.mjs +62 -22
- package/dist/editor/RichTextEditor.vue +2 -1
- package/dist/internal/core/ButtonElement.d.ts +2 -0
- package/dist/internal/core/ButtonElement.mjs +8 -0
- package/dist/internal/forms/files.d.ts +7 -0
- package/dist/internal/forms/files.mjs +24 -0
- package/dist/internal/keys.d.ts +2 -1
- package/dist/internal/keys.mjs +1 -0
- package/dist/internal/layout/route.mjs +1 -1
- package/dist/locale/en.mjs +4 -1
- package/dist/locale/it.mjs +4 -1
- package/dist/locale/types.d.ts +3 -0
- package/dist/nuxt/module.mjs +1 -1
- package/dist/styles/core/button.css +1 -13
- package/dist/styles/core/form-field.css +2 -2
- package/dist/styles/data/avatar.css +1 -1
- package/dist/styles/data/description-list.css +5 -3
- package/dist/styles/data/filter-pills.css +0 -1
- package/dist/styles/data/pagination.css +0 -1
- package/dist/styles/data/selection-bar.css +4 -0
- package/dist/styles/data/stat.css +1 -6
- package/dist/styles/data/table.css +1 -2
- package/dist/styles/data/tag.css +1 -4
- package/dist/styles/data/timeline.css +1 -0
- package/dist/styles/data/tree.css +8 -2
- package/dist/styles/feedback/alert.css +1 -1
- package/dist/styles/feedback/empty-state.css +6 -5
- package/dist/styles/forms/color-input.css +1 -1
- package/dist/styles/forms/combobox.css +0 -1
- package/dist/styles/forms/date-picker.css +1 -1
- package/dist/styles/forms/file-input.css +9 -1
- package/dist/styles/forms/number-input.css +1 -1
- package/dist/styles/forms/password-input.css +1 -5
- package/dist/styles/forms/switch.css +0 -1
- package/dist/styles/layout/accordion.css +7 -2
- package/dist/styles/layout/card.css +13 -7
- package/dist/styles/layout/copy-button.css +2 -2
- package/dist/styles/layout/nav-link.css +1 -2
- package/dist/styles/layout/page-header.css +2 -1
- package/dist/styles/layout/sidebar-nav.css +1 -1
- package/dist/styles/layout/sidebar.css +1 -1
- package/dist/styles/layout/tabs.css +22 -2
- package/dist/styles/layout/theme-switch.css +1 -3
- package/dist/styles/overlays/command.css +1 -1
- package/dist/styles/overlays/confirm.css +0 -1
- package/dist/styles/overlays/drawer.css +23 -2
- package/dist/styles/overlays/menu.css +2 -4
- package/dist/styles/overlays/modal.css +4 -3
- package/dist/styles/overlays/toast.css +0 -1
- package/dist/styles/templates/auth-layout.css +4 -1
- package/dist/styles/templates/empty-page.css +7 -3
- package/dist/styles/templates/error-page.css +4 -0
- package/dist/styles/templates/form-page.css +1 -1
- package/dist/styles/templates/page.css +1 -1
- package/dist/styles/templates/settings-modal.css +4 -2
- package/dist/styles/tokens.css +1 -1
- package/package.json +1 -1
- package/dist/internal/forms/FormAlerts.vue +0 -25
- package/dist/internal/overlays/FieldBoundary.d.ts +0 -4
- package/dist/internal/overlays/FieldBoundary.mjs +0 -9
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
<script setup>
|
|
19
19
|
import { useTemplateRef } from "vue";
|
|
20
|
-
import FieldBoundary from "
|
|
20
|
+
import FieldBoundary from "../core/FieldBoundary.vue";
|
|
21
21
|
import { useHoverTrigger } from "../../internal/overlays/hover";
|
|
22
22
|
import { ARROW_OFFSET, syncOpenModel, useFloatingLayer } from "../../internal/floating/layer";
|
|
23
23
|
import { useSlotTrigger } from "../../internal/floating/trigger";
|
|
@@ -206,7 +206,7 @@ declare const __VLS_base: import("vue").DefineComponent<{
|
|
|
206
206
|
is?: string | undefined | undefined;
|
|
207
207
|
exportparts?: string | undefined;
|
|
208
208
|
part?: string | undefined;
|
|
209
|
-
popover?: (import("
|
|
209
|
+
popover?: (import("../../index.ts").PopoverMode | "" | boolean) | undefined;
|
|
210
210
|
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
211
211
|
"update:open": (value: boolean) => any;
|
|
212
212
|
}, string, import("vue").PublicProps, Readonly<{
|
|
@@ -408,7 +408,7 @@ declare const __VLS_base: import("vue").DefineComponent<{
|
|
|
408
408
|
is?: string | undefined | undefined;
|
|
409
409
|
exportparts?: string | undefined;
|
|
410
410
|
part?: string | undefined;
|
|
411
|
-
popover?: (import("
|
|
411
|
+
popover?: (import("../../index.ts").PopoverMode | "" | boolean) | undefined;
|
|
412
412
|
}> & Readonly<{
|
|
413
413
|
"onUpdate:open"?: ((value: boolean) => any) | undefined;
|
|
414
414
|
}>, {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
<script setup>
|
|
23
23
|
import { useId, useTemplateRef, watch } from "vue";
|
|
24
|
-
import FieldBoundary from "
|
|
24
|
+
import FieldBoundary from "../core/FieldBoundary.vue";
|
|
25
25
|
import { focusFirst } from "../../internal/overlays/focus";
|
|
26
26
|
import { ARROW_OFFSET, syncOpenModel, useFloatingLayer } from "../../internal/floating/layer";
|
|
27
27
|
import { setAttributes, useInvoker, useSlotTrigger } from "../../internal/floating/trigger";
|
|
@@ -209,7 +209,7 @@ declare const __VLS_base: import("vue").DefineComponent<{
|
|
|
209
209
|
is?: string | undefined | undefined;
|
|
210
210
|
exportparts?: string | undefined;
|
|
211
211
|
part?: string | undefined;
|
|
212
|
-
popover?: (import("
|
|
212
|
+
popover?: (import("../../index.ts").PopoverMode | "" | boolean) | undefined;
|
|
213
213
|
}, {
|
|
214
214
|
show: () => void;
|
|
215
215
|
hide: () => void;
|
|
@@ -415,7 +415,7 @@ declare const __VLS_base: import("vue").DefineComponent<{
|
|
|
415
415
|
is?: string | undefined | undefined;
|
|
416
416
|
exportparts?: string | undefined;
|
|
417
417
|
part?: string | undefined;
|
|
418
|
-
popover?: (import("
|
|
418
|
+
popover?: (import("../../index.ts").PopoverMode | "" | boolean) | undefined;
|
|
419
419
|
}> & Readonly<{
|
|
420
420
|
"onUpdate:open"?: ((value: boolean) => any) | undefined;
|
|
421
421
|
}>, {
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
variant="ghost"
|
|
80
80
|
tone="neutral"
|
|
81
81
|
:aria-label="dismissText"
|
|
82
|
-
@click="
|
|
82
|
+
@click="dismissFromToast(entry.id)"
|
|
83
83
|
/>
|
|
84
84
|
</div>
|
|
85
85
|
<span
|
|
@@ -122,6 +122,7 @@ const props = defineProps({
|
|
|
122
122
|
position: { type: String, required: false, default: "bottom-right" },
|
|
123
123
|
max: { type: Number, required: false, default: 4 },
|
|
124
124
|
duration: { type: Number, required: false, default: 4e3 },
|
|
125
|
+
actionDuration: { type: Number, required: false, default: 1e4 },
|
|
125
126
|
gap: { type: Number, required: false, default: 8 },
|
|
126
127
|
expand: { type: Boolean, required: false },
|
|
127
128
|
progress: { type: Boolean, required: false },
|
|
@@ -274,7 +275,8 @@ function syncEntries() {
|
|
|
274
275
|
}
|
|
275
276
|
const timers = /* @__PURE__ */ new Map();
|
|
276
277
|
function durationOf(item) {
|
|
277
|
-
|
|
278
|
+
if (item.duration !== void 0) return item.duration;
|
|
279
|
+
return item.action ? Math.max(props.duration, props.actionDuration) : props.duration;
|
|
278
280
|
}
|
|
279
281
|
function hasTimer(item) {
|
|
280
282
|
const duration = durationOf(item);
|
|
@@ -343,8 +345,15 @@ function resumeTimers() {
|
|
|
343
345
|
for (const [id, timer] of timers) if (timer.handle === void 0) run(id, timer);
|
|
344
346
|
}
|
|
345
347
|
watch(paused, (value) => value ? pauseTimers() : resumeTimers());
|
|
348
|
+
function actionHint(item) {
|
|
349
|
+
if (!item.action || !props.hotkey) return "";
|
|
350
|
+
return t("toaster.actionHint", {
|
|
351
|
+
hotkey: ariaKeyShortcuts(props.hotkey, false),
|
|
352
|
+
action: item.action.label
|
|
353
|
+
});
|
|
354
|
+
}
|
|
346
355
|
function announce(item) {
|
|
347
|
-
const text = [item.title, ...descriptionLines(item)].filter(Boolean).join(". ");
|
|
356
|
+
const text = [item.title, ...descriptionLines(item), actionHint(item)].filter(Boolean).join(". ");
|
|
348
357
|
const target = item.tone === "danger" ? assertiveMessage : politeMessage;
|
|
349
358
|
target.value = "";
|
|
350
359
|
nextTick(() => target.value = text);
|
|
@@ -408,9 +417,29 @@ watch(active, async (value) => {
|
|
|
408
417
|
function dismiss(id) {
|
|
409
418
|
toast.dismiss(id);
|
|
410
419
|
}
|
|
420
|
+
let returnFocus = null;
|
|
421
|
+
function focusInToaster() {
|
|
422
|
+
const active2 = document.activeElement;
|
|
423
|
+
return Boolean(active2 && toasterRef.value?.contains(active2));
|
|
424
|
+
}
|
|
425
|
+
function restoreFocus() {
|
|
426
|
+
const target = returnFocus;
|
|
427
|
+
returnFocus = null;
|
|
428
|
+
const next = toasterRef.value?.querySelector(
|
|
429
|
+
'.k-toast[data-visible="true"]:not([data-removed="true"]) button'
|
|
430
|
+
);
|
|
431
|
+
if (target?.isConnected) target.focus({ preventScroll: true });
|
|
432
|
+
else if (next) next.focus({ preventScroll: true });
|
|
433
|
+
if (!focusInToaster()) focusInside.value = false;
|
|
434
|
+
}
|
|
435
|
+
function dismissFromToast(id) {
|
|
436
|
+
const hadFocus = focusInToaster();
|
|
437
|
+
dismiss(id);
|
|
438
|
+
if (hadFocus) nextTick(restoreFocus);
|
|
439
|
+
}
|
|
411
440
|
function runAction(item, event) {
|
|
412
441
|
item.action?.onClick(event);
|
|
413
|
-
if (!item.action?.keepOpen)
|
|
442
|
+
if (!item.action?.keepOpen) dismissFromToast(item.id);
|
|
414
443
|
}
|
|
415
444
|
function onPointerEnter(event) {
|
|
416
445
|
if (event.pointerType === "mouse") hovered.value = true;
|
|
@@ -451,6 +480,8 @@ function onVisibilityChange() {
|
|
|
451
480
|
useHotkey(
|
|
452
481
|
() => props.hotkey ? [props.hotkey] : [],
|
|
453
482
|
() => {
|
|
483
|
+
if (!focusInToaster())
|
|
484
|
+
returnFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
454
485
|
const first = toasterRef.value?.querySelector(
|
|
455
486
|
'.k-toast[data-visible="true"] button'
|
|
456
487
|
);
|
|
@@ -3,6 +3,7 @@ declare const __VLS_export: import("vue").DefineComponent<{
|
|
|
3
3
|
position?: ToasterPosition;
|
|
4
4
|
max?: number;
|
|
5
5
|
duration?: number;
|
|
6
|
+
actionDuration?: number;
|
|
6
7
|
gap?: number;
|
|
7
8
|
expand?: boolean;
|
|
8
9
|
progress?: boolean;
|
|
@@ -214,6 +215,7 @@ declare const __VLS_export: import("vue").DefineComponent<{
|
|
|
214
215
|
position?: ToasterPosition;
|
|
215
216
|
max?: number;
|
|
216
217
|
duration?: number;
|
|
218
|
+
actionDuration?: number;
|
|
217
219
|
gap?: number;
|
|
218
220
|
expand?: boolean;
|
|
219
221
|
progress?: boolean;
|
|
@@ -426,6 +428,7 @@ declare const __VLS_export: import("vue").DefineComponent<{
|
|
|
426
428
|
duration: number;
|
|
427
429
|
position: ToasterPosition;
|
|
428
430
|
gap: number;
|
|
431
|
+
actionDuration: number;
|
|
429
432
|
hotkey: string | false;
|
|
430
433
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
431
434
|
declare const _default: typeof __VLS_export;
|
|
@@ -10,6 +10,7 @@ export interface ToasterOptions {
|
|
|
10
10
|
position?: ToasterPosition;
|
|
11
11
|
max?: number;
|
|
12
12
|
duration?: number;
|
|
13
|
+
actionDuration?: number;
|
|
13
14
|
gap?: number;
|
|
14
15
|
expand?: boolean;
|
|
15
16
|
progress?: boolean;
|
|
@@ -60,7 +61,7 @@ export interface MenuSeparator {
|
|
|
60
61
|
export type MenuItem = MenuActionItem | MenuCheckboxItem | MenuRadioItem;
|
|
61
62
|
export type MenuEntry = MenuItem | MenuLabel | MenuSeparator;
|
|
62
63
|
export type MenuItems = MenuEntry[] | MenuEntry[][];
|
|
63
|
-
export interface CommandItem {
|
|
64
|
+
export interface CommandItem<T = unknown> {
|
|
64
65
|
id: string;
|
|
65
66
|
label: string;
|
|
66
67
|
description?: string;
|
|
@@ -70,11 +71,14 @@ export interface CommandItem {
|
|
|
70
71
|
to?: LinkTarget;
|
|
71
72
|
href?: string;
|
|
72
73
|
disabled?: boolean;
|
|
73
|
-
|
|
74
|
+
data?: T;
|
|
75
|
+
onSelect?: (item: CommandItem<T>) => void;
|
|
74
76
|
}
|
|
75
|
-
export interface CommandGroup {
|
|
77
|
+
export interface CommandGroup<T = unknown> {
|
|
76
78
|
id: string;
|
|
77
79
|
label?: string;
|
|
78
80
|
description?: string;
|
|
79
|
-
items: CommandItem[];
|
|
81
|
+
items: CommandItem<T>[];
|
|
80
82
|
}
|
|
83
|
+
export type CommandSearch<T = unknown> = (query: string, signal: AbortSignal) => CommandGroup<T>[] | Promise<CommandGroup<T>[]>;
|
|
84
|
+
export type CommandEmptyText = string | ((query: string) => string);
|
|
@@ -45,12 +45,17 @@
|
|
|
45
45
|
:search="searchFunction"
|
|
46
46
|
:placeholder="searchProps?.placeholder ?? searchPlaceholderText"
|
|
47
47
|
>
|
|
48
|
-
<template
|
|
49
|
-
v-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
48
|
+
<template v-if="$slots['search-item']" #item="scope">
|
|
49
|
+
<slot name="search-item" v-bind="scope" />
|
|
50
|
+
</template>
|
|
51
|
+
<template v-if="$slots['search-empty']" #empty="scope">
|
|
52
|
+
<slot name="search-empty" v-bind="scope" />
|
|
53
|
+
</template>
|
|
54
|
+
<template v-if="$slots['search-group-label']" #group-label="scope">
|
|
55
|
+
<slot name="search-group-label" v-bind="scope" />
|
|
56
|
+
</template>
|
|
57
|
+
<template v-if="$slots['search-after-results']" #after-results="scope">
|
|
58
|
+
<slot name="search-after-results" v-bind="scope" />
|
|
54
59
|
</template>
|
|
55
60
|
</CommandPalette>
|
|
56
61
|
</slot>
|
|
@@ -138,6 +143,9 @@
|
|
|
138
143
|
:title="settingsTitleText"
|
|
139
144
|
:on-sign-out="onSignOut"
|
|
140
145
|
>
|
|
146
|
+
<template v-if="$slots['settings-account-fields']" #account-fields="scope">
|
|
147
|
+
<slot name="settings-account-fields" v-bind="scope" />
|
|
148
|
+
</template>
|
|
141
149
|
<template v-for="entry in settingsSlots" :key="entry.source" #[entry.target]="scope">
|
|
142
150
|
<slot :name="entry.source" v-bind="scope" />
|
|
143
151
|
</template>
|
|
@@ -147,7 +155,7 @@
|
|
|
147
155
|
</template>
|
|
148
156
|
|
|
149
157
|
<script setup>
|
|
150
|
-
import { computed, ref,
|
|
158
|
+
import { computed, ref, useTemplateRef } from "vue";
|
|
151
159
|
import { useLocale } from "../../composables/useLocale";
|
|
152
160
|
import { navCommands, toNavSections } from "../../internal/layout/navigation";
|
|
153
161
|
import { matchesSearch } from "../../internal/core/text";
|
|
@@ -200,6 +208,7 @@ const props = defineProps({
|
|
|
200
208
|
themeLabel: { type: String, required: false }
|
|
201
209
|
});
|
|
202
210
|
const emit = defineEmits(["accountSelect"]);
|
|
211
|
+
const slots = defineSlots();
|
|
203
212
|
const collapsed = defineModel("collapsed", { type: Boolean, ...{ default: false } });
|
|
204
213
|
const open = defineModel("open", { type: Boolean, ...{ default: false } });
|
|
205
214
|
const settingsOpen = defineModel("settingsOpen", { type: Boolean, ...{ default: false } });
|
|
@@ -212,7 +221,6 @@ const searchPlaceholderText = computed(
|
|
|
212
221
|
const navigationGroupLabel = computed(
|
|
213
222
|
() => props.searchNavigationLabel ?? t("dashboardLayout.pages")
|
|
214
223
|
);
|
|
215
|
-
const slots = useSlots();
|
|
216
224
|
const shell = useTemplateRef("shell");
|
|
217
225
|
const searchOpen = ref(false);
|
|
218
226
|
const hasDesktopTopbar = computed(
|
|
@@ -228,21 +236,16 @@ const hasSidebarFooter = computed(
|
|
|
228
236
|
const hasSettings = computed(
|
|
229
237
|
() => props.accountAction === "settings" && Boolean(props.account || props.settingsSections)
|
|
230
238
|
);
|
|
231
|
-
const
|
|
239
|
+
const SETTINGS_SLOT_PATTERN = /^settings-(section|actions)-./;
|
|
232
240
|
const settingsSlots = computed(
|
|
233
|
-
() => Object.keys(slots).filter((name) =>
|
|
241
|
+
() => Object.keys(slots).filter((name) => SETTINGS_SLOT_PATTERN.test(name)).map((name) => ({
|
|
234
242
|
source: name,
|
|
235
|
-
target: name.slice(
|
|
243
|
+
target: name.slice("settings-".length)
|
|
236
244
|
}))
|
|
237
245
|
);
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
() => Object.keys(slots).filter((name) => name.startsWith(SEARCH_SLOT_PREFIX)).map((name) => ({
|
|
241
|
-
source: name,
|
|
242
|
-
target: name.slice(SEARCH_SLOT_PREFIX.length)
|
|
243
|
-
}))
|
|
246
|
+
const navigationCommands = computed(
|
|
247
|
+
() => navCommands(toNavSections(props.navigation))
|
|
244
248
|
);
|
|
245
|
-
const navigationCommands = computed(() => navCommands(toNavSections(props.navigation)));
|
|
246
249
|
const searchFunction = computed(() => {
|
|
247
250
|
const search = props.search;
|
|
248
251
|
if (typeof search !== "function") return void 0;
|