@revojs/ui 0.2.61 → 0.2.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/accordion.d.ts +13 -0
- package/dist/components/accordion.js +1 -0
- package/dist/components/checkbox.d.ts +1 -0
- package/dist/components/collapsible.d.ts +11 -0
- package/dist/components/collapsible.js +1 -0
- package/dist/components/confirm.d.ts +12 -0
- package/dist/components/confirm.js +1 -0
- package/dist/components/counter.d.ts +5 -0
- package/dist/components/labels.d.ts +24 -0
- package/dist/components/labels.js +1 -0
- package/dist/components/menu.d.ts +34 -0
- package/dist/components/radio-group.d.ts +17 -0
- package/dist/components/radio-group.js +1 -0
- package/dist/components/range.d.ts +2 -0
- package/dist/components/roving-focus.d.ts +7 -0
- package/dist/components/roving-focus.js +1 -0
- package/dist/components/select.d.ts +1 -0
- package/dist/components/stepper.d.ts +16 -0
- package/dist/components/stepper.js +1 -0
- package/dist/components/tabs.d.ts +4 -0
- package/dist/components/tags-input.d.ts +10 -0
- package/dist/components/tags-input.js +1 -0
- package/dist/components/toast.d.ts +19 -0
- package/dist/components/toast.js +1 -0
- package/dist/components/toggle-group.d.ts +5 -2
- package/dist/components/toolbar.d.ts +12 -0
- package/dist/components/toolbar.js +1 -0
- package/dist/components/tooltip.d.ts +1 -0
- package/dist/index.d.ts +15 -5
- package/dist/style.css +4 -0
- package/dist/vue/components/accordion.vue +57 -0
- package/dist/vue/components/checkbox.vue +24 -4
- package/dist/vue/components/collapsible.vue +72 -0
- package/dist/vue/components/collection.vue +5 -2
- package/dist/vue/components/confirm-dialog.vue +45 -0
- package/dist/vue/components/context-menu.vue +178 -0
- package/dist/vue/components/counter.vue +124 -18
- package/dist/vue/components/dialog.vue +5 -2
- package/dist/vue/components/menu-checkbox-item.vue +52 -0
- package/dist/vue/components/menu-group.vue +37 -0
- package/dist/vue/components/menu-layer.vue +152 -0
- package/dist/vue/components/menu-radio-group.vue +36 -0
- package/dist/vue/components/menu-radio-item.vue +50 -0
- package/dist/vue/components/menu.vue +16 -46
- package/dist/vue/components/pagination.vue +26 -6
- package/dist/vue/components/popover.vue +62 -13
- package/dist/vue/components/radio-group.vue +46 -0
- package/dist/vue/components/range.vue +31 -7
- package/dist/vue/components/rating.vue +35 -4
- package/dist/vue/components/select.vue +170 -52
- package/dist/vue/components/sheet.vue +5 -2
- package/dist/vue/components/shell.vue +5 -2
- package/dist/vue/components/stepper.vue +96 -0
- package/dist/vue/components/tabs.vue +37 -43
- package/dist/vue/components/tags-input.vue +141 -0
- package/dist/vue/components/toast-region.vue +233 -0
- package/dist/vue/components/toggle-group.vue +65 -10
- package/dist/vue/components/toolbar.vue +43 -0
- package/dist/vue/components/tooltip.vue +101 -15
- package/dist/vue/components/upload.vue +7 -4
- package/dist/vue/index.d.ts +28 -7
- package/dist/vue/index.js +29 -8
- package/dist/vue/utilities/labels.d.ts +7 -0
- package/dist/vue/utilities/labels.js +62 -0
- package/dist/vue/utilities/menu.d.ts +6 -0
- package/dist/vue/utilities/menu.js +2 -1
- package/dist/vue/utilities/tooltip.d.ts +3 -0
- package/dist/vue/utilities/tooltip.js +4 -0
- package/dist/vue/utilities/use-anchor.d.ts +6 -0
- package/dist/vue/utilities/use-anchor.js +26 -0
- package/dist/vue/utilities/use-confirm.d.ts +24 -0
- package/dist/vue/utilities/use-confirm.js +27 -0
- package/dist/vue/utilities/use-menu-navigation.d.ts +6 -0
- package/dist/vue/utilities/use-menu-navigation.js +48 -0
- package/dist/vue/utilities/use-roving-focus.d.ts +7 -0
- package/dist/vue/utilities/use-roving-focus.js +73 -0
- package/dist/vue/utilities/use-toast.d.ts +27 -0
- package/dist/vue/utilities/use-toast.js +33 -0
- package/dist/vue/utilities/use-typeahead.d.ts +5 -0
- package/dist/vue/utilities/use-typeahead.js +37 -0
- package/package.json +1 -1
- package/dist/vue/utilities/use-focus-trap.d.ts +0 -2
- package/dist/vue/utilities/use-focus-trap.js +0 -34
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<Stack direction="horizontal" align="center" justify="between" gap="0">
|
|
18
18
|
<span class="min-w-0 flex-1 p-3">
|
|
19
19
|
<span class="block truncate px-1">{{
|
|
20
|
-
"name" in modelValue ? modelValue.name :
|
|
20
|
+
"name" in modelValue ? modelValue.name : labels.fileSelected
|
|
21
21
|
}}</span>
|
|
22
22
|
</span>
|
|
23
23
|
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
variant="secondary"
|
|
27
27
|
:text="text"
|
|
28
28
|
:icon-prefix="CloseIcon"
|
|
29
|
-
aria-label="
|
|
29
|
+
:aria-label="labels.removeFile"
|
|
30
30
|
:disabled="disabled"
|
|
31
31
|
@click="remove"
|
|
32
32
|
/>
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
<Stack align="center" gap="3" padding="5" class="text-center">
|
|
37
37
|
<Icon :is="UploadIcon" :size="24" />
|
|
38
38
|
|
|
39
|
-
<span class="text-sm opacity-60">
|
|
39
|
+
<span class="text-sm opacity-60">{{ labels.dropFile }}</span>
|
|
40
40
|
|
|
41
|
-
<Button label="
|
|
41
|
+
<Button :label="labels.browseFiles" variant="outline" :disabled="disabled" @click="browse" />
|
|
42
42
|
</Stack>
|
|
43
43
|
</slot>
|
|
44
44
|
|
|
@@ -70,6 +70,7 @@ import CloseIcon from "~icons/hugeicons/multiplication-sign";
|
|
|
70
70
|
import { computed, ref, useTemplateRef } from "vue";
|
|
71
71
|
import type { ControlInteraction } from "../../components/control.ts";
|
|
72
72
|
import type { UploadProps, UploadState, UploadText } from "../../components/upload";
|
|
73
|
+
import { useUiLabels } from "../utilities/labels";
|
|
73
74
|
import Button from "./button.vue";
|
|
74
75
|
import Icon from "./icon.vue";
|
|
75
76
|
import Stack from "./stack.vue";
|
|
@@ -94,6 +95,8 @@ defineSlots<{
|
|
|
94
95
|
file?: (props: { file: Blob | File; remove: () => void; disabled: boolean }) => unknown;
|
|
95
96
|
}>();
|
|
96
97
|
|
|
98
|
+
const labels = useUiLabels();
|
|
99
|
+
|
|
97
100
|
const input = useTemplateRef("input");
|
|
98
101
|
|
|
99
102
|
const isOver = ref(false);
|
package/dist/vue/index.d.ts
CHANGED
|
@@ -1,42 +1,63 @@
|
|
|
1
|
+
export { default as Accordion } from "./components/accordion.vue";
|
|
1
2
|
export { default as Badge } from "./components/badge.vue";
|
|
2
3
|
export { default as Breadcrumb } from "./components/breadcrumb.vue";
|
|
3
4
|
export { default as Button } from "./components/button.vue";
|
|
4
5
|
export { default as Card } from "./components/card.vue";
|
|
5
6
|
export { default as Checkbox } from "./components/checkbox.vue";
|
|
7
|
+
export { default as Collapsible } from "./components/collapsible.vue";
|
|
6
8
|
export { default as Collection } from "./components/collection.vue";
|
|
9
|
+
export { default as ConfirmDialog } from "./components/confirm-dialog.vue";
|
|
7
10
|
export { default as Container } from "./components/container.vue";
|
|
11
|
+
export { default as ContextMenu } from "./components/context-menu.vue";
|
|
8
12
|
export { default as Counter } from "./components/counter.vue";
|
|
9
13
|
export { default as Dialog } from "./components/dialog.vue";
|
|
14
|
+
export { default as Entry } from "./components/entry.vue";
|
|
10
15
|
export { default as Field } from "./components/field.vue";
|
|
11
16
|
export { default as Heading } from "./components/heading.vue";
|
|
12
|
-
export { default as Shell } from "./components/shell.vue";
|
|
13
17
|
export { default as Icon } from "./components/icon.vue";
|
|
14
18
|
export { default as Input } from "./components/input.vue";
|
|
15
19
|
export { default as Link } from "./components/link.vue";
|
|
16
20
|
export { default as Markdown } from "./components/markdown.vue";
|
|
17
21
|
export { default as Menu } from "./components/menu.vue";
|
|
22
|
+
export { default as MenuCheckboxItem } from "./components/menu-checkbox-item.vue";
|
|
23
|
+
export { default as MenuGroup } from "./components/menu-group.vue";
|
|
18
24
|
export { default as MenuItem } from "./components/menu-item.vue";
|
|
19
|
-
export { default as
|
|
20
|
-
export { default as
|
|
25
|
+
export { default as MenuLayer } from "./components/menu-layer.vue";
|
|
26
|
+
export { default as MenuRadioGroup } from "./components/menu-radio-group.vue";
|
|
27
|
+
export { default as MenuRadioItem } from "./components/menu-radio-item.vue";
|
|
21
28
|
export { default as Navigate } from "./components/navigate.vue";
|
|
22
|
-
export { default as
|
|
29
|
+
export { default as Notification } from "./components/notification.vue";
|
|
23
30
|
export { default as Pagination } from "./components/pagination.vue";
|
|
31
|
+
export { default as Popover } from "./components/popover.vue";
|
|
24
32
|
export { default as Progress } from "./components/progress.vue";
|
|
25
33
|
export { default as Radio } from "./components/radio.vue";
|
|
34
|
+
export { default as RadioGroup } from "./components/radio-group.vue";
|
|
26
35
|
export { default as Range } from "./components/range.vue";
|
|
27
36
|
export { default as Rating } from "./components/rating.vue";
|
|
28
37
|
export { default as Select } from "./components/select.vue";
|
|
29
38
|
export { default as Separator } from "./components/separator.vue";
|
|
30
39
|
export { default as Sheet } from "./components/sheet.vue";
|
|
40
|
+
export { default as Shell } from "./components/shell.vue";
|
|
31
41
|
export { default as Stack } from "./components/stack.vue";
|
|
42
|
+
export { default as Stepper } from "./components/stepper.vue";
|
|
32
43
|
export { default as Switch } from "./components/switch.vue";
|
|
33
44
|
export { default as Tabs } from "./components/tabs.vue";
|
|
34
|
-
export { default as
|
|
45
|
+
export { default as TagsInput } from "./components/tags-input.vue";
|
|
35
46
|
export { default as Textarea } from "./components/textarea.vue";
|
|
47
|
+
export { default as ToastRegion } from "./components/toast-region.vue";
|
|
36
48
|
export { default as ToggleGroup } from "./components/toggle-group.vue";
|
|
49
|
+
export { default as Toolbar } from "./components/toolbar.vue";
|
|
37
50
|
export { default as Tooltip } from "./components/tooltip.vue";
|
|
38
|
-
export {
|
|
51
|
+
export { default as Upload } from "./components/upload.vue";
|
|
52
|
+
export { defaultUiLabels, germanUiLabels, provideUiLabels, uiLabelsKey, useUiLabels } from "./utilities/labels";
|
|
53
|
+
export { menuCloseKey, menuRadioKey, menuSizeKey, type MenuRadioContext } from "./utilities/menu";
|
|
54
|
+
export { tooltipState } from "./utilities/tooltip";
|
|
55
|
+
export { useAnchor } from "./utilities/use-anchor";
|
|
56
|
+
export { useConfirm } from "./utilities/use-confirm";
|
|
39
57
|
export { useControlAttributes } from "./utilities/use-control-attributes";
|
|
40
|
-
export {
|
|
58
|
+
export { menuItemSelector, useMenuNavigation } from "./utilities/use-menu-navigation";
|
|
41
59
|
export { useModalDialog } from "./utilities/use-modal-dialog";
|
|
60
|
+
export { useRovingFocus } from "./utilities/use-roving-focus";
|
|
42
61
|
export { useScrollLock } from "./utilities/use-scroll-lock";
|
|
62
|
+
export { useToast } from "./utilities/use-toast";
|
|
63
|
+
export { isTypeaheadKey, useTypeahead } from "./utilities/use-typeahead";
|
package/dist/vue/index.js
CHANGED
|
@@ -1,43 +1,64 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defaultUiLabels, germanUiLabels, provideUiLabels, uiLabelsKey, useUiLabels } from "./utilities/labels.js";
|
|
2
|
+
import { menuCloseKey, menuRadioKey, menuSizeKey } from "./utilities/menu.js";
|
|
3
|
+
import { tooltipState } from "./utilities/tooltip.js";
|
|
4
|
+
import { useAnchor } from "./utilities/use-anchor.js";
|
|
5
|
+
import { useConfirm } from "./utilities/use-confirm.js";
|
|
2
6
|
import { useControlAttributes } from "./utilities/use-control-attributes.js";
|
|
3
|
-
import {
|
|
7
|
+
import { isTypeaheadKey, useTypeahead } from "./utilities/use-typeahead.js";
|
|
8
|
+
import { menuItemSelector, useMenuNavigation } from "./utilities/use-menu-navigation.js";
|
|
4
9
|
import { useScrollLock } from "./utilities/use-scroll-lock.js";
|
|
5
10
|
import { useModalDialog } from "./utilities/use-modal-dialog.js";
|
|
11
|
+
import { useRovingFocus } from "./utilities/use-roving-focus.js";
|
|
12
|
+
import { useToast } from "./utilities/use-toast.js";
|
|
13
|
+
import Accordion from "./components/accordion.vue";
|
|
6
14
|
import Badge from "./components/badge.vue";
|
|
7
15
|
import Breadcrumb from "./components/breadcrumb.vue";
|
|
8
16
|
import Button from "./components/button.vue";
|
|
9
17
|
import Card from "./components/card.vue";
|
|
10
18
|
import Checkbox from "./components/checkbox.vue";
|
|
19
|
+
import Collapsible from "./components/collapsible.vue";
|
|
11
20
|
import Collection from "./components/collection.vue";
|
|
21
|
+
import ConfirmDialog from "./components/confirm-dialog.vue";
|
|
12
22
|
import Container from "./components/container.vue";
|
|
23
|
+
import ContextMenu from "./components/context-menu.vue";
|
|
13
24
|
import Counter from "./components/counter.vue";
|
|
14
25
|
import Dialog from "./components/dialog.vue";
|
|
26
|
+
import Entry from "./components/entry.vue";
|
|
15
27
|
import Field from "./components/field.vue";
|
|
16
28
|
import Heading from "./components/heading.vue";
|
|
17
|
-
import Shell from "./components/shell.vue";
|
|
18
29
|
import Icon from "./components/icon.vue";
|
|
19
30
|
import Input from "./components/input.vue";
|
|
20
31
|
import Link from "./components/link.vue";
|
|
21
32
|
import Markdown from "./components/markdown.vue";
|
|
22
33
|
import Menu from "./components/menu.vue";
|
|
34
|
+
import MenuCheckboxItem from "./components/menu-checkbox-item.vue";
|
|
35
|
+
import MenuGroup from "./components/menu-group.vue";
|
|
23
36
|
import MenuItem from "./components/menu-item.vue";
|
|
24
|
-
import
|
|
25
|
-
import
|
|
37
|
+
import MenuLayer from "./components/menu-layer.vue";
|
|
38
|
+
import MenuRadioGroup from "./components/menu-radio-group.vue";
|
|
39
|
+
import MenuRadioItem from "./components/menu-radio-item.vue";
|
|
26
40
|
import Navigate from "./components/navigate.vue";
|
|
27
|
-
import
|
|
41
|
+
import Notification from "./components/notification.vue";
|
|
28
42
|
import Pagination from "./components/pagination.vue";
|
|
43
|
+
import Popover from "./components/popover.vue";
|
|
29
44
|
import Progress from "./components/progress.vue";
|
|
30
45
|
import Radio from "./components/radio.vue";
|
|
46
|
+
import RadioGroup from "./components/radio-group.vue";
|
|
31
47
|
import Range from "./components/range.vue";
|
|
32
48
|
import Rating from "./components/rating.vue";
|
|
33
49
|
import Select from "./components/select.vue";
|
|
34
50
|
import Separator from "./components/separator.vue";
|
|
35
51
|
import Sheet from "./components/sheet.vue";
|
|
52
|
+
import Shell from "./components/shell.vue";
|
|
36
53
|
import Stack from "./components/stack.vue";
|
|
54
|
+
import Stepper from "./components/stepper.vue";
|
|
37
55
|
import Switch from "./components/switch.vue";
|
|
38
56
|
import Tabs from "./components/tabs.vue";
|
|
39
|
-
import
|
|
57
|
+
import TagsInput from "./components/tags-input.vue";
|
|
40
58
|
import Textarea from "./components/textarea.vue";
|
|
59
|
+
import ToastRegion from "./components/toast-region.vue";
|
|
41
60
|
import ToggleGroup from "./components/toggle-group.vue";
|
|
61
|
+
import Toolbar from "./components/toolbar.vue";
|
|
42
62
|
import Tooltip from "./components/tooltip.vue";
|
|
43
|
-
|
|
63
|
+
import Upload from "./components/upload.vue";
|
|
64
|
+
export { Accordion, Badge, Breadcrumb, Button, Card, Checkbox, Collapsible, Collection, ConfirmDialog, Container, ContextMenu, Counter, Dialog, Entry, Field, Heading, Icon, Input, Link, Markdown, Menu, MenuCheckboxItem, MenuGroup, MenuItem, MenuLayer, MenuRadioGroup, MenuRadioItem, Navigate, Notification, Pagination, Popover, Progress, Radio, RadioGroup, Range, Rating, Select, Separator, Sheet, Shell, Stack, Stepper, Switch, Tabs, TagsInput, Textarea, ToastRegion, ToggleGroup, Toolbar, Tooltip, Upload, defaultUiLabels, germanUiLabels, isTypeaheadKey, menuCloseKey, menuItemSelector, menuRadioKey, menuSizeKey, provideUiLabels, tooltipState, uiLabelsKey, useAnchor, useConfirm, useControlAttributes, useMenuNavigation, useModalDialog, useRovingFocus, useScrollLock, useToast, useTypeahead, useUiLabels };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type InjectionKey } from "vue";
|
|
2
|
+
import type { UiLabels } from "../../components/labels";
|
|
3
|
+
export declare function useUiLabels(): UiLabels;
|
|
4
|
+
export declare function provideUiLabels(labels: Partial<UiLabels>): void;
|
|
5
|
+
export declare const uiLabelsKey: InjectionKey<UiLabels>;
|
|
6
|
+
export declare const defaultUiLabels: UiLabels;
|
|
7
|
+
export declare const germanUiLabels: UiLabels;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { inject, provide } from "vue";
|
|
2
|
+
//#region src/vue/utilities/labels.ts
|
|
3
|
+
function useUiLabels() {
|
|
4
|
+
return inject(uiLabelsKey, defaultUiLabels);
|
|
5
|
+
}
|
|
6
|
+
function provideUiLabels(labels) {
|
|
7
|
+
provide(uiLabelsKey, {
|
|
8
|
+
...useUiLabels(),
|
|
9
|
+
...labels
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
var uiLabelsKey = Symbol("ui-labels");
|
|
13
|
+
var defaultUiLabels = {
|
|
14
|
+
open: "Open",
|
|
15
|
+
close: "Close",
|
|
16
|
+
menu: "Menu",
|
|
17
|
+
select: "Select",
|
|
18
|
+
selectRequired: "Please select an option",
|
|
19
|
+
noResults: "No results found",
|
|
20
|
+
empty: "Nothing found",
|
|
21
|
+
previous: "Previous",
|
|
22
|
+
next: "Next",
|
|
23
|
+
pagination: "Pagination",
|
|
24
|
+
pageNavigation: "Page navigation",
|
|
25
|
+
fileSelected: "File selected",
|
|
26
|
+
dropFile: "Drag and drop a file here",
|
|
27
|
+
browseFiles: "Browse files",
|
|
28
|
+
removeFile: "Remove file",
|
|
29
|
+
decrease: "Decrease",
|
|
30
|
+
increase: "Increase",
|
|
31
|
+
rating: (value, max) => `${value} of ${max}`,
|
|
32
|
+
notifications: "Notifications (F8)",
|
|
33
|
+
confirm: "Confirm",
|
|
34
|
+
cancel: "Cancel",
|
|
35
|
+
remove: (label) => `Remove ${label}`
|
|
36
|
+
};
|
|
37
|
+
var germanUiLabels = {
|
|
38
|
+
open: "Öffnen",
|
|
39
|
+
close: "Schließen",
|
|
40
|
+
menu: "Menü",
|
|
41
|
+
select: "Auswählen",
|
|
42
|
+
selectRequired: "Bitte wähle eine Option",
|
|
43
|
+
noResults: "Keine Treffer",
|
|
44
|
+
empty: "Nichts gefunden",
|
|
45
|
+
previous: "Zurück",
|
|
46
|
+
next: "Weiter",
|
|
47
|
+
pagination: "Seiten",
|
|
48
|
+
pageNavigation: "Seitennavigation",
|
|
49
|
+
fileSelected: "Datei ausgewählt",
|
|
50
|
+
dropFile: "Datei hierher ziehen",
|
|
51
|
+
browseFiles: "Datei auswählen",
|
|
52
|
+
removeFile: "Datei entfernen",
|
|
53
|
+
decrease: "Verringern",
|
|
54
|
+
increase: "Erhöhen",
|
|
55
|
+
rating: (value, max) => `${value} von ${max}`,
|
|
56
|
+
notifications: "Mitteilungen (F8)",
|
|
57
|
+
confirm: "Bestätigen",
|
|
58
|
+
cancel: "Abbrechen",
|
|
59
|
+
remove: (label) => `${label} entfernen`
|
|
60
|
+
};
|
|
61
|
+
//#endregion
|
|
62
|
+
export { defaultUiLabels, germanUiLabels, provideUiLabels, uiLabelsKey, useUiLabels };
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import type { ComputedRef, InjectionKey } from "vue";
|
|
2
2
|
import type { ButtonSize } from "../../components/button";
|
|
3
|
+
import type { MenuRadioValue } from "../../components/menu";
|
|
4
|
+
export interface MenuRadioContext {
|
|
5
|
+
value: ComputedRef<MenuRadioValue | undefined>;
|
|
6
|
+
select: (value: MenuRadioValue) => void;
|
|
7
|
+
}
|
|
3
8
|
export declare const menuCloseKey: InjectionKey<() => void>;
|
|
4
9
|
export declare const menuSizeKey: InjectionKey<ComputedRef<ButtonSize>>;
|
|
10
|
+
export declare const menuRadioKey: InjectionKey<MenuRadioContext>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
//#region src/vue/utilities/menu.ts
|
|
2
2
|
var menuCloseKey = Symbol("menu-close");
|
|
3
3
|
var menuSizeKey = Symbol("menu-size");
|
|
4
|
+
var menuRadioKey = Symbol("menu-radio");
|
|
4
5
|
//#endregion
|
|
5
|
-
export { menuCloseKey, menuSizeKey };
|
|
6
|
+
export { menuCloseKey, menuRadioKey, menuSizeKey };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { onMounted, ref, toValue, useId, watch } from "vue";
|
|
2
|
+
//#region src/vue/utilities/use-anchor.ts
|
|
3
|
+
function useAnchor(layer, open = true) {
|
|
4
|
+
const name = `--anchor-${useId()}`;
|
|
5
|
+
const anchored = ref(false);
|
|
6
|
+
onMounted(() => {
|
|
7
|
+
anchored.value = typeof HTMLElement.prototype.showPopover === "function" && CSS.supports("anchor-name", name);
|
|
8
|
+
});
|
|
9
|
+
watch([
|
|
10
|
+
layer,
|
|
11
|
+
anchored,
|
|
12
|
+
() => toValue(open)
|
|
13
|
+
], ([element, supported, value]) => {
|
|
14
|
+
if (!element || !supported) return;
|
|
15
|
+
const shown = element.matches(":popover-open");
|
|
16
|
+
if (value && !shown) element.showPopover();
|
|
17
|
+
else if (!value && shown) element.hidePopover();
|
|
18
|
+
}, { flush: "post" });
|
|
19
|
+
return {
|
|
20
|
+
anchored,
|
|
21
|
+
anchorStyle: `anchor-name: ${name}`,
|
|
22
|
+
layerStyle: `position-anchor: ${name}`
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export { useAnchor };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ConfirmOptions } from "../../components/confirm";
|
|
2
|
+
export declare function useConfirm(): {
|
|
3
|
+
request: Readonly<import("vue").Ref<{
|
|
4
|
+
readonly options: {
|
|
5
|
+
readonly label: string;
|
|
6
|
+
readonly description?: string;
|
|
7
|
+
readonly confirmLabel?: string;
|
|
8
|
+
readonly cancelLabel?: string;
|
|
9
|
+
readonly variant?: import("../..").ConfirmVariant;
|
|
10
|
+
};
|
|
11
|
+
readonly resolve: (value: boolean) => void;
|
|
12
|
+
} | undefined, {
|
|
13
|
+
readonly options: {
|
|
14
|
+
readonly label: string;
|
|
15
|
+
readonly description?: string;
|
|
16
|
+
readonly confirmLabel?: string;
|
|
17
|
+
readonly cancelLabel?: string;
|
|
18
|
+
readonly variant?: import("../..").ConfirmVariant;
|
|
19
|
+
};
|
|
20
|
+
readonly resolve: (value: boolean) => void;
|
|
21
|
+
} | undefined>>;
|
|
22
|
+
confirm: (options: ConfirmOptions) => Promise<boolean>;
|
|
23
|
+
answer: (value: boolean) => void;
|
|
24
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { readonly, shallowRef } from "vue";
|
|
2
|
+
//#region src/vue/utilities/use-confirm.ts
|
|
3
|
+
function useConfirm() {
|
|
4
|
+
function confirm(options) {
|
|
5
|
+
request.value?.resolve(false);
|
|
6
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
7
|
+
if (typeof document === "undefined") resolve(false);
|
|
8
|
+
else request.value = {
|
|
9
|
+
options,
|
|
10
|
+
resolve
|
|
11
|
+
};
|
|
12
|
+
return promise;
|
|
13
|
+
}
|
|
14
|
+
function answer(value) {
|
|
15
|
+
const current = request.value;
|
|
16
|
+
request.value = void 0;
|
|
17
|
+
current?.resolve(value);
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
request: readonly(request),
|
|
21
|
+
confirm,
|
|
22
|
+
answer
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
var request = shallowRef();
|
|
26
|
+
//#endregion
|
|
27
|
+
export { useConfirm };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function useMenuNavigation(): {
|
|
2
|
+
items: (menu: Element | null | undefined) => HTMLElement[];
|
|
3
|
+
focusItem: (menu: Element | null | undefined, index: number) => void;
|
|
4
|
+
handleKeyDown: (event: KeyboardEvent) => void;
|
|
5
|
+
};
|
|
6
|
+
export declare const menuItemSelector = "[role='menuitem'], [role='menuitemcheckbox'], [role='menuitemradio']";
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { isTypeaheadKey, useTypeahead } from "./use-typeahead.js";
|
|
2
|
+
//#region src/vue/utilities/use-menu-navigation.ts
|
|
3
|
+
function useMenuNavigation() {
|
|
4
|
+
const { search, pending } = useTypeahead();
|
|
5
|
+
function items(menu) {
|
|
6
|
+
const list = [];
|
|
7
|
+
for (const item of menu?.querySelectorAll("[role='menuitem'], [role='menuitemcheckbox'], [role='menuitemradio']") ?? []) if (item.closest("[role='menu']") === menu && item.getAttribute("aria-disabled") !== "true") list.push(item);
|
|
8
|
+
return list;
|
|
9
|
+
}
|
|
10
|
+
function focusItem(menu, index) {
|
|
11
|
+
const list = items(menu);
|
|
12
|
+
list[(index + list.length) % list.length]?.focus();
|
|
13
|
+
}
|
|
14
|
+
function handleKeyDown(event) {
|
|
15
|
+
const target = event.target;
|
|
16
|
+
const menu = target.closest("[role='menu']");
|
|
17
|
+
const list = items(menu);
|
|
18
|
+
const index = list.indexOf(target);
|
|
19
|
+
if (index === -1) return;
|
|
20
|
+
if (event.key === "ArrowDown") {
|
|
21
|
+
event.preventDefault();
|
|
22
|
+
focusItem(menu, index + 1);
|
|
23
|
+
} else if (event.key === "ArrowUp") {
|
|
24
|
+
event.preventDefault();
|
|
25
|
+
focusItem(menu, index - 1);
|
|
26
|
+
} else if (event.key === "Home") {
|
|
27
|
+
event.preventDefault();
|
|
28
|
+
focusItem(menu, 0);
|
|
29
|
+
} else if (event.key === "End") {
|
|
30
|
+
event.preventDefault();
|
|
31
|
+
focusItem(menu, -1);
|
|
32
|
+
} else if (isTypeaheadKey(event) && (event.key !== " " || pending())) {
|
|
33
|
+
const labels = [];
|
|
34
|
+
for (const item of list) labels.push(item.textContent ?? "");
|
|
35
|
+
const match = search(event.key, labels, index);
|
|
36
|
+
event.preventDefault();
|
|
37
|
+
if (match !== -1) list[match].focus();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
items,
|
|
42
|
+
focusItem,
|
|
43
|
+
handleKeyDown
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
var menuItemSelector = "[role='menuitem'], [role='menuitemcheckbox'], [role='menuitemradio']";
|
|
47
|
+
//#endregion
|
|
48
|
+
export { menuItemSelector, useMenuNavigation };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type MaybeRefOrGetter, type Ref } from "vue";
|
|
2
|
+
import type { RovingFocusOptions } from "../../components/roving-focus";
|
|
3
|
+
export declare function useRovingFocus(container: Ref<HTMLElement | null>, options?: MaybeRefOrGetter<RovingFocusOptions>): {
|
|
4
|
+
handleKeyDown: (event: KeyboardEvent) => void;
|
|
5
|
+
handleFocusIn: (event: FocusEvent) => void;
|
|
6
|
+
sync: () => void;
|
|
7
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { onMounted, onUpdated, toValue } from "vue";
|
|
2
|
+
//#region src/vue/utilities/use-roving-focus.ts
|
|
3
|
+
function useRovingFocus(container, options = {}) {
|
|
4
|
+
let active;
|
|
5
|
+
function items() {
|
|
6
|
+
const { selector = "button, a[href], input, [tabindex]" } = toValue(options);
|
|
7
|
+
const list = [];
|
|
8
|
+
for (const element of container.value?.querySelectorAll(selector) ?? []) {
|
|
9
|
+
if (element.matches(":disabled, [aria-disabled='true'], [type='hidden']") || element.getAttribute("tabindex") === "-1" && element.dataset.rovingItem === void 0 || element.closest("[role='menu'], [role='dialog'], [role='listbox']") !== container.value?.closest("[role='menu'], [role='dialog'], [role='listbox']")) continue;
|
|
10
|
+
list.push(element);
|
|
11
|
+
}
|
|
12
|
+
return list;
|
|
13
|
+
}
|
|
14
|
+
function sync() {
|
|
15
|
+
const list = items();
|
|
16
|
+
if (!container.value?.contains(document.activeElement) || !active || !list.includes(active)) active = list.find((element) => element.matches("[aria-checked='true'], [aria-selected='true'], [aria-pressed='true']")) ?? list[0];
|
|
17
|
+
for (const element of list) {
|
|
18
|
+
element.dataset.rovingItem = "";
|
|
19
|
+
element.tabIndex = element === active ? 0 : -1;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function focus(element) {
|
|
23
|
+
active = element;
|
|
24
|
+
sync();
|
|
25
|
+
element.focus();
|
|
26
|
+
toValue(options).onMove?.(element);
|
|
27
|
+
}
|
|
28
|
+
function handleFocusIn(event) {
|
|
29
|
+
const list = items();
|
|
30
|
+
const target = event.target;
|
|
31
|
+
if (list.includes(target)) {
|
|
32
|
+
active = target;
|
|
33
|
+
sync();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function handleKeyDown(event) {
|
|
37
|
+
const target = event.target;
|
|
38
|
+
if (target.matches("input:not([type='checkbox'], [type='radio'], [type='button']), textarea, [contenteditable]")) return;
|
|
39
|
+
const { orientation = "horizontal", loop = true } = toValue(options);
|
|
40
|
+
const list = items();
|
|
41
|
+
const index = list.indexOf(target);
|
|
42
|
+
if (index === -1 || event.altKey || event.ctrlKey || event.metaKey) return;
|
|
43
|
+
const rtl = getComputedStyle(container.value ?? target).direction === "rtl";
|
|
44
|
+
let step = 0;
|
|
45
|
+
if (orientation !== "vertical" && event.key === "ArrowRight") step = rtl ? -1 : 1;
|
|
46
|
+
else if (orientation !== "vertical" && event.key === "ArrowLeft") step = rtl ? 1 : -1;
|
|
47
|
+
else if (orientation !== "horizontal" && event.key === "ArrowDown") step = 1;
|
|
48
|
+
else if (orientation !== "horizontal" && event.key === "ArrowUp") step = -1;
|
|
49
|
+
else if (event.key === "Home") {
|
|
50
|
+
event.preventDefault();
|
|
51
|
+
focus(list[0]);
|
|
52
|
+
return;
|
|
53
|
+
} else if (event.key === "End") {
|
|
54
|
+
event.preventDefault();
|
|
55
|
+
focus(list[list.length - 1]);
|
|
56
|
+
return;
|
|
57
|
+
} else return;
|
|
58
|
+
event.preventDefault();
|
|
59
|
+
let next = index + step;
|
|
60
|
+
if (loop) next = (next + list.length) % list.length;
|
|
61
|
+
const element = list[next];
|
|
62
|
+
if (element) focus(element);
|
|
63
|
+
}
|
|
64
|
+
onMounted(sync);
|
|
65
|
+
onUpdated(sync);
|
|
66
|
+
return {
|
|
67
|
+
handleKeyDown,
|
|
68
|
+
handleFocusIn,
|
|
69
|
+
sync
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//#endregion
|
|
73
|
+
export { useRovingFocus };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ToastOptions } from "../../components/toast";
|
|
2
|
+
export declare function useToast(): {
|
|
3
|
+
toasts: Readonly<import("vue").Ref<readonly {
|
|
4
|
+
readonly label: string;
|
|
5
|
+
readonly subtext?: string;
|
|
6
|
+
readonly variant?: import("../..").NotificationVariant;
|
|
7
|
+
readonly duration?: number;
|
|
8
|
+
readonly action?: {
|
|
9
|
+
readonly label: string;
|
|
10
|
+
readonly onSelect: () => void;
|
|
11
|
+
} | undefined;
|
|
12
|
+
readonly id: string;
|
|
13
|
+
}[], readonly {
|
|
14
|
+
readonly label: string;
|
|
15
|
+
readonly subtext?: string;
|
|
16
|
+
readonly variant?: import("../..").NotificationVariant;
|
|
17
|
+
readonly duration?: number;
|
|
18
|
+
readonly action?: {
|
|
19
|
+
readonly label: string;
|
|
20
|
+
readonly onSelect: () => void;
|
|
21
|
+
} | undefined;
|
|
22
|
+
readonly id: string;
|
|
23
|
+
}[]>>;
|
|
24
|
+
add: (options: ToastOptions) => string;
|
|
25
|
+
remove: (id: string) => void;
|
|
26
|
+
clear: () => void;
|
|
27
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { readonly, shallowRef } from "vue";
|
|
2
|
+
//#region src/vue/utilities/use-toast.ts
|
|
3
|
+
function useToast() {
|
|
4
|
+
function add(options) {
|
|
5
|
+
if (typeof document === "undefined") return "";
|
|
6
|
+
counter.value += 1;
|
|
7
|
+
const id = `toast-${counter.value}`;
|
|
8
|
+
toasts.value = [...toasts.value, {
|
|
9
|
+
duration: 5e3,
|
|
10
|
+
...options,
|
|
11
|
+
id
|
|
12
|
+
}];
|
|
13
|
+
return id;
|
|
14
|
+
}
|
|
15
|
+
function remove(id) {
|
|
16
|
+
const list = [];
|
|
17
|
+
for (const toast of toasts.value) if (toast.id !== id) list.push(toast);
|
|
18
|
+
toasts.value = list;
|
|
19
|
+
}
|
|
20
|
+
function clear() {
|
|
21
|
+
toasts.value = [];
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
toasts: readonly(toasts),
|
|
25
|
+
add,
|
|
26
|
+
remove,
|
|
27
|
+
clear
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
var counter = shallowRef(0);
|
|
31
|
+
var toasts = shallowRef([]);
|
|
32
|
+
//#endregion
|
|
33
|
+
export { useToast };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
//#region src/vue/utilities/use-typeahead.ts
|
|
2
|
+
function useTypeahead(timeout = 1e3) {
|
|
3
|
+
let buffer = "";
|
|
4
|
+
let timer;
|
|
5
|
+
function search(key, labels, current) {
|
|
6
|
+
clearTimeout(timer);
|
|
7
|
+
buffer += key.toLowerCase();
|
|
8
|
+
timer = setTimeout(() => {
|
|
9
|
+
buffer = "";
|
|
10
|
+
}, timeout);
|
|
11
|
+
let repeated = true;
|
|
12
|
+
for (const character of buffer) if (character !== buffer[0]) {
|
|
13
|
+
repeated = false;
|
|
14
|
+
break;
|
|
15
|
+
}
|
|
16
|
+
const term = repeated ? buffer[0] : buffer;
|
|
17
|
+
let start = current;
|
|
18
|
+
if (repeated || current < 0) start = current + 1;
|
|
19
|
+
for (let offset = 0; offset < labels.length; offset++) {
|
|
20
|
+
const index = (start + offset) % labels.length;
|
|
21
|
+
if (labels[index].trim().toLowerCase().startsWith(term)) return index;
|
|
22
|
+
}
|
|
23
|
+
return -1;
|
|
24
|
+
}
|
|
25
|
+
function pending() {
|
|
26
|
+
return buffer !== "";
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
search,
|
|
30
|
+
pending
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function isTypeaheadKey(event) {
|
|
34
|
+
return event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey;
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export { isTypeaheadKey, useTypeahead };
|
package/package.json
CHANGED