@sewadah/selaras 0.7.1 → 0.8.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.
Files changed (44) hide show
  1. package/dist/agent/catalog.json +1 -1
  2. package/dist/module.json +1 -1
  3. package/dist/runtime/components/AvatarGroup.vue +3 -2
  4. package/dist/runtime/components/CodeGroup.vue +3 -15
  5. package/dist/runtime/components/ColorModeSwitch.vue +5 -4
  6. package/dist/runtime/components/ColorModeToggle.vue +5 -4
  7. package/dist/runtime/components/Listbox.d.vue.ts +28 -0
  8. package/dist/runtime/components/Listbox.vue +53 -0
  9. package/dist/runtime/components/Listbox.vue.d.ts +28 -0
  10. package/dist/runtime/components/TransferList.d.vue.ts +47 -0
  11. package/dist/runtime/components/TransferList.vue +67 -0
  12. package/dist/runtime/components/TransferList.vue.d.ts +47 -0
  13. package/dist/runtime/internal/ListSelectionForm.d.vue.ts +15 -0
  14. package/dist/runtime/internal/ListSelectionForm.vue +33 -0
  15. package/dist/runtime/internal/ListSelectionForm.vue.d.ts +15 -0
  16. package/dist/runtime/internal/ListboxBase.d.vue.ts +49 -0
  17. package/dist/runtime/internal/ListboxBase.vue +177 -0
  18. package/dist/runtime/internal/ListboxBase.vue.d.ts +49 -0
  19. package/dist/runtime/internal/ListboxOption.d.vue.ts +31 -0
  20. package/dist/runtime/internal/ListboxOption.vue +37 -0
  21. package/dist/runtime/internal/ListboxOption.vue.d.ts +31 -0
  22. package/dist/runtime/internal/TransferListBase.d.vue.ts +63 -0
  23. package/dist/runtime/internal/TransferListBase.vue +206 -0
  24. package/dist/runtime/internal/TransferListBase.vue.d.ts +63 -0
  25. package/dist/runtime/internal/color-mode-control.d.ts +7 -0
  26. package/dist/runtime/internal/color-mode-control.js +12 -0
  27. package/dist/runtime/internal/list-selection.d.ts +15 -0
  28. package/dist/runtime/internal/list-selection.js +43 -0
  29. package/dist/runtime/theme/listbox.d.ts +131 -0
  30. package/dist/runtime/theme/listbox.js +27 -0
  31. package/dist/runtime/theme/select.js +1 -1
  32. package/dist/runtime/theme/transfer-list.d.ts +74 -0
  33. package/dist/runtime/theme/transfer-list.js +21 -0
  34. package/dist/runtime/theme-config.d.ts +10 -0
  35. package/dist/runtime/types/index.d.ts +2 -0
  36. package/dist/runtime/utils/listbox-contracts.d.ts +31 -0
  37. package/dist/runtime/utils/listbox-contracts.js +0 -0
  38. package/dist/runtime/utils/messages.d.ts +7 -0
  39. package/dist/runtime/utils/messages.js +7 -0
  40. package/dist/runtime/utils/slot-children.d.ts +2 -0
  41. package/dist/runtime/utils/slot-children.js +15 -0
  42. package/dist/runtime/utils/transfer-list-contracts.d.ts +48 -0
  43. package/dist/runtime/utils/transfer-list-contracts.js +0 -0
  44. package/package.json +1 -1
