@revojs/ui 0.2.61 → 0.2.63
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 +5 -1
- 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 +6 -3
- 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
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { IconComponent } from "./icon";
|
|
2
|
+
export type AccordionValue = string | number;
|
|
3
|
+
export interface AccordionItem<Value extends AccordionValue = AccordionValue> {
|
|
4
|
+
value: Value;
|
|
5
|
+
label: string;
|
|
6
|
+
iconPrefix?: IconComponent;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface AccordionProps<Value extends AccordionValue = AccordionValue> {
|
|
10
|
+
modelValue?: Array<Value>;
|
|
11
|
+
items: Array<AccordionItem<Value>>;
|
|
12
|
+
multiple?: boolean;
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { IconComponent } from "./icon";
|
|
2
|
+
import type { StackProps } from "./stack";
|
|
3
|
+
export interface CollapsibleProps {
|
|
4
|
+
modelValue?: boolean;
|
|
5
|
+
label: string;
|
|
6
|
+
iconPrefix?: IconComponent;
|
|
7
|
+
name?: string;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
bodyPadding?: StackProps["padding"];
|
|
10
|
+
bodyGap?: StackProps["gap"];
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type ConfirmVariant = "primary" | "destructive";
|
|
2
|
+
export interface ConfirmOptions {
|
|
3
|
+
label: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
confirmLabel?: string;
|
|
6
|
+
cancelLabel?: string;
|
|
7
|
+
variant?: ConfirmVariant;
|
|
8
|
+
}
|
|
9
|
+
export interface ConfirmRequest {
|
|
10
|
+
options: ConfirmOptions;
|
|
11
|
+
resolve: (value: boolean) => void;
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface UiLabels {
|
|
2
|
+
open: string;
|
|
3
|
+
close: string;
|
|
4
|
+
menu: string;
|
|
5
|
+
select: string;
|
|
6
|
+
selectRequired: string;
|
|
7
|
+
noResults: string;
|
|
8
|
+
empty: string;
|
|
9
|
+
previous: string;
|
|
10
|
+
next: string;
|
|
11
|
+
pagination: string;
|
|
12
|
+
pageNavigation: string;
|
|
13
|
+
fileSelected: string;
|
|
14
|
+
dropFile: string;
|
|
15
|
+
browseFiles: string;
|
|
16
|
+
removeFile: string;
|
|
17
|
+
decrease: string;
|
|
18
|
+
increase: string;
|
|
19
|
+
rating: (value: number, max: number) => string;
|
|
20
|
+
notifications: string;
|
|
21
|
+
confirm: string;
|
|
22
|
+
cancel: string;
|
|
23
|
+
remove: (label: string) => string;
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -2,6 +2,7 @@ import type { ButtonSize } from "./button";
|
|
|
2
2
|
import type { IconComponent } from "./icon";
|
|
3
3
|
import type { PopoverProps } from "./popover";
|
|
4
4
|
export type MenuItemVariant = "default" | "destructive";
|
|
5
|
+
export type MenuRadioValue = string | number;
|
|
5
6
|
export interface MenuProps extends Omit<PopoverProps, "contentRole" | "contentDirection" | "contentAlign" | "contentJustify" | "contentWrap"> {
|
|
6
7
|
itemSize?: ButtonSize;
|
|
7
8
|
}
|
|
@@ -14,3 +15,36 @@ export interface MenuItemProps {
|
|
|
14
15
|
size?: ButtonSize;
|
|
15
16
|
disabled?: boolean;
|
|
16
17
|
}
|
|
18
|
+
export interface MenuCheckboxItemProps {
|
|
19
|
+
modelValue?: boolean;
|
|
20
|
+
label?: string;
|
|
21
|
+
iconPrefix?: IconComponent;
|
|
22
|
+
size?: ButtonSize;
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface MenuRadioGroupProps<Value extends MenuRadioValue = MenuRadioValue> {
|
|
26
|
+
modelValue?: Value;
|
|
27
|
+
label?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface MenuRadioItemProps<Value extends MenuRadioValue = MenuRadioValue> {
|
|
30
|
+
value: Value;
|
|
31
|
+
label?: string;
|
|
32
|
+
iconPrefix?: IconComponent;
|
|
33
|
+
size?: ButtonSize;
|
|
34
|
+
disabled?: boolean;
|
|
35
|
+
}
|
|
36
|
+
export interface MenuGroupProps {
|
|
37
|
+
label?: string;
|
|
38
|
+
size?: ButtonSize;
|
|
39
|
+
}
|
|
40
|
+
export interface MenuLayerProps {
|
|
41
|
+
label: string;
|
|
42
|
+
iconPrefix?: IconComponent;
|
|
43
|
+
size?: ButtonSize;
|
|
44
|
+
disabled?: boolean;
|
|
45
|
+
}
|
|
46
|
+
export interface ContextMenuProps {
|
|
47
|
+
itemSize?: ButtonSize;
|
|
48
|
+
contentClass?: string;
|
|
49
|
+
disabled?: boolean;
|
|
50
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { RadioValue } from "./radio";
|
|
2
|
+
export type RadioGroupOrientation = "vertical" | "horizontal";
|
|
3
|
+
export interface RadioGroupOption<Value extends RadioValue = RadioValue> {
|
|
4
|
+
value: Value;
|
|
5
|
+
label: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface RadioGroupProps<Value extends RadioValue = RadioValue> {
|
|
10
|
+
modelValue?: Value;
|
|
11
|
+
options: Array<RadioGroupOption<Value>>;
|
|
12
|
+
label?: string;
|
|
13
|
+
name?: string;
|
|
14
|
+
orientation?: RadioGroupOrientation;
|
|
15
|
+
required?: boolean;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -8,6 +8,7 @@ export type SelectWidth = "full" | "fit";
|
|
|
8
8
|
export interface SelectOption<Value extends SelectValue = SelectValue> {
|
|
9
9
|
label: string;
|
|
10
10
|
value: Value;
|
|
11
|
+
group?: string;
|
|
11
12
|
disabled?: boolean;
|
|
12
13
|
}
|
|
13
14
|
export interface SelectProps<Value extends SelectValue = SelectValue> {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type StepperValue = string | number;
|
|
2
|
+
export type StepperOrientation = "horizontal" | "vertical";
|
|
3
|
+
export type StepperState = "complete" | "current" | "upcoming";
|
|
4
|
+
export interface StepperItem<Value extends StepperValue = StepperValue> {
|
|
5
|
+
value: Value;
|
|
6
|
+
label: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface StepperProps<Value extends StepperValue = StepperValue> {
|
|
11
|
+
modelValue?: Value;
|
|
12
|
+
items: Array<StepperItem<Value>>;
|
|
13
|
+
label?: string;
|
|
14
|
+
orientation?: StepperOrientation;
|
|
15
|
+
linear?: boolean;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { IconComponent } from "./icon";
|
|
2
2
|
export type TabsValue = string | number;
|
|
3
|
-
export type TabsSize = "md" | "xs";
|
|
3
|
+
export type TabsSize = "md" | "sm" | "xs";
|
|
4
|
+
export type TabsOrientation = "horizontal" | "vertical";
|
|
5
|
+
export type TabsActivation = "automatic" | "manual";
|
|
4
6
|
export interface TabsItem<Value extends TabsValue = TabsValue> {
|
|
5
7
|
value: Value;
|
|
6
8
|
label: string;
|
|
@@ -12,4 +14,6 @@ export interface TabsProps<Value extends TabsValue = TabsValue> {
|
|
|
12
14
|
items: Array<TabsItem<Value>>;
|
|
13
15
|
label?: string;
|
|
14
16
|
size?: TabsSize;
|
|
17
|
+
orientation?: TabsOrientation;
|
|
18
|
+
activation?: TabsActivation;
|
|
15
19
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { NotificationVariant } from "./notification";
|
|
2
|
+
export interface ToastAction {
|
|
3
|
+
label: string;
|
|
4
|
+
onSelect: () => void;
|
|
5
|
+
}
|
|
6
|
+
export interface ToastOptions {
|
|
7
|
+
label: string;
|
|
8
|
+
subtext?: string;
|
|
9
|
+
variant?: NotificationVariant;
|
|
10
|
+
duration?: number;
|
|
11
|
+
action?: ToastAction;
|
|
12
|
+
}
|
|
13
|
+
export interface Toast extends ToastOptions {
|
|
14
|
+
id: string;
|
|
15
|
+
}
|
|
16
|
+
export interface ToastRegionProps {
|
|
17
|
+
label?: string;
|
|
18
|
+
hotkey?: string;
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import type { IconComponent } from "./icon";
|
|
2
|
+
import type { RovingFocusOrientation } from "./roving-focus";
|
|
2
3
|
export type ToggleGroupValue = string | number;
|
|
3
|
-
export type ToggleGroupSize = "md" | "xs";
|
|
4
|
+
export type ToggleGroupSize = "md" | "sm" | "xs";
|
|
4
5
|
export interface ToggleGroupItem<Value extends ToggleGroupValue = ToggleGroupValue> {
|
|
5
6
|
value: Value;
|
|
6
7
|
label?: string;
|
|
7
8
|
iconPrefix?: IconComponent;
|
|
8
9
|
disabled?: boolean;
|
|
9
10
|
}
|
|
10
|
-
export interface ToggleGroupProps<Value extends ToggleGroupValue = ToggleGroupValue> {
|
|
11
|
-
modelValue?:
|
|
11
|
+
export interface ToggleGroupProps<Value extends ToggleGroupValue = ToggleGroupValue, Model extends Value | Array<Value> = Value> {
|
|
12
|
+
modelValue?: Model;
|
|
12
13
|
items: Array<ToggleGroupItem<Value>>;
|
|
13
14
|
label?: string;
|
|
14
15
|
size?: ToggleGroupSize;
|
|
15
16
|
wrap?: boolean;
|
|
17
|
+
multiple?: boolean;
|
|
18
|
+
orientation?: Exclude<RovingFocusOrientation, "both">;
|
|
16
19
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { RovingFocusOrientation } from "./roving-focus";
|
|
2
|
+
import type { StackProps } from "./stack";
|
|
3
|
+
export interface ToolbarProps {
|
|
4
|
+
label?: string;
|
|
5
|
+
orientation?: Exclude<RovingFocusOrientation, "both">;
|
|
6
|
+
gap?: StackProps["gap"];
|
|
7
|
+
padding?: StackProps["padding"];
|
|
8
|
+
align?: StackProps["align"];
|
|
9
|
+
justify?: StackProps["justify"];
|
|
10
|
+
wrap?: boolean;
|
|
11
|
+
loop?: boolean;
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,37 +1,47 @@
|
|
|
1
|
+
export type * from "./components/accordion";
|
|
1
2
|
export type * from "./components/badge";
|
|
2
3
|
export type * from "./components/breadcrumb";
|
|
3
4
|
export type * from "./components/button";
|
|
4
5
|
export type * from "./components/card";
|
|
5
6
|
export type * from "./components/checkbox";
|
|
7
|
+
export type * from "./components/collapsible";
|
|
6
8
|
export type * from "./components/collection";
|
|
9
|
+
export type * from "./components/confirm";
|
|
7
10
|
export type * from "./components/container";
|
|
8
11
|
export type * from "./components/control";
|
|
9
12
|
export type * from "./components/counter";
|
|
10
13
|
export type * from "./components/dialog";
|
|
14
|
+
export type * from "./components/entry";
|
|
11
15
|
export type * from "./components/field";
|
|
12
16
|
export type * from "./components/heading";
|
|
13
|
-
export type * from "./components/shell";
|
|
14
17
|
export type * from "./components/icon";
|
|
15
18
|
export type * from "./components/input";
|
|
19
|
+
export type * from "./components/labels";
|
|
16
20
|
export type * from "./components/link";
|
|
17
21
|
export type * from "./components/markdown";
|
|
18
22
|
export type * from "./components/menu";
|
|
19
|
-
export type * from "./components/entry";
|
|
20
|
-
export type * from "./components/notification";
|
|
21
23
|
export type * from "./components/navigate";
|
|
22
|
-
export type * from "./components/
|
|
24
|
+
export type * from "./components/notification";
|
|
23
25
|
export type * from "./components/pagination";
|
|
26
|
+
export type * from "./components/popover";
|
|
24
27
|
export type * from "./components/progress";
|
|
25
28
|
export type * from "./components/radio";
|
|
29
|
+
export type * from "./components/radio-group";
|
|
26
30
|
export type * from "./components/range";
|
|
27
31
|
export type * from "./components/rating";
|
|
32
|
+
export type * from "./components/roving-focus";
|
|
28
33
|
export type * from "./components/select";
|
|
29
34
|
export type * from "./components/separator";
|
|
30
35
|
export type * from "./components/sheet";
|
|
36
|
+
export type * from "./components/shell";
|
|
31
37
|
export type * from "./components/stack";
|
|
38
|
+
export type * from "./components/stepper";
|
|
32
39
|
export type * from "./components/switch";
|
|
33
40
|
export type * from "./components/tabs";
|
|
34
|
-
export type * from "./components/
|
|
41
|
+
export type * from "./components/tags-input";
|
|
35
42
|
export type * from "./components/textarea";
|
|
43
|
+
export type * from "./components/toast";
|
|
36
44
|
export type * from "./components/toggle-group";
|
|
45
|
+
export type * from "./components/toolbar";
|
|
37
46
|
export type * from "./components/tooltip";
|
|
47
|
+
export type * from "./components/upload";
|
package/dist/style.css
CHANGED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Stack gap="1">
|
|
3
|
+
<Collapsible
|
|
4
|
+
v-for="item in items"
|
|
5
|
+
:key="item.value"
|
|
6
|
+
:model-value="opened.includes(item.value)"
|
|
7
|
+
:label="item.label"
|
|
8
|
+
:icon-prefix="item.iconPrefix"
|
|
9
|
+
:disabled="item.disabled"
|
|
10
|
+
:name="multiple ? undefined : name"
|
|
11
|
+
@update:model-value="toggle(item.value, $event)"
|
|
12
|
+
>
|
|
13
|
+
<slot :item="item" />
|
|
14
|
+
</Collapsible>
|
|
15
|
+
</Stack>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<script setup lang="ts" generic="Value extends AccordionValue = AccordionValue">
|
|
19
|
+
import { ref, useId, watch } from "vue";
|
|
20
|
+
import type { AccordionProps, AccordionValue } from "../../components/accordion";
|
|
21
|
+
import Collapsible from "./collapsible.vue";
|
|
22
|
+
import Stack from "./stack.vue";
|
|
23
|
+
|
|
24
|
+
const { modelValue, items, multiple = false } = defineProps<AccordionProps<Value>>();
|
|
25
|
+
|
|
26
|
+
const emit = defineEmits<{
|
|
27
|
+
"update:modelValue": [value: Array<Value>];
|
|
28
|
+
}>();
|
|
29
|
+
|
|
30
|
+
const name = useId();
|
|
31
|
+
|
|
32
|
+
const opened = ref<Array<AccordionValue>>([...(modelValue ?? [])]);
|
|
33
|
+
|
|
34
|
+
function toggle(value: Value, open: boolean) {
|
|
35
|
+
const values: Array<Value> = [];
|
|
36
|
+
|
|
37
|
+
for (const entry of opened.value as Array<Value>) {
|
|
38
|
+
if (entry !== value && (multiple || open === false)) {
|
|
39
|
+
values.push(entry);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (open) {
|
|
44
|
+
values.push(value);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
opened.value = values;
|
|
48
|
+
emit("update:modelValue", values);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
watch(
|
|
52
|
+
() => modelValue,
|
|
53
|
+
(value) => {
|
|
54
|
+
opened.value = [...(value ?? [])];
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
</script>
|
|
@@ -8,9 +8,11 @@
|
|
|
8
8
|
:class="interactionVariants[interaction]"
|
|
9
9
|
>
|
|
10
10
|
<input
|
|
11
|
+
ref="input"
|
|
11
12
|
class="peer sr-only"
|
|
12
13
|
type="checkbox"
|
|
13
14
|
:checked="modelValue"
|
|
15
|
+
:data-state="state"
|
|
14
16
|
:name="name"
|
|
15
17
|
:required="required"
|
|
16
18
|
:disabled="disabled"
|
|
@@ -21,16 +23,17 @@
|
|
|
21
23
|
aria-hidden="true"
|
|
22
24
|
class="mt-0.5 flex size-5 shrink-0 items-center justify-center rounded-ui border peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-ring"
|
|
23
25
|
:class="[
|
|
24
|
-
modelValue ? 'border-transparent bg-primary' : 'border-input bg-background',
|
|
26
|
+
modelValue || indeterminate ? 'border-transparent bg-primary' : 'border-input bg-background',
|
|
25
27
|
disabled
|
|
26
28
|
? ''
|
|
27
|
-
: modelValue
|
|
29
|
+
: modelValue || indeterminate
|
|
28
30
|
? 'group-hover:bg-primary-hover group-active:bg-primary-active'
|
|
29
31
|
: 'group-hover:bg-secondary-hover group-active:bg-secondary-active',
|
|
30
32
|
]"
|
|
31
33
|
>
|
|
34
|
+
<span v-if="indeterminate" class="h-0.5 w-2.5 bg-primary-foreground" />
|
|
32
35
|
<span
|
|
33
|
-
v-if="modelValue"
|
|
36
|
+
v-else-if="modelValue"
|
|
34
37
|
class="mb-px h-2.5 w-1.5 rotate-45 border-b-2 border-r-2 border-primary-foreground"
|
|
35
38
|
/>
|
|
36
39
|
</span>
|
|
@@ -45,13 +48,14 @@
|
|
|
45
48
|
</template>
|
|
46
49
|
|
|
47
50
|
<script setup lang="ts">
|
|
48
|
-
import { computed } from "vue";
|
|
51
|
+
import { computed, useTemplateRef, watchEffect } from "vue";
|
|
49
52
|
import type { CheckboxProps } from "../../components/checkbox";
|
|
50
53
|
import type { ControlInteraction } from "../../components/control.ts";
|
|
51
54
|
import Stack from "./stack.vue";
|
|
52
55
|
|
|
53
56
|
const {
|
|
54
57
|
modelValue = false,
|
|
58
|
+
indeterminate = false,
|
|
55
59
|
label,
|
|
56
60
|
description,
|
|
57
61
|
name,
|
|
@@ -63,6 +67,22 @@ defineEmits<{
|
|
|
63
67
|
"update:modelValue": [value: boolean];
|
|
64
68
|
}>();
|
|
65
69
|
|
|
70
|
+
const input = useTemplateRef("input");
|
|
71
|
+
|
|
72
|
+
const state = computed(() => {
|
|
73
|
+
if (indeterminate) {
|
|
74
|
+
return "indeterminate";
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return modelValue ? "checked" : "unchecked";
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
watchEffect(() => {
|
|
81
|
+
if (input.value) {
|
|
82
|
+
input.value.indeterminate = indeterminate;
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
66
86
|
const interaction = computed<ControlInteraction>(() => (disabled ? "disabled" : "enabled"));
|
|
67
87
|
|
|
68
88
|
const interactionVariants: Record<ControlInteraction, string> = {
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<details
|
|
3
|
+
:name="name"
|
|
4
|
+
:open="isOpen"
|
|
5
|
+
class="group/collapsible w-full rounded-ui"
|
|
6
|
+
:data-state="isOpen ? 'open' : 'closed'"
|
|
7
|
+
:data-disabled="disabled ? '' : undefined"
|
|
8
|
+
@toggle="handleToggle"
|
|
9
|
+
>
|
|
10
|
+
<summary
|
|
11
|
+
class="flex cursor-pointer list-none items-center gap-1 rounded-ui p-3 text-sm font-medium outline-ring select-none hover:bg-ghost-hover active:bg-ghost-active focus-visible:outline-2 focus-visible:outline-offset-[-2px] [&::-webkit-details-marker]:hidden"
|
|
12
|
+
:class="disabled ? 'cursor-not-allowed opacity-50 hover:bg-transparent active:bg-transparent' : ''"
|
|
13
|
+
:tabindex="disabled ? -1 : undefined"
|
|
14
|
+
:aria-disabled="disabled || undefined"
|
|
15
|
+
@click="disabled && $event.preventDefault()"
|
|
16
|
+
>
|
|
17
|
+
<Icon v-if="iconPrefix" :is="iconPrefix" :size="20" />
|
|
18
|
+
|
|
19
|
+
<span class="min-w-0 flex-1 truncate px-1">{{ label }}</span>
|
|
20
|
+
|
|
21
|
+
<Icon :is="ArrowDownIcon" :size="20" class="shrink-0 group-open/collapsible:rotate-180" />
|
|
22
|
+
</summary>
|
|
23
|
+
|
|
24
|
+
<Stack :padding="bodyPadding">
|
|
25
|
+
<Stack :gap="bodyGap" class="px-1">
|
|
26
|
+
<slot />
|
|
27
|
+
</Stack>
|
|
28
|
+
</Stack>
|
|
29
|
+
</details>
|
|
30
|
+
</template>
|
|
31
|
+
|
|
32
|
+
<script setup lang="ts">
|
|
33
|
+
import ArrowDownIcon from "~icons/hugeicons/arrow-down-01";
|
|
34
|
+
import { ref, watch } from "vue";
|
|
35
|
+
import type { CollapsibleProps } from "../../components/collapsible";
|
|
36
|
+
import Icon from "./icon.vue";
|
|
37
|
+
import Stack from "./stack.vue";
|
|
38
|
+
|
|
39
|
+
const {
|
|
40
|
+
modelValue = undefined,
|
|
41
|
+
label,
|
|
42
|
+
iconPrefix,
|
|
43
|
+
name,
|
|
44
|
+
disabled = false,
|
|
45
|
+
bodyPadding = "3",
|
|
46
|
+
bodyGap = "3",
|
|
47
|
+
} = defineProps<CollapsibleProps>();
|
|
48
|
+
|
|
49
|
+
const emit = defineEmits<{
|
|
50
|
+
"update:modelValue": [value: boolean];
|
|
51
|
+
}>();
|
|
52
|
+
|
|
53
|
+
const isOpen = ref(modelValue ?? false);
|
|
54
|
+
|
|
55
|
+
function handleToggle(event: Event) {
|
|
56
|
+
const value = (event.currentTarget as HTMLDetailsElement).open;
|
|
57
|
+
|
|
58
|
+
if (value !== isOpen.value) {
|
|
59
|
+
isOpen.value = value;
|
|
60
|
+
emit("update:modelValue", value);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
watch(
|
|
65
|
+
() => modelValue,
|
|
66
|
+
(value) => {
|
|
67
|
+
if (value !== undefined) {
|
|
68
|
+
isOpen.value = value;
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
);
|
|
72
|
+
</script>
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<slot v-else name="empty">
|
|
13
13
|
<Stack padding="1">
|
|
14
14
|
<Stack padding="3" align="center" class="text-sm text-muted-foreground">
|
|
15
|
-
<span>{{ emptyLabel }}</span>
|
|
15
|
+
<span>{{ emptyLabel ?? labels.empty }}</span>
|
|
16
16
|
</Stack>
|
|
17
17
|
</Stack>
|
|
18
18
|
</slot>
|
|
@@ -25,9 +25,12 @@
|
|
|
25
25
|
<script setup generic="T" lang="ts">
|
|
26
26
|
import type { CollectionColumns, CollectionProps } from "../../components/collection";
|
|
27
27
|
import type { StackGap } from "../../components/stack";
|
|
28
|
+
import { useUiLabels } from "../utilities/labels";
|
|
28
29
|
import Stack from "./stack.vue";
|
|
29
30
|
|
|
30
|
-
const { items, columns = 1, gap = "5", itemKey, emptyLabel
|
|
31
|
+
const { items, columns = 1, gap = "5", itemKey, emptyLabel } = defineProps<CollectionProps<T>>();
|
|
32
|
+
|
|
33
|
+
const labels = useUiLabels();
|
|
31
34
|
|
|
32
35
|
defineSlots<{
|
|
33
36
|
default: (() => unknown) & ((props: { item: T; index: number }) => unknown);
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Dialog
|
|
3
|
+
:model-value="request !== undefined"
|
|
4
|
+
role="alertdialog"
|
|
5
|
+
:label="request?.options.label"
|
|
6
|
+
:aria-describedby="request?.options.description ? descriptionId : undefined"
|
|
7
|
+
@update:model-value="!$event && answer(false)"
|
|
8
|
+
>
|
|
9
|
+
<p v-if="request?.options.description" :id="descriptionId" class="text-sm text-muted-foreground">
|
|
10
|
+
{{ request.options.description }}
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<template #footer>
|
|
14
|
+
<Stack direction="horizontal" justify="end" gap="1" wrap class="w-full">
|
|
15
|
+
<Button
|
|
16
|
+
autofocus
|
|
17
|
+
variant="outline"
|
|
18
|
+
:label="request?.options.cancelLabel ?? labels.cancel"
|
|
19
|
+
@click="answer(false)"
|
|
20
|
+
/>
|
|
21
|
+
|
|
22
|
+
<Button
|
|
23
|
+
:variant="request?.options.variant ?? 'primary'"
|
|
24
|
+
:label="request?.options.confirmLabel ?? labels.confirm"
|
|
25
|
+
@click="answer(true)"
|
|
26
|
+
/>
|
|
27
|
+
</Stack>
|
|
28
|
+
</template>
|
|
29
|
+
</Dialog>
|
|
30
|
+
</template>
|
|
31
|
+
|
|
32
|
+
<script setup lang="ts">
|
|
33
|
+
import { useId } from "vue";
|
|
34
|
+
import { useUiLabels } from "../utilities/labels";
|
|
35
|
+
import { useConfirm } from "../utilities/use-confirm";
|
|
36
|
+
import Button from "./button.vue";
|
|
37
|
+
import Dialog from "./dialog.vue";
|
|
38
|
+
import Stack from "./stack.vue";
|
|
39
|
+
|
|
40
|
+
const labels = useUiLabels();
|
|
41
|
+
|
|
42
|
+
const { request, answer } = useConfirm();
|
|
43
|
+
|
|
44
|
+
const descriptionId = useId();
|
|
45
|
+
</script>
|