@@ -0,0 +1,7 @@
1
+ import type { ComputedRef } from 'vue';
2
+ import { useColorMode } from '#imports';
3
+ export declare function useColorModeControl(): {
4
+ colorMode: ReturnType<typeof useColorMode>;
5
+ isDark: ComputedRef<boolean>;
6
+ isDisabled: ComputedRef<boolean>;
7
+ };
@@ -0,0 +1,12 @@
1
+ import { computed, onMounted, ref } from "vue";
2
+ import { useColorMode } from "#imports";
3
+ export function useColorModeControl() {
4
+ const colorMode = useColorMode();
5
+ const mounted = ref(false);
6
+ onMounted(() => mounted.value = true);
7
+ return {
8
+ colorMode,
9
+ isDark: computed(() => mounted.value && colorMode.value === "dark"),
10
+ isDisabled: computed(() => !mounted.value || colorMode.unknown || colorMode.forced)
11
+ };
12
+ }
@@ -0,0 +1,15 @@
1
+ import type { SelectModelValue } from '../utils/select-contracts.js';
2
+ export type ListSelection = SelectModelValue | SelectModelValue[] | undefined;
3
+ export declare function selectionForMode(value: ListSelection, multiple: boolean): ListSelection;
4
+ export declare function assertUniqueSelection(value: ListSelection): void;
5
+ export declare function useListSelection(props: {
6
+ modelValue?: ListSelection;
7
+ defaultValue?: ListSelection;
8
+ multiple?: boolean;
9
+ disabled?: boolean;
10
+ }, emit: (value: ListSelection) => void): {
11
+ selection: import("vue").ComputedRef<string | number | object | undefined>;
12
+ values: import("vue").ComputedRef<SelectModelValue[]>;
13
+ update: (value: ListSelection) => void;
14
+ reset: () => void;
15
+ };
@@ -0,0 +1,43 @@
1
+ import { computed, getCurrentInstance, ref, watch } from "vue";
2
+ export function selectionForMode(value, multiple) {
3
+ return multiple ? value === void 0 ? [] : Array.isArray(value) ? [...value] : [value] : Array.isArray(value) ? value[0] : value;
4
+ }
5
+ export function assertUniqueSelection(value) {
6
+ if (Array.isArray(value) && new Set(value).size !== value.length)
7
+ throw new TypeError("[selaras] List selection values must be unique.");
8
+ }
9
+ export function useListSelection(props, emit) {
10
+ const instance = getCurrentInstance();
11
+ const controlled = () => Object.hasOwn(instance.vnode.props ?? {}, "modelValue") || Object.hasOwn(instance.vnode.props ?? {}, "model-value");
12
+ const initial = Array.isArray(props.defaultValue) ? [...props.defaultValue] : props.defaultValue;
13
+ assertUniqueSelection(initial);
14
+ const local = ref(selectionForMode(initial, !!props.multiple));
15
+ const selection = computed(() => {
16
+ const value = controlled() ? props.modelValue : local.value;
17
+ if (controlled() && value !== void 0 && Array.isArray(value) !== !!props.multiple)
18
+ throw new TypeError("[selaras] List modelValue must be an array in multiple mode and a scalar in single mode.");
19
+ assertUniqueSelection(value);
20
+ return value;
21
+ });
22
+ void selection.value;
23
+ function update(value) {
24
+ if (props.disabled)
25
+ return;
26
+ assertUniqueSelection(value);
27
+ if (!controlled())
28
+ local.value = value;
29
+ emit(value);
30
+ }
31
+ watch(() => props.multiple, (multiple) => {
32
+ if (!controlled())
33
+ update(selectionForMode(local.value, !!multiple));
34
+ });
35
+ function reset() {
36
+ const value = selectionForMode(initial, !!props.multiple);
37
+ if (!controlled())
38
+ local.value = value;
39
+ emit(value);
40
+ }
41
+ const values = computed(() => selection.value === void 0 ? [] : Array.isArray(selection.value) ? selection.value : [selection.value]);
42
+ return { selection, values, update, reset };
43
+ }
@@ -0,0 +1,131 @@
1
+ export declare const listboxTheme: import("tailwind-variants").TVReturnType<{
2
+ size: {
3
+ sm: {
4
+ item: string;
5
+ };
6
+ md: {
7
+ item: string;
8
+ };
9
+ lg: {
10
+ item: string;
11
+ };
12
+ };
13
+ color: {
14
+ primary: "";
15
+ secondary: "";
16
+ neutral: "";
17
+ success: "";
18
+ danger: "";
19
+ info: "";
20
+ warning: "";
21
+ };
22
+ invalid: {
23
+ true: {
24
+ root: string;
25
+ };
26
+ };
27
+ }, {
28
+ root: string;
29
+ header: string;
30
+ footer: string;
31
+ searchWrapper: string;
32
+ searchInput: string;
33
+ content: string;
34
+ group: string;
35
+ groupLabel: string;
36
+ item: string;
37
+ label: string;
38
+ description: string;
39
+ itemContent: string;
40
+ icon: string;
41
+ indicator: string;
42
+ checkbox: string;
43
+ empty: string;
44
+ }, undefined, {
45
+ size: {
46
+ sm: {
47
+ item: string;
48
+ };
49
+ md: {
50
+ item: string;
51
+ };
52
+ lg: {
53
+ item: string;
54
+ };
55
+ };
56
+ color: {
57
+ primary: "";
58
+ secondary: "";
59
+ neutral: "";
60
+ success: "";
61
+ danger: "";
62
+ info: "";
63
+ warning: "";
64
+ };
65
+ invalid: {
66
+ true: {
67
+ root: string;
68
+ };
69
+ };
70
+ }, {
71
+ root: string;
72
+ header: string;
73
+ footer: string;
74
+ searchWrapper: string;
75
+ searchInput: string;
76
+ content: string;
77
+ group: string;
78
+ groupLabel: string;
79
+ item: string;
80
+ label: string;
81
+ description: string;
82
+ itemContent: string;
83
+ icon: string;
84
+ indicator: string;
85
+ checkbox: string;
86
+ empty: string;
87
+ }, import("tailwind-variants").TVReturnTypeLike<{
88
+ size: {
89
+ sm: {
90
+ item: string;
91
+ };
92
+ md: {
93
+ item: string;
94
+ };
95
+ lg: {
96
+ item: string;
97
+ };
98
+ };
99
+ color: {
100
+ primary: "";
101
+ secondary: "";
102
+ neutral: "";
103
+ success: "";
104
+ danger: "";
105
+ info: "";
106
+ warning: "";
107
+ };
108
+ invalid: {
109
+ true: {
110
+ root: string;
111
+ };
112
+ };
113
+ }, {
114
+ root: string;
115
+ header: string;
116
+ footer: string;
117
+ searchWrapper: string;
118
+ searchInput: string;
119
+ content: string;
120
+ group: string;
121
+ groupLabel: string;
122
+ item: string;
123
+ label: string;
124
+ description: string;
125
+ itemContent: string;
126
+ icon: string;
127
+ indicator: string;
128
+ checkbox: string;
129
+ empty: string;
130
+ }>>;
131
+ export type ListboxThemeSlots = keyof (typeof listboxTheme)['slots'];
@@ -0,0 +1,27 @@
1
+ import { tv } from "tailwind-variants";
2
+ export const listboxTheme = tv({
3
+ slots: {
4
+ root: "flex min-h-0 min-w-0 flex-col overflow-hidden rounded-[var(--selaras-resolved-radius-md)] border border-[var(--selaras-resolved-border-default)] bg-[var(--selaras-resolved-surface-default)] text-[var(--selaras-resolved-text-default)]",
5
+ header: "flex items-center justify-between gap-2 border-b border-[var(--selaras-resolved-border-default)] px-3 py-2",
6
+ footer: "border-t border-[var(--selaras-resolved-border-default)] px-3 py-2",
7
+ searchWrapper: "flex items-center gap-2 border-b border-[var(--selaras-resolved-border-default)] px-3",
8
+ searchInput: "h-10 min-w-0 flex-1 bg-transparent text-sm outline-none placeholder:text-[var(--selaras-resolved-text-muted)]",
9
+ content: "max-h-72 min-h-0 overflow-y-auto p-1 outline-none focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-[var(--_selaras-color-focus)]",
10
+ group: "",
11
+ groupLabel: "px-2 py-2 text-xs font-medium text-[var(--selaras-resolved-text-muted)]",
12
+ item: "my-0.5 flex w-full min-w-0 items-center gap-2 rounded-[var(--selaras-resolved-radius-sm)] px-2 py-2 outline-none cursor-pointer select-none transition-colors data-[highlighted]:bg-[var(--selaras-resolved-surface-elevated)] data-[state=checked]:bg-[var(--_selaras-color-subtle)] data-[state=checked]:text-[var(--_selaras-color-on-subtle)] data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
13
+ label: "truncate",
14
+ description: "text-xs text-[var(--selaras-resolved-text-muted)]",
15
+ itemContent: "flex min-w-0 flex-1 flex-col gap-0.5",
16
+ icon: "size-4 shrink-0",
17
+ indicator: "ms-auto flex size-4 shrink-0 items-center justify-center text-[var(--_selaras-color-indicator)]",
18
+ checkbox: "pointer-events-none flex size-4 shrink-0 items-center justify-center rounded-[var(--selaras-resolved-radius-sm)] border border-[var(--selaras-resolved-border-default)] data-[state=checked]:border-[var(--_selaras-color-fill)] data-[state=checked]:bg-[var(--_selaras-color-fill)] data-[state=checked]:text-[var(--_selaras-color-on-fill)]",
19
+ empty: "px-3 py-6 text-center text-sm text-[var(--selaras-resolved-text-muted)]"
20
+ },
21
+ variants: {
22
+ size: { sm: { item: "py-1.5 text-xs" }, md: { item: "text-sm" }, lg: { item: "py-2.5 text-base" } },
23
+ color: { primary: "", secondary: "", neutral: "", success: "", danger: "", info: "", warning: "" },
24
+ invalid: { true: { root: "border-[var(--_selaras-color-border)]" } }
25
+ },
26
+ defaultVariants: { size: "md", color: "primary" }
27
+ });
@@ -40,7 +40,7 @@ export const selectTheme = tv({
40
40
  mobilePanel: "",
41
41
  viewport: "max-h-72 overflow-y-auto p-1",
42
42
  group: "px-2 pt-2 pb-1 text-xs font-medium text-[var(--selaras-resolved-text-muted)]",
43
- item: "relative flex items-center gap-2 rounded-[var(--selaras-resolved-radius-sm)] py-1.5 ps-2 pe-8 text-sm text-[var(--selaras-resolved-text-default)] outline-none cursor-pointer select-none data-[highlighted]:bg-[var(--selaras-resolved-surface-elevated)] data-[disabled]:opacity-50 data-[disabled]:pointer-events-none",
43
+ item: "relative my-0.5 flex w-full min-w-0 items-center gap-2 rounded-[var(--selaras-resolved-radius-sm)] py-1.5 ps-2 pe-8 text-sm text-[var(--selaras-resolved-text-default)] outline-none cursor-pointer select-none transition-colors data-[highlighted]:bg-[var(--selaras-resolved-surface-elevated)] data-[state=checked]:bg-[var(--_selaras-color-subtle)] data-[state=checked]:text-[var(--_selaras-color-on-subtle)] data-[disabled]:opacity-50 data-[disabled]:pointer-events-none",
44
44
  itemIndicator: "absolute end-2 flex items-center text-[var(--_selaras-color-indicator)]",
45
45
  empty: "px-2 py-6 text-center text-sm text-[var(--selaras-resolved-text-muted)]",
46
46
  arrow: "fill-[var(--selaras-resolved-surface-default)] stroke-[var(--selaras-resolved-border-default)] stroke-1"
@@ -0,0 +1,74 @@
1
+ export declare const transferListTheme: import("tailwind-variants").TVReturnType<{
2
+ layout: {
3
+ auto: {
4
+ root: string;
5
+ actions: string;
6
+ };
7
+ horizontal: {
8
+ root: string;
9
+ actions: string;
10
+ };
11
+ vertical: {
12
+ root: string;
13
+ actions: string;
14
+ };
15
+ };
16
+ }, {
17
+ root: string;
18
+ panel: string;
19
+ header: string;
20
+ count: string;
21
+ listbox: string;
22
+ actions: string;
23
+ action: string;
24
+ announcement: string;
25
+ }, undefined, {
26
+ layout: {
27
+ auto: {
28
+ root: string;
29
+ actions: string;
30
+ };
31
+ horizontal: {
32
+ root: string;
33
+ actions: string;
34
+ };
35
+ vertical: {
36
+ root: string;
37
+ actions: string;
38
+ };
39
+ };
40
+ }, {
41
+ root: string;
42
+ panel: string;
43
+ header: string;
44
+ count: string;
45
+ listbox: string;
46
+ actions: string;
47
+ action: string;
48
+ announcement: string;
49
+ }, import("tailwind-variants").TVReturnTypeLike<{
50
+ layout: {
51
+ auto: {
52
+ root: string;
53
+ actions: string;
54
+ };
55
+ horizontal: {
56
+ root: string;
57
+ actions: string;
58
+ };
59
+ vertical: {
60
+ root: string;
61
+ actions: string;
62
+ };
63
+ };
64
+ }, {
65
+ root: string;
66
+ panel: string;
67
+ header: string;
68
+ count: string;
69
+ listbox: string;
70
+ actions: string;
71
+ action: string;
72
+ announcement: string;
73
+ }>>;
74
+ export type TransferListThemeSlots = keyof (typeof transferListTheme)['slots'];
@@ -0,0 +1,21 @@
1
+ import { tv } from "tailwind-variants";
2
+ export const transferListTheme = tv({
3
+ slots: {
4
+ root: "flex min-w-0 gap-3",
5
+ panel: "flex min-w-0 flex-1 flex-col gap-2",
6
+ header: "flex items-center justify-between gap-2 text-sm font-medium text-[var(--selaras-resolved-text-default)]",
7
+ count: "text-xs font-normal text-[var(--selaras-resolved-text-muted)]",
8
+ listbox: "flex-1",
9
+ actions: "flex shrink-0 items-center justify-center gap-2",
10
+ action: "",
11
+ announcement: "sr-only"
12
+ },
13
+ variants: {
14
+ layout: {
15
+ auto: { root: "flex-col sm:flex-row", actions: "flex-row sm:flex-col" },
16
+ horizontal: { root: "flex-row", actions: "flex-col" },
17
+ vertical: { root: "flex-col", actions: "flex-row" }
18
+ }
19
+ },
20
+ defaultVariants: { layout: "auto" }
21
+ });
@@ -41,6 +41,7 @@ import type { inputTheme, InputThemeSlots } from './theme/input.js';
41
41
  import type { inputGroupTheme, InputGroupThemeSlots } from './theme/input-group.js';
42
42
  import type { inputNumberTheme, InputNumberThemeSlots } from './theme/input-number.js';
43
43
  import type { kbdTheme, KbdThemeSlots } from './theme/kbd.js';
44
+ import type { listboxTheme, ListboxThemeSlots } from './theme/listbox.js';
44
45
  import type { modalTheme, ModalThemeSlots } from './theme/modal.js';
45
46
  import type { navigationMenuTheme, NavigationMenuThemeSlots } from './theme/navigation-menu.js';
46
47
  import type { pageAsideTheme, PageAsideThemeSlots } from './theme/page-aside.js';
@@ -72,6 +73,7 @@ import type { toastTheme, ToastThemeSlots } from './theme/toast.js';
72
73
  import type { toggleTheme, ToggleThemeSlots } from './theme/toggle.js';
73
74
  import type { toggleGroupTheme, ToggleGroupThemeSlots } from './theme/toggle-group.js';
74
75
  import type { tooltipTheme, TooltipThemeSlots } from './theme/tooltip.js';
76
+ import type { transferListTheme, TransferListThemeSlots } from './theme/transfer-list.js';
75
77
  import type { treeTheme, TreeThemeSlots } from './theme/tree.js';
76
78
  import type { ColorRole, RuntimeTokenOverrides } from './utils/color-registry.js';
77
79
  type AccordionVariants = VariantProps<typeof accordionTheme>;
@@ -362,6 +364,14 @@ export interface ThemeComponentRegistry {
362
364
  slots: RadioGroupThemeSlots;
363
365
  conditions: WithRegisteredColor<Pick<RadioGroupVariants, 'color' | 'size' | 'orientation' | 'variant' | 'invalid'>>;
364
366
  };
367
+ listbox: {
368
+ slots: ListboxThemeSlots;
369
+ conditions: WithRegisteredColor<Pick<VariantProps<typeof listboxTheme>, 'color' | 'size' | 'invalid'>>;
370
+ };
371
+ transferList: {
372
+ slots: TransferListThemeSlots;
373
+ conditions: Pick<VariantProps<typeof transferListTheme>, 'layout'>;
374
+ };
365
375
  rating: {
366
376
  slots: RatingThemeSlots;
367
377
  conditions: WithRegisteredColor<Pick<RatingVariants, 'color' | 'size' | 'orientation'>>;
@@ -46,6 +46,7 @@ export type * from '../components/Input.vue';
46
46
  export type * from '../components/InputGroup.vue';
47
47
  export type * from '../components/InputNumber.vue';
48
48
  export type * from '../components/Kbd.vue';
49
+ export type * from '../components/Listbox.vue';
49
50
  export type * from '../components/Modal.vue';
50
51
  export type * from '../components/NavigationMenu.vue';
51
52
  export type * from '../components/PageAside.vue';
@@ -83,6 +84,7 @@ export type * from '../components/Toast.vue';
83
84
  export type * from '../components/Toggle.vue';
84
85
  export type * from '../components/ToggleGroup.vue';
85
86
  export type * from '../components/Tooltip.vue';
87
+ export type * from '../components/TransferList.vue';
86
88
  export type * from '../components/Tree.vue';
87
89
  export type { UseCommandPaletteReturn } from '../composables/use-command-palette.js';
88
90
  export type { UseConfirmOptions, UseConfirmReturn } from '../composables/use-confirm.js';
@@ -0,0 +1,31 @@
1
+ import type { ListboxThemeSlots } from '../theme/listbox.js';
2
+ import type { SelectEntry, SelectEntryGroup, SelectEntryItem, SelectIdentity, SelectModel, SelectProps } from './select-contracts.js';
3
+ import type { UiProp } from './ui.js';
4
+ export interface ListboxProps<Entry extends SelectEntry = SelectEntry, Key extends string = 'value', Multiple extends boolean = false> extends Pick<SelectProps<Entry, Key, Multiple>, 'items' | 'modelValue' | 'defaultValue' | 'valueKey' | 'labelKey' | 'multiple' | 'searchable' | 'searchTerm' | 'virtualize' | 'disabled' | 'loading' | 'invalid' | 'size' | 'color' | 'id' | 'name' | 'form' | 'required'> {
5
+ label?: string;
6
+ descriptionKey?: keyof SelectEntryItem<Entry> & string;
7
+ selectionBehavior?: 'toggle' | 'replace';
8
+ checkbox?: boolean;
9
+ selectAll?: boolean;
10
+ ui?: UiProp<ListboxThemeSlots>;
11
+ }
12
+ export interface ListboxEmits<Entry extends SelectEntry = SelectEntry, Key extends string = 'value', Multiple extends boolean = false> {
13
+ 'update:modelValue': [value: SelectModel<SelectIdentity<Entry, Key>, Multiple>];
14
+ 'update:searchTerm': [value: string];
15
+ }
16
+ export interface ListboxItemSlot<Entry extends SelectEntry> {
17
+ item: SelectEntryItem<Entry>;
18
+ index: number;
19
+ selected: boolean;
20
+ disabled: boolean;
21
+ }
22
+ export interface ListboxSlots<Entry extends SelectEntry> {
23
+ 'item'?: (props: ListboxItemSlot<Entry>) => any;
24
+ 'group'?: (props: {
25
+ group: SelectEntryGroup<Entry>;
26
+ }) => any;
27
+ 'header'?: () => any;
28
+ 'footer'?: () => any;
29
+ 'empty'?: () => any;
30
+ 'empty-filter'?: () => any;
31
+ }
File without changes
@@ -44,6 +44,13 @@ export interface MessageRegistry {
44
44
  increment: string;
45
45
  decrement: string;
46
46
  noOptions: string;
47
+ selectAll: string;
48
+ transferSource: string;
49
+ transferTarget: string;
50
+ moveToTarget: string;
51
+ moveToSource: string;
52
+ listSelectionCount: (selected: number, total: number) => string;
53
+ transferItems: (count: number, target: string) => string;
47
54
  noResultsFound: string;
48
55
  createOption: (value: string) => string;
49
56
  noData: string;
@@ -44,6 +44,13 @@ export const defaultMessages = {
44
44
  increment: "Increment",
45
45
  decrement: "Decrement",
46
46
  noOptions: "No options",
47
+ selectAll: "Select all",
48
+ transferSource: "Available",
49
+ transferTarget: "Assigned",
50
+ moveToTarget: "Add selected",
51
+ moveToSource: "Remove selected",
52
+ listSelectionCount: (selected, total) => `${selected} of ${total} selected`,
53
+ transferItems: (count, target) => `${count} item${count === 1 ? "" : "s"} moved to ${target}`,
47
54
  noResultsFound: "No results found",
48
55
  createOption: (value) => `Create "${value}"`,
49
56
  noData: "No data",
@@ -0,0 +1,2 @@
1
+ import type { VNode } from 'vue';
2
+ export declare function flattenSlotChildren(vnodes: VNode[]): VNode[];
@@ -0,0 +1,15 @@
1
+ import { Comment, Fragment, Text } from "vue";
2
+ export function flattenSlotChildren(vnodes) {
3
+ const children = [];
4
+ for (const vnode of vnodes) {
5
+ if (vnode.type === Comment || vnode.type === Text)
6
+ continue;
7
+ if (vnode.type === Fragment) {
8
+ if (Array.isArray(vnode.children))
9
+ children.push(...flattenSlotChildren(vnode.children));
10
+ continue;
11
+ }
12
+ children.push(vnode);
13
+ }
14
+ return children;
15
+ }
@@ -0,0 +1,48 @@
1
+ import type { TransferListThemeSlots } from '../theme/transfer-list.js';
2
+ import type { ListboxItemSlot, ListboxProps } from './listbox-contracts.js';
3
+ import type { SelectEntry, SelectIdentity } from './select-contracts.js';
4
+ import type { UiProp } from './ui.js';
5
+ export type TransferDirection = 'to-target' | 'to-source';
6
+ export type TransferSide = 'source' | 'target';
7
+ export interface TransferListProps<Entry extends SelectEntry = SelectEntry, Key extends string = 'value'> extends Omit<ListboxProps<Entry, Key, true>, 'multiple' | 'checkbox' | 'selectAll' | 'selectionBehavior' | 'searchTerm' | 'ui' | 'label'> {
8
+ checked?: NoInfer<SelectIdentity<Entry, Key>[]>;
9
+ sourceLabel?: string;
10
+ targetLabel?: string;
11
+ sourceSearchTerm?: string;
12
+ targetSearchTerm?: string;
13
+ showSelectAll?: boolean;
14
+ layout?: 'auto' | 'horizontal' | 'vertical';
15
+ ui?: UiProp<TransferListThemeSlots>;
16
+ }
17
+ export interface TransferListEmits<Entry extends SelectEntry = SelectEntry, Key extends string = 'value'> {
18
+ 'update:modelValue': [value: SelectIdentity<Entry, Key>[]];
19
+ 'update:checked': [value: SelectIdentity<Entry, Key>[]];
20
+ 'update:sourceSearchTerm': [value: string];
21
+ 'update:targetSearchTerm': [value: string];
22
+ 'transfer': [payload: {
23
+ direction: TransferDirection;
24
+ items: ListboxItemSlot<Entry>['item'][];
25
+ values: SelectIdentity<Entry, Key>[];
26
+ }];
27
+ }
28
+ export interface TransferListSlots<Entry extends SelectEntry> {
29
+ 'item'?: (props: ListboxItemSlot<Entry> & {
30
+ side: TransferSide;
31
+ }) => any;
32
+ 'source-header'?: (props: {
33
+ count: number;
34
+ checkedCount: number;
35
+ }) => any;
36
+ 'target-header'?: (props: {
37
+ count: number;
38
+ checkedCount: number;
39
+ }) => any;
40
+ 'source-footer'?: () => any;
41
+ 'target-footer'?: () => any;
42
+ 'empty'?: (props: {
43
+ side: TransferSide;
44
+ }) => any;
45
+ 'empty-filter'?: (props: {
46
+ side: TransferSide;
47
+ }) => any;
48
+ }
File without changes
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sewadah/selaras",
3
3
  "type": "module",
4
- "version": "0.7.1",
4
+ "version": "0.8.0",
5
5
  "description": "A UI component library for Nuxt, built on Reka UI and Tailwind v4",
6
6
  "author": "Wicaksana Pratama <wicaksanapratama@gmail.com>",
7
7
  "license": "MIT",