nuance-ui 0.2.2 → 0.2.6

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 (34) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/avatar/avatar.vue +15 -15
  3. package/dist/runtime/components/box.vue +3 -3
  4. package/dist/runtime/components/combobox/combobox-dropdown.vue +15 -15
  5. package/dist/runtime/components/combobox/combobox-group.d.vue.ts +5 -5
  6. package/dist/runtime/components/combobox/combobox-group.vue +22 -22
  7. package/dist/runtime/components/combobox/combobox-group.vue.d.ts +5 -5
  8. package/dist/runtime/components/combobox/combobox-option.vue +23 -28
  9. package/dist/runtime/components/combobox/combobox-options-dropdown.d.vue.ts +6 -8
  10. package/dist/runtime/components/combobox/combobox-options-dropdown.vue +31 -32
  11. package/dist/runtime/components/combobox/combobox-options-dropdown.vue.d.ts +6 -8
  12. package/dist/runtime/components/combobox/combobox-root.d.vue.ts +0 -2
  13. package/dist/runtime/components/combobox/combobox-root.vue +1 -3
  14. package/dist/runtime/components/combobox/combobox-root.vue.d.ts +0 -2
  15. package/dist/runtime/components/combobox/combobox-target.vue +1 -1
  16. package/dist/runtime/components/combobox/combobox.module.css +1 -1
  17. package/dist/runtime/components/combobox/lib/use-combobox/use-combobox.js +8 -1
  18. package/dist/runtime/components/combobox/lib/use-combobox-data/get-parsed-combobox-data.d.ts +2 -2
  19. package/dist/runtime/components/combobox/lib/use-combobox-data/get-parsed-combobox-data.js +2 -1
  20. package/dist/runtime/components/combobox/lib/use-combobox-data/use-combobox-data.d.ts +4 -4
  21. package/dist/runtime/components/combobox/lib/use-combobox-data/use-combobox-data.js +3 -2
  22. package/dist/runtime/components/combobox/lib/utils/default-option-filter.d.ts +3 -3
  23. package/dist/runtime/components/combobox/lib/utils/default-option-filter.js +1 -1
  24. package/dist/runtime/components/combobox/lib/utils/index.d.ts +2 -3
  25. package/dist/runtime/components/combobox/lib/utils/index.js +2 -2
  26. package/dist/runtime/components/combobox/lib/utils/is-empty-combobox-data.d.ts +2 -2
  27. package/dist/runtime/components/combobox/lib/utils/is-guards.d.ts +2 -0
  28. package/dist/runtime/components/combobox/types/item.d.ts +3 -8
  29. package/dist/runtime/components/select/select.d.vue.ts +20 -7
  30. package/dist/runtime/components/select/select.vue +107 -73
  31. package/dist/runtime/components/select/select.vue.d.ts +20 -7
  32. package/package.json +10 -49
  33. package/dist/runtime/components/combobox/lib/utils/is-options-group.d.ts +0 -2
  34. /package/dist/runtime/components/combobox/lib/utils/{is-options-group.js → is-guards.js} +0 -0
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": "^4.0.0"
6
6
  },
7
- "version": "0.2.2",
7
+ "version": "0.2.6",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
@@ -1,11 +1,11 @@
1
1
  <script setup>
2
- import { getInitialsColor } from "@nui/components/avatar/_lib/get-initials-color";
3
2
  import { useStyleResolver } from "@nui/composals";
4
3
  import { createVariantColorResolver, getRadius, getSize } from "@nui/utils";
5
4
  import { computed } from "vue";
6
5
  import Box from "../box.vue";
7
6
  import { useAvatarGroupState } from "./_lib/context";
8
7
  import { getInitials } from "./_lib/get-initials";
8
+ import { getInitialsColor } from "./_lib/get-initials-color";
9
9
  import css from "./avatar.module.css";
10
10
  const {
11
11
  alt,
@@ -54,18 +54,18 @@ const style = computed(() => useStyleResolver((theme) => {
54
54
  </script>
55
55
 
56
56
  <template>
57
- <Box :style :class='css.root' :mod='[{ "within-group": ctx?.withinGroup }, mod]'>
58
- <span v-if='!src' :class='css.placeholder' :title='alt'>
59
- <slot>
60
- <Icon v-if='!src && !name' :name='placeholder' />
61
- {{ initials }}
62
- </slot>
63
- </span>
64
- <NuxtImg
65
- v-else
66
- :src
67
- :alt
68
- :class='css.image'
69
- />
70
- </Box>
57
+ <Box :style :class='css.root' :mod='[{ "within-group": ctx?.withinGroup }, mod]'>
58
+ <span v-if='!src' :class='css.placeholder' :title='alt'>
59
+ <slot>
60
+ <Icon v-if='!src && !name' :name='placeholder' />
61
+ {{ initials }}
62
+ </slot>
63
+ </span>
64
+ <NuxtImg
65
+ v-else
66
+ :src
67
+ :alt
68
+ :class='css.image'
69
+ />
70
+ </Box>
71
71
  </template>
@@ -16,7 +16,7 @@ const _mod = computed(() => {
16
16
  </script>
17
17
 
18
18
  <template>
19
- <component :is v-bind='_mod'>
20
- <slot />
21
- </component>
19
+ <component :is v-bind='_mod'>
20
+ <slot />
21
+ </component>
22
22
  </template>
@@ -1,6 +1,6 @@
1
1
  <script setup>
2
- import { getSize } from "@nui/utils";
3
2
  import { computed } from "vue";
3
+ import { getSize } from "../../utils";
4
4
  import Box from "../box.vue";
5
5
  import PopoverDropdown from "../popover/popover-dropdown.vue";
6
6
  import css from "./combobox.module.css";
@@ -13,21 +13,21 @@ const style = computed(() => ({
13
13
  </script>
14
14
 
15
15
  <template>
16
- <PopoverDropdown :class='$style.dropdown'>
17
- <Box
18
- :id='store.listId'
19
- role='presentation'
20
- :class='css.dropdown'
21
- :style
22
- v-bind='$attrs'
23
- >
24
- <slot />
25
- </Box>
26
- </PopoverDropdown>
16
+ <PopoverDropdown :class='$style.dropdown'>
17
+ <Box
18
+ :id='store.listId'
19
+ role='presentation'
20
+ :class='css.dropdown'
21
+ :style
22
+ v-bind='$attrs'
23
+ >
24
+ <slot />
25
+ </Box>
26
+ </PopoverDropdown>
27
27
  </template>
28
28
 
29
29
  <style module lang="postcss">
30
- .dropdown {
31
- padding: 0;
32
- }
30
+ .dropdown {
31
+ padding: 0;
32
+ }
33
33
  </style>
@@ -1,5 +1,5 @@
1
1
  import type { BoxProps } from '../box.vue.js';
2
- import type { ComboboxItem, ComboboxItemExt, ComboboxItemGroup, ComboboxItemProps } from './types/index.js';
2
+ import type { ComboboxItemExt, ComboboxItemGroup, ComboboxItemProps } from './types/index.js';
3
3
  export interface ComboboxGroupProps<Value extends string = string, Ext extends ComboboxItemExt = object> extends BoxProps, ComboboxItemProps {
4
4
  /** Group label */
5
5
  label?: string;
@@ -7,9 +7,9 @@ export interface ComboboxGroupProps<Value extends string = string, Ext extends C
7
7
  }
8
8
  declare const __VLS_export: <Value extends string = string, Ext extends ComboboxItemExt = object>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
9
9
  props: import("vue").PublicProps & __VLS_PrettifyLocal<(ComboboxGroupProps<Value, Ext> & {
10
- value?: ComboboxItem<Value, Ext> | ComboboxItem<Value, Ext>[] | null;
10
+ value?: string | string[] | null;
11
11
  }) & {
12
- "onUpdate:value"?: ((value: ComboboxItem<Value, Ext> | ComboboxItem<Value, Ext>[] | null | undefined) => any) | undefined;
12
+ "onUpdate:value"?: ((value: string | string[] | null | undefined) => any) | undefined;
13
13
  }> & (typeof globalThis extends {
14
14
  __VLS_PROPS_FALLBACK: infer P;
15
15
  } ? P : {});
@@ -19,13 +19,13 @@ declare const __VLS_export: <Value extends string = string, Ext extends Combobox
19
19
  label?: (props: {}) => any;
20
20
  } & {
21
21
  option?: (props: {
22
- data: ComboboxItem<Value, Ext>;
22
+ data: import("./types/index.js").ComboboxItem<any, Ext>;
23
23
  checked: boolean;
24
24
  withCheckIcon: boolean;
25
25
  iconPosition: "left" | "right";
26
26
  }) => any;
27
27
  };
28
- emit: (event: "update:value", value: ComboboxItem<Value, Ext> | ComboboxItem<Value, Ext>[] | null | undefined) => void;
28
+ emit: (event: "update:value", value: string | string[] | null | undefined) => void;
29
29
  }>) => import("vue").VNode & {
30
30
  __ctx?: Awaited<typeof __VLS_setup>;
31
31
  };
@@ -21,29 +21,29 @@ const {
21
21
  iconPosition: { type: String, required: false }
22
22
  });
23
23
  const uid = useId();
24
- const value = defineModel("value", { type: [Object, Array, null] });
24
+ const value = defineModel("value", { type: [String, Array, null] });
25
25
  </script>
26
26
 
27
27
  <template>
28
- <Box :class='css.group' role='group' :aria-labelledby='label ? uid : void 0' :mod>
29
- <div v-if='label || $slots?.label' :id='uid' :class='css.groupLabel'>
30
- <slot name='label'>
31
- {{ label }}
32
- </slot>
33
- </div>
34
-
35
- <ComboboxOption
36
- v-for='item in data.items'
37
- :key='item.value'
38
- :data='item'
39
- :icon-position
40
- :with-check-icon
41
- :check-icon
42
- :checked='isValueChecked(value, item)'
43
- >
44
- <template v-if='$slots.option' #default='props'>
45
- <slot name='option' v-bind='props' />
46
- </template>
47
- </ComboboxOption>
48
- </Box>
28
+ <Box :class='css.group' role='group' :aria-labelledby='label ? uid : void 0' :mod>
29
+ <div v-if='label || $slots?.label' :id='uid' :class='css.groupLabel'>
30
+ <slot name='label'>
31
+ {{ label }}
32
+ </slot>
33
+ </div>
34
+
35
+ <ComboboxOption
36
+ v-for='item in data.items'
37
+ :key='item.value'
38
+ :data='item'
39
+ :icon-position
40
+ :with-check-icon
41
+ :check-icon
42
+ :checked='isValueChecked(value, item.value)'
43
+ >
44
+ <template v-if='$slots.option' #default='props'>
45
+ <slot name='option' v-bind='props' />
46
+ </template>
47
+ </ComboboxOption>
48
+ </Box>
49
49
  </template>
@@ -1,5 +1,5 @@
1
1
  import type { BoxProps } from '../box.vue.js';
2
- import type { ComboboxItem, ComboboxItemExt, ComboboxItemGroup, ComboboxItemProps } from './types/index.js';
2
+ import type { ComboboxItemExt, ComboboxItemGroup, ComboboxItemProps } from './types/index.js';
3
3
  export interface ComboboxGroupProps<Value extends string = string, Ext extends ComboboxItemExt = object> extends BoxProps, ComboboxItemProps {
4
4
  /** Group label */
5
5
  label?: string;
@@ -7,9 +7,9 @@ export interface ComboboxGroupProps<Value extends string = string, Ext extends C
7
7
  }
8
8
  declare const __VLS_export: <Value extends string = string, Ext extends ComboboxItemExt = object>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
9
9
  props: import("vue").PublicProps & __VLS_PrettifyLocal<(ComboboxGroupProps<Value, Ext> & {
10
- value?: ComboboxItem<Value, Ext> | ComboboxItem<Value, Ext>[] | null;
10
+ value?: string | string[] | null;
11
11
  }) & {
12
- "onUpdate:value"?: ((value: ComboboxItem<Value, Ext> | ComboboxItem<Value, Ext>[] | null | undefined) => any) | undefined;
12
+ "onUpdate:value"?: ((value: string | string[] | null | undefined) => any) | undefined;
13
13
  }> & (typeof globalThis extends {
14
14
  __VLS_PROPS_FALLBACK: infer P;
15
15
  } ? P : {});
@@ -19,13 +19,13 @@ declare const __VLS_export: <Value extends string = string, Ext extends Combobox
19
19
  label?: (props: {}) => any;
20
20
  } & {
21
21
  option?: (props: {
22
- data: ComboboxItem<Value, Ext>;
22
+ data: import("./types/index.js").ComboboxItem<any, Ext>;
23
23
  checked: boolean;
24
24
  withCheckIcon: boolean;
25
25
  iconPosition: "left" | "right";
26
26
  }) => any;
27
27
  };
28
- emit: (event: "update:value", value: ComboboxItem<Value, Ext> | ComboboxItem<Value, Ext>[] | null | undefined) => void;
28
+ emit: (event: "update:value", value: string | string[] | null | undefined) => void;
29
29
  }>) => import("vue").VNode & {
30
30
  __ctx?: Awaited<typeof __VLS_setup>;
31
31
  };
@@ -8,7 +8,7 @@ const {
8
8
  data,
9
9
  iconPosition = "left",
10
10
  checkIcon = "gravity-ui:check",
11
- withCheckIcon,
11
+ withCheckIcon = true,
12
12
  mod: _mod,
13
13
  checked,
14
14
  selected
@@ -26,7 +26,6 @@ defineSlots();
26
26
  const { onOptionSubmit } = useComboboxState();
27
27
  const mod = computed(() => [
28
28
  {
29
- [COMBOBOX_ATTRS.option]: true,
30
29
  [COMBOBOX_ATTRS.active]: checked,
31
30
  [COMBOBOX_ATTRS.selected]: selected,
32
31
  [COMBOBOX_ATTRS.disabled]: data?.disabled,
@@ -38,30 +37,26 @@ const mod = computed(() => [
38
37
  </script>
39
38
 
40
39
  <template>
41
- <Box
42
- :class='css.option'
43
- :mod
44
- role='option'
45
- :aria-selected='checked'
46
- @click='() => !data?.disabled && onOptionSubmit?.(data.value, data)'
47
- >
48
- <slot
49
- :with-check-icon
50
- :icon-position
51
- :data
52
- :checked
53
- >
54
- <Icon
55
- v-if='withCheckIcon && iconPosition === "left"'
56
- :class='css.optionCheck'
57
- :name='data?.icon ?? checkIcon'
58
- />
59
- <span>{{ data.label }}</span>
60
- <Icon
61
- v-if='withCheckIcon && iconPosition === "right"'
62
- :class='css.optionCheck'
63
- :name='data?.icon ?? checkIcon'
64
- />
65
- </slot>
66
- </Box>
40
+ <Box
41
+ :class='css.option'
42
+ data-combobox-option
43
+ :mod
44
+ role='option'
45
+ :aria-selected='checked'
46
+ @mousedown='() => !data?.disabled && onOptionSubmit?.(data.value, data)'
47
+ >
48
+ <slot :with-check-icon :icon-position :data :checked>
49
+ <Icon
50
+ v-if='checked && withCheckIcon && iconPosition === "left"'
51
+ :class='css.optionCheck'
52
+ :name='data?.icon ?? checkIcon'
53
+ />
54
+ <span>{{ data.label }}</span>
55
+ <Icon
56
+ v-if='checked && withCheckIcon && iconPosition === "right"'
57
+ :class='css.optionCheck'
58
+ :name='data?.icon ?? checkIcon'
59
+ />
60
+ </slot>
61
+ </Box>
67
62
  </template>
@@ -1,12 +1,10 @@
1
1
  import type { FilterOptionsInput } from './lib/utils/index.js';
2
- import type { ComboboxItem, ComboboxItemExt, ComboboxParsedItem } from './types/index.js';
2
+ import type { ComboboxItemExt, ComboboxOption } from './types/index.js';
3
3
  export interface ComboboxOptionsDropdownProps<Value extends string = string, Ext extends ComboboxItemExt = object> {
4
- data: ComboboxParsedItem<Value, Ext>[];
5
- filter?: (input: FilterOptionsInput<Value, Ext>) => ComboboxParsedItem<Value, Ext>[];
4
+ data: ComboboxOption<Value, Ext>[];
5
+ filter?: (input: FilterOptionsInput<Value, Ext>) => ComboboxOption<Value, Ext>[];
6
6
  limit?: number;
7
- withScrollArea?: boolean;
8
7
  maxDropdownHeight?: number | string;
9
- hiddenWhenEmpty?: boolean;
10
8
  filterOptions?: boolean;
11
9
  nothingFoundMessage?: string;
12
10
  labelId: string | undefined;
@@ -17,9 +15,9 @@ export interface ComboboxOptionsDropdownProps<Value extends string = string, Ext
17
15
  declare const __VLS_export: <Value extends string = string, Ext extends ComboboxItemExt = object>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
18
16
  props: import("vue").PublicProps & __VLS_PrettifyLocal<(ComboboxOptionsDropdownProps<Value, Ext> & {
19
17
  search?: string | undefined;
20
- modelValue?: ComboboxItem<Value, Ext> | ComboboxItem<Value, Ext>[] | null;
18
+ modelValue?: string | string[] | null;
21
19
  }) & {
22
- "onUpdate:modelValue"?: ((value: ComboboxItem<Value, Ext> | ComboboxItem<Value, Ext>[] | null | undefined) => any) | undefined;
20
+ "onUpdate:modelValue"?: ((value: string | string[] | null | undefined) => any) | undefined;
23
21
  "onUpdate:search"?: ((value: string | undefined) => any) | undefined;
24
22
  }> & (typeof globalThis extends {
25
23
  __VLS_PROPS_FALLBACK: infer P;
@@ -27,7 +25,7 @@ declare const __VLS_export: <Value extends string = string, Ext extends Combobox
27
25
  expose: (exposed: {}) => void;
28
26
  attrs: any;
29
27
  slots: {};
30
- emit: ((event: "update:modelValue", value: ComboboxItem<Value, Ext> | ComboboxItem<Value, Ext>[] | null | undefined) => void) & ((event: "update:search", value: string | undefined) => void);
28
+ emit: ((event: "update:modelValue", value: string | string[] | null | undefined) => void) & ((event: "update:search", value: string | undefined) => void);
31
29
  }>) => import("vue").VNode & {
32
30
  __ctx?: Awaited<typeof __VLS_setup>;
33
31
  };
@@ -4,7 +4,7 @@ import ComboboxDropdown from "./combobox-dropdown.vue";
4
4
  import ComboboxEmpty from "./combobox-empty.vue";
5
5
  import ComboboxGroup from "./combobox-group.vue";
6
6
  import ComboboxOptionList from "./combobox-option-list.vue";
7
- import ComboboxOption from "./combobox-option.vue";
7
+ import ComboboxOptions from "./combobox-option.vue";
8
8
  import { defaultOptionsFilter, isEmptyComboboxData, isOptionsGroup, isValueChecked } from "./lib/utils";
9
9
  const {
10
10
  data,
@@ -20,9 +20,7 @@ const {
20
20
  data: { type: Array, required: true },
21
21
  filter: { type: Function, required: false },
22
22
  limit: { type: Number, required: false },
23
- withScrollArea: { type: Boolean, required: false },
24
23
  maxDropdownHeight: { type: [Number, String], required: false },
25
- hiddenWhenEmpty: { type: Boolean, required: false },
26
24
  filterOptions: { type: Boolean, required: false },
27
25
  nothingFoundMessage: { type: String, required: false },
28
26
  labelId: { type: null, required: true },
@@ -31,7 +29,7 @@ const {
31
29
  checkIcon: { type: String, required: false }
32
30
  });
33
31
  const search = defineModel("search", { type: null });
34
- const value = defineModel({ type: [Object, Array, null] });
32
+ const value = defineModel({ type: [String, Array, null] });
35
33
  const isEmpty = computed(() => isEmptyComboboxData(data));
36
34
  const filteredData = computed(() => typeof search.value === "string" ? (filter || defaultOptionsFilter)({
37
35
  options: data,
@@ -41,32 +39,33 @@ const filteredData = computed(() => typeof search.value === "string" ? (filter |
41
39
  </script>
42
40
 
43
41
  <template>
44
- <ComboboxDropdown data-composed>
45
- <ComboboxOptionList :labelled-by='labelId' v-bind='$attrs'>
46
- <template
47
- v-for='item in filteredData'
48
- :key='isOptionsGroup(item) ? item.group : item?.value'
49
- >
50
- <ComboboxGroup
51
- v-if='isOptionsGroup(item)'
52
- v-model:value='value'
53
- :data='item'
54
- :with-check-icon
55
- :icon-position
56
- :check-icon
57
- />
58
- <ComboboxOption
59
- v-else
60
- :data='item'
61
- :with-check-icon
62
- :icon-position
63
- :check-icon
64
- :checked='isValueChecked(value, item)'
65
- />
66
- </template>
67
- <ComboboxEmpty v-if='isEmpty'>
68
- {{ nothingFoundMessage }}
69
- </ComboboxEmpty>
70
- </ComboboxOptionList>
71
- </ComboboxDropdown>
42
+ <ComboboxDropdown>
43
+ <ComboboxOptionList :labelled-by='labelId' v-bind='$attrs'>
44
+ <template
45
+ v-for='item in filteredData'
46
+ :key='isOptionsGroup(item) ? item.group : item?.value'
47
+ >
48
+ <ComboboxGroup
49
+ v-if='isOptionsGroup(item)'
50
+ v-model:value='value'
51
+ :label='item.group'
52
+ :data='item'
53
+ :with-check-icon
54
+ :icon-position
55
+ :check-icon
56
+ />
57
+ <ComboboxOptions
58
+ v-else
59
+ :data='item'
60
+ :with-check-icon
61
+ :icon-position
62
+ :check-icon
63
+ :checked='isValueChecked(value, item.value)'
64
+ />
65
+ </template>
66
+ <ComboboxEmpty v-if='isEmpty'>
67
+ {{ nothingFoundMessage }}
68
+ </ComboboxEmpty>
69
+ </ComboboxOptionList>
70
+ </ComboboxDropdown>
72
71
  </template>
@@ -1,12 +1,10 @@
1
1
  import type { FilterOptionsInput } from './lib/utils/index.js';
2
- import type { ComboboxItem, ComboboxItemExt, ComboboxParsedItem } from './types/index.js';
2
+ import type { ComboboxItemExt, ComboboxOption } from './types/index.js';
3
3
  export interface ComboboxOptionsDropdownProps<Value extends string = string, Ext extends ComboboxItemExt = object> {
4
- data: ComboboxParsedItem<Value, Ext>[];
5
- filter?: (input: FilterOptionsInput<Value, Ext>) => ComboboxParsedItem<Value, Ext>[];
4
+ data: ComboboxOption<Value, Ext>[];
5
+ filter?: (input: FilterOptionsInput<Value, Ext>) => ComboboxOption<Value, Ext>[];
6
6
  limit?: number;
7
- withScrollArea?: boolean;
8
7
  maxDropdownHeight?: number | string;
9
- hiddenWhenEmpty?: boolean;
10
8
  filterOptions?: boolean;
11
9
  nothingFoundMessage?: string;
12
10
  labelId: string | undefined;
@@ -17,9 +15,9 @@ export interface ComboboxOptionsDropdownProps<Value extends string = string, Ext
17
15
  declare const __VLS_export: <Value extends string = string, Ext extends ComboboxItemExt = object>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
18
16
  props: import("vue").PublicProps & __VLS_PrettifyLocal<(ComboboxOptionsDropdownProps<Value, Ext> & {
19
17
  search?: string | undefined;
20
- modelValue?: ComboboxItem<Value, Ext> | ComboboxItem<Value, Ext>[] | null;
18
+ modelValue?: string | string[] | null;
21
19
  }) & {
22
- "onUpdate:modelValue"?: ((value: ComboboxItem<Value, Ext> | ComboboxItem<Value, Ext>[] | null | undefined) => any) | undefined;
20
+ "onUpdate:modelValue"?: ((value: string | string[] | null | undefined) => any) | undefined;
23
21
  "onUpdate:search"?: ((value: string | undefined) => any) | undefined;
24
22
  }> & (typeof globalThis extends {
25
23
  __VLS_PROPS_FALLBACK: infer P;
@@ -27,7 +25,7 @@ declare const __VLS_export: <Value extends string = string, Ext extends Combobox
27
25
  expose: (exposed: {}) => void;
28
26
  attrs: any;
29
27
  slots: {};
30
- emit: ((event: "update:modelValue", value: ComboboxItem<Value, Ext> | ComboboxItem<Value, Ext>[] | null | undefined) => void) & ((event: "update:search", value: string | undefined) => void);
28
+ emit: ((event: "update:modelValue", value: string | string[] | null | undefined) => void) & ((event: "update:search", value: string | undefined) => void);
31
29
  }>) => import("vue").VNode & {
32
30
  __ctx?: Awaited<typeof __VLS_setup>;
33
31
  };
@@ -6,8 +6,6 @@ export interface ComboboxProps extends PopoverProps {
6
6
  store?: ComboboxStore;
7
7
  /** Determines whether arrow key presses should loop though items (first to last and last to first), `true` by default */
8
8
  loop?: boolean;
9
- /** `behavior` passed down to `element.scrollIntoView`, `'instant'` by default */
10
- scrollBehavior?: ScrollBehavior;
11
9
  /** Controls items `font-size` and `padding` @default `'sm'` */
12
10
  size?: NuanceSize;
13
11
  /** Controls `padding` of the dropdown @default `4` */
@@ -3,7 +3,6 @@ import Popover from "../popover/popover.vue";
3
3
  import { useProvideComboboxState } from "./lib/context";
4
4
  import { useCombobox } from "./lib/use-combobox";
5
5
  const {
6
- scrollBehavior = "instant",
7
6
  loop = true,
8
7
  readOnly = false,
9
8
  size = "sm",
@@ -13,7 +12,6 @@ const {
13
12
  } = defineProps({
14
13
  store: { type: Object, required: false },
15
14
  loop: { type: Boolean, required: false },
16
- scrollBehavior: { type: null, required: false },
17
15
  size: { type: String, required: false },
18
16
  dropdownPadding: { type: String, required: false },
19
17
  readOnly: { type: Boolean, required: false },
@@ -35,7 +33,7 @@ const emit = defineEmits(["clear", "select", "open", "close", "submit"]);
35
33
  const opened = defineModel("open", { type: Boolean, ...{ default: false } });
36
34
  const store = _store ?? useCombobox({
37
35
  loop,
38
- scrollBehavior,
36
+ scrollBehavior: "instant",
39
37
  onSelect: (ix) => emit("select", ix),
40
38
  onClear: () => emit("clear"),
41
39
  onOpenDropdown: (source) => emit("open", source),
@@ -6,8 +6,6 @@ export interface ComboboxProps extends PopoverProps {
6
6
  store?: ComboboxStore;
7
7
  /** Determines whether arrow key presses should loop though items (first to last and last to first), `true` by default */
8
8
  loop?: boolean;
9
- /** `behavior` passed down to `element.scrollIntoView`, `'instant'` by default */
10
- scrollBehavior?: ScrollBehavior;
11
9
  /** Controls items `font-size` and `padding` @default `'sm'` */
12
10
  size?: NuanceSize;
13
11
  /** Controls `padding` of the dropdown @default `4` */
@@ -26,7 +26,7 @@ const { store: { targetRef } } = useComboboxState();
26
26
  </script>
27
27
 
28
28
  <template>
29
- <PopoverTarget ref='targetRef' v-bind='aria' disabled>
29
+ <PopoverTarget ref='targetRef' v-bind='aria' disable>
30
30
  <slot />
31
31
  </PopoverTarget>
32
32
  </template>
@@ -1 +1 @@
1
- .dropdown{--combobox-padding:.25rem;padding:var(--combobox-padding)}.dropdown:has([data-scrollbar]) .search{max-width:calc(100% + var(--combobox-padding))}.dropdown[data-composed]{padding-inline-end:0}.dropdown[data-hidden]{display:none}.dropdown,.options{--combobox-option-padding-xs:rem(4px) rem(8px);--combobox-option-padding-sm:rem(6px) rem(10px);--combobox-option-padding-md:rem(8px) rem(12px);--combobox-option-padding-lg:rem(10px) rem(16px);--combobox-option-padding-xl:rem(14px) rem(20px);--combobox-option-padding:var(--combobox-option-padding-sm)}.option{align-items:center;background-color:transparent;border-radius:var(--radius-default);color:inherit;cursor:pointer;display:flex;font-size:var(--combobox-option-fz,var(--font-size-sm));gap:8px;overflow-wrap:break-word;padding:var(--combobox-option-padding)}.option:where([data-combobox-selected]){background-color:var(--color-primary-filled);color:var(--color-white)}.option:where([data-combobox-disabled]){cursor:not-allowed;opacity:.35}.option:where([data-reverse]){justify-content:space-between}.option{@mixin hover{&:where(:not([data-combobox-selected],[data-combobox-disabled])){@mixin where-light{background-color:var(--color-gray-0)}@mixin where-dark{background-color:var(--color-dark-7)}}}}.optionCheck{height:.8em;min-width:.8em;opacity:.4;width:.8em}:where([data-combobox-selected]) .optionCheck{opacity:1}.search{border-end-end-radius:0;border-end-start-radius:0;border-inline-width:0;border-top-width:0;margin-inline:calc(var(--combobox-padding)*-1);margin-bottom:var(--combobox-padding);margin-top:calc(var(--combobox-padding)*-1);position:relative;width:calc(100% + var(--combobox-padding)*2)}.search,.search:focus{@mixin where-light{border-color:var(--color-gray-2)}@mixin where-dark{border-color:var(--color-dark-4)}}.search{@mixin where-light{background-color:var(--color-white)}}.search{@mixin where-dark{background-color:var(--color-dark-7)}}.empty{color:var(--color-dimmed);font-size:var(--combobox-option-fz,var(--font-size-sm));padding:var(--combobox-option-padding);text-align:center}.footer,.header{border:0 solid transparent;font-size:var(--combobox-option-fz,var(--font-size-sm));margin-inline:calc(var(--combobox-padding)*-1);padding:var(--combobox-option-padding);@mixin where-light{border-color:var(--color-gray-2)}@mixin where-dark{border-color:var(--color-dark-4)}}.footer{border-top-width:1px;margin-bottom:calc(var(--combobox-padding)*-1);margin-top:var(--combobox-padding)}.header{border-bottom-width:1px;margin-bottom:var(--combobox-padding);margin-top:calc(var(--combobox-padding)*-1)}.group:has(.groupLabel:only-child){display:none}.groupLabel{align-items:center;color:var(--color-dimmed);display:flex;font-size:calc(var(--combobox-option-fz, var(--font-size-sm))*.85);font-weight:500;padding:var(--combobox-option-padding);position:relative}.groupLabel:after{content:"";flex:1;height:1px;inset-inline:0;margin-inline-start:var(--spacing-xs);@mixin where-light{background-color:var(--color-gray-2)}@mixin where-dark{background-color:var(--color-dark-4)}}.groupLabel:only-child{display:none}.chevron{--combobox-chevron-size-xs:rem(14px);--combobox-chevron-size-sm:rem(18px);--combobox-chevron-size-md:rem(20px);--combobox-chevron-size-lg:rem(24px);--combobox-chevron-size-xl:rem(28px);--combobox-chevron-size:var(--combobox-chevron-size-sm);@mixin where-light{--_combobox-chevron-color:var(--combobox-chevron-color,var(--color-gray-6))}@mixin where-dark{--_combobox-chevron-color:var(--combobox-chevron-color,var(--color-dark-3))}color:var(--_combobox-chevron-color);height:var(--combobox-chevron-size);width:var(--combobox-chevron-size)}.chevron:where([data-error]){color:var(--combobox-chevron-color,var(--color-error))}
1
+ .dropdown{--combobox-padding:.25rem;padding:var(--combobox-padding)}.dropdown:has([data-scrollbar]) .search{max-width:calc(100% + var(--combobox-padding))}.dropdown[data-hidden]{display:none}.dropdown,.options{--combobox-option-padding-xs:rem(4px) rem(8px);--combobox-option-padding-sm:rem(6px) rem(10px);--combobox-option-padding-md:rem(8px) rem(12px);--combobox-option-padding-lg:rem(10px) rem(16px);--combobox-option-padding-xl:rem(14px) rem(20px);--combobox-option-padding:var(--combobox-option-padding-sm)}.option{align-items:center;background-color:transparent;border-radius:var(--radius-default);color:inherit;cursor:pointer;display:flex;font-size:var(--combobox-option-fz,var(--font-size-sm));gap:8px;overflow-wrap:break-word;padding:var(--combobox-option-padding)}.option:where([data-combobox-selected]){background-color:var(--color-primary-filled);color:var(--color-white)}.option:where([data-combobox-disabled]){cursor:not-allowed;opacity:.35}.option:where([data-reverse]){justify-content:space-between}.option{@mixin hover{&:where(:not([data-combobox-selected],[data-combobox-disabled])){@mixin where-light{background-color:var(--color-gray-0)}@mixin where-dark{background-color:var(--color-dark-7)}}}}.optionCheck{height:.8em;min-width:.8em;opacity:.4;width:.8em}:where([data-combobox-selected]) .optionCheck{opacity:1}.search{border-end-end-radius:0;border-end-start-radius:0;border-inline-width:0;border-top-width:0;margin-inline:calc(var(--combobox-padding)*-1);margin-bottom:var(--combobox-padding);margin-top:calc(var(--combobox-padding)*-1);position:relative;width:calc(100% + var(--combobox-padding)*2)}.search,.search:focus{@mixin where-light{border-color:var(--color-gray-2)}@mixin where-dark{border-color:var(--color-dark-4)}}.search{@mixin where-light{background-color:var(--color-white)}}.search{@mixin where-dark{background-color:var(--color-dark-7)}}.empty{color:var(--color-dimmed);font-size:var(--combobox-option-fz,var(--font-size-sm));padding:var(--combobox-option-padding);text-align:center}.footer,.header{border:0 solid transparent;font-size:var(--combobox-option-fz,var(--font-size-sm));margin-inline:calc(var(--combobox-padding)*-1);padding:var(--combobox-option-padding);@mixin where-light{border-color:var(--color-gray-2)}@mixin where-dark{border-color:var(--color-dark-4)}}.footer{border-top-width:1px;margin-bottom:calc(var(--combobox-padding)*-1);margin-top:var(--combobox-padding)}.header{border-bottom-width:1px;margin-bottom:var(--combobox-padding);margin-top:calc(var(--combobox-padding)*-1)}.group:has(.groupLabel:only-child){display:none}.groupLabel{align-items:center;color:var(--color-dimmed);display:flex;font-size:calc(var(--combobox-option-fz, var(--font-size-sm))*.85);font-weight:500;padding:var(--combobox-option-padding);position:relative}.groupLabel:after{content:"";flex:1;height:1px;inset-inline:0;margin-inline-start:var(--spacing-xs);@mixin where-light{background-color:var(--color-gray-2)}@mixin where-dark{background-color:var(--color-dark-4)}}.groupLabel:only-child{display:none}.chevron{--combobox-chevron-size-xs:rem(14px);--combobox-chevron-size-sm:rem(18px);--combobox-chevron-size-md:rem(20px);--combobox-chevron-size-lg:rem(24px);--combobox-chevron-size-xl:rem(28px);--combobox-chevron-size:var(--combobox-chevron-size-sm);@mixin where-light{--_combobox-chevron-color:var(--combobox-chevron-color,var(--color-gray-6))}@mixin where-dark{--_combobox-chevron-color:var(--combobox-chevron-color,var(--color-dark-3))}color:var(--_combobox-chevron-color);height:var(--combobox-chevron-size);width:var(--combobox-chevron-size)}.chevron:where([data-error]){color:var(--combobox-chevron-color,var(--color-error))}
@@ -10,7 +10,14 @@ import {
10
10
  selectPrevOption,
11
11
  updateSelectedOptionIx
12
12
  } from "./handlers.js";
13
- export function useCombobox({ onSelect, onClear, onCloseDropdown, onOpenDropdown, opened, ..._options }) {
13
+ export function useCombobox({
14
+ onSelect,
15
+ onClear,
16
+ onCloseDropdown,
17
+ onOpenDropdown,
18
+ opened,
19
+ ..._options
20
+ }) {
14
21
  const listId = useId();
15
22
  const targetRef = shallowRef(null);
16
23
  const searchRef = shallowRef(null);
@@ -1,2 +1,2 @@
1
- import type { ComboboxData, ComboboxItemExt, ComboboxParsedItem } from '../../types/index.js';
2
- export declare function getParsedComboboxData<Value extends string = string, Ext extends ComboboxItemExt = object>(data: ComboboxData<Value, Ext> | undefined): ComboboxParsedItem<Value, Ext>[];
1
+ import type { ComboboxData, ComboboxItemExt, ComboboxOption } from '../../types/index.js';
2
+ export declare function getParsedComboboxData<Value extends string = string, Ext extends ComboboxItemExt = object>(data: ComboboxData<Value, Ext> | undefined): ComboboxOption<Value, Ext>[];
@@ -1,6 +1,7 @@
1
+ import { isNumber } from "es-toolkit";
1
2
  import { isOptionsGroup } from "../utils/index.js";
2
3
  function parseItem(item) {
3
- if (typeof item === "number")
4
+ if (isNumber(item))
4
5
  return { value: item.toString(), label: item.toString() };
5
6
  if (isOptionsGroup(item)) {
6
7
  return {
@@ -1,7 +1,7 @@
1
- import type { ComboboxData, ComboboxItem, ComboboxItemExt, ComboboxParsedItem } from '../../types/index.js';
2
- export declare function getOptionsLockup<Value extends string = string, Ext extends ComboboxItemExt = object>(options: ComboboxParsedItem<Value, Ext>[]): Record<string, ComboboxItem<Value, Ext>>;
3
- export declare function getLabelsLockup<Value extends string = string, Ext extends ComboboxItemExt = object>(options: ComboboxParsedItem<Value, Ext>[]): Record<string, string>;
1
+ import type { ComboboxData, ComboboxItem, ComboboxItemExt, ComboboxOption } from '../../types/index.js';
2
+ export declare function getOptionsLockup<Value extends string = string, Ext extends ComboboxItemExt = object>(options: ComboboxOption<Value, Ext>[]): Record<string, ComboboxItem<Value, Ext>>;
3
+ export declare function getLabelsLockup<Value extends string = string, Ext extends ComboboxItemExt = object>(options: ComboboxOption<Value, Ext>[]): Record<string, ComboboxOption<Value, Ext>>;
4
4
  export declare function useComboboxData<Value extends string = string, Ext extends ComboboxItemExt = object>(data: ComboboxData<Value, Ext>): {
5
- parsed: import("vue").ComputedRef<ComboboxParsedItem<Value, Ext>[]>;
5
+ parsed: import("vue").ComputedRef<ComboboxOption<Value, Ext>[]>;
6
6
  options: import("vue").ComputedRef<Record<string, ComboboxItem<Value, Ext>>>;
7
7
  };
@@ -1,8 +1,9 @@
1
1
  import { computed } from "vue";
2
+ import { isOptionsGroup } from "../utils/index.js";
2
3
  import { getParsedComboboxData } from "./get-parsed-combobox-data.js";
3
4
  export function getOptionsLockup(options) {
4
5
  return options.reduce((acc, item) => {
5
- if ("group" in item)
6
+ if (isOptionsGroup(item))
6
7
  return { ...acc, ...getOptionsLockup(item.items) };
7
8
  acc[item.value] = item;
8
9
  return acc;
@@ -10,7 +11,7 @@ export function getOptionsLockup(options) {
10
11
  }
11
12
  export function getLabelsLockup(options) {
12
13
  return options.reduce((acc, item) => {
13
- if ("group" in item)
14
+ if (isOptionsGroup(item))
14
15
  return { ...acc, ...getLabelsLockup(item.items) };
15
16
  acc[item.label] = item;
16
17
  return acc;
@@ -1,7 +1,7 @@
1
- import type { ComboboxItemExt, ComboboxParsedItem } from '../../types/index.js';
1
+ import type { ComboboxItemExt, ComboboxOption } from '../../types/index.js';
2
2
  export interface FilterOptionsInput<Value extends string = string, Ext extends ComboboxItemExt = object> {
3
- options: ComboboxParsedItem<Value, Ext>[];
3
+ options: ComboboxOption<Value, Ext>[];
4
4
  search: string;
5
5
  limit: number;
6
6
  }
7
- export declare function defaultOptionsFilter<Value extends string = string, Ext extends ComboboxItemExt = object>({ options, search, limit, }: FilterOptionsInput<Value, Ext>): ComboboxParsedItem<Value, Ext>[];
7
+ export declare function defaultOptionsFilter<Value extends string = string, Ext extends ComboboxItemExt = object>({ options, search, limit, }: FilterOptionsInput<Value, Ext>): ComboboxOption<Value, Ext>[];
@@ -1,4 +1,4 @@
1
- import { isOptionsGroup } from "./is-options-group.js";
1
+ import { isOptionsGroup } from "./is-guards.js";
2
2
  export function defaultOptionsFilter({
3
3
  options,
4
4
  search,
@@ -1,5 +1,4 @@
1
- import type { ComboboxItem, ComboboxItemExt } from '../../types/index.js';
2
1
  export * from './default-option-filter.js';
3
2
  export { isEmptyComboboxData } from './is-empty-combobox-data.js';
4
- export { isOptionsGroup } from './is-options-group.js';
5
- export declare function isValueChecked<Value extends string = string, Ext extends ComboboxItemExt = object>(value: ComboboxItem<Value, Ext> | ComboboxItem<Value, Ext>[] | undefined | null, optionValue: ComboboxItem<Value, Ext>): boolean;
3
+ export { isOptionsGroup } from './is-guards.js';
4
+ export declare function isValueChecked(value: string | string[] | null | undefined, optionValue: string): boolean;
@@ -1,6 +1,6 @@
1
1
  export * from "./default-option-filter.js";
2
2
  export { isEmptyComboboxData } from "./is-empty-combobox-data.js";
3
- export { isOptionsGroup } from "./is-options-group.js";
3
+ export { isOptionsGroup } from "./is-guards.js";
4
4
  export function isValueChecked(value, optionValue) {
5
- return Array.isArray(value) ? value.some(({ value: value2 }) => value2 === optionValue.value) : value?.value === optionValue.value;
5
+ return Array.isArray(value) ? value.includes(optionValue) : value === optionValue;
6
6
  }
@@ -1,2 +1,2 @@
1
- import type { ComboboxParsedItem } from '../../types/index.js';
2
- export declare function isEmptyComboboxData(data: ComboboxParsedItem[]): boolean;
1
+ import type { ComboboxOption } from '../../types/index.js';
2
+ export declare function isEmptyComboboxData(data: ComboboxOption[]): boolean;
@@ -0,0 +1,2 @@
1
+ import type { ComboboxItemExt, ComboboxItemGroup, ComboboxOption } from '../../types/index.js';
2
+ export declare function isOptionsGroup<Value extends string = string, Ext extends ComboboxItemExt = object>(item: ComboboxOption<Value, Ext>): item is ComboboxItemGroup<Value, Ext>;
@@ -8,15 +8,10 @@ export type ComboboxItemExt = Omit<object, keyof BaseComboboxFields>;
8
8
  export type ComboboxItem<Value extends string = string, Ext extends ComboboxItemExt = object> = BaseComboboxFields & {
9
9
  value: Value;
10
10
  } & Ext;
11
- export interface ComboboxParsedItemGroup<Value extends string = string, Ext extends ComboboxItemExt = object> {
11
+ export interface ComboboxItemGroup<_Value extends string = string, Ext extends ComboboxItemExt = object> {
12
12
  group: string;
13
13
  icon?: string;
14
- items: ComboboxItem<Value, Ext>[];
15
- }
16
- export type ComboboxParsedItem<Value extends string = string, Ext extends ComboboxItemExt = object> = ComboboxItem<Value, Ext> | ComboboxParsedItemGroup<Value, Ext>;
17
- export interface ComboboxItemGroup<Value extends string = string, Ext extends ComboboxItemExt = object> {
18
- group: string;
19
- icon?: string;
20
- items: ComboboxItem<Value, Ext>[];
14
+ items: ComboboxItem<any, Ext>[];
21
15
  }
16
+ export type ComboboxOption<Value extends string = string, Ext extends ComboboxItemExt = object> = ComboboxItem<Value, Ext> | ComboboxItemGroup<Value, Ext>;
22
17
  export {};
@@ -1,9 +1,11 @@
1
- import type { ComboboxData, ComboboxItem, ComboboxItemExt } from '../combobox/index.js';
1
+ import type { ComboboxData, ComboboxItemExt } from '../combobox/index.js';
2
2
  import type { TextInputProps } from '../input/index.js';
3
3
  export interface SelectProps<Value extends string = string, Ext extends ComboboxItemExt = object> extends Omit<TextInputProps, 'modelValue' | 'multiline' | 'resize' | 'is' | 'id'> {
4
- data: ComboboxData<Value, Ext>;
4
+ options: ComboboxData<Value, Ext>;
5
5
  /** Determines whether the select should be searchable @default `false` */
6
6
  searchable?: boolean;
7
+ /** If set, multiple options can be selected @default `false` */
8
+ multiple?: boolean;
7
9
  /** If set, the check icon is displayed near the selected option label @default `true` */
8
10
  withCheckIcon?: boolean;
9
11
  /** Position of the check icon relative to the option label @default `'left'` */
@@ -12,23 +14,29 @@ export interface SelectProps<Value extends string = string, Ext extends Combobox
12
14
  nothingFoundMessage?: string;
13
15
  /** If set, it becomes possible to deselect value by clicking on the selected option @default `true` */
14
16
  allowDeselect?: boolean;
17
+ /** If set, the dropdown will close after an option is selected @default `!multiple` */
18
+ closeOnSelect?: boolean;
15
19
  /** If set, the clear button is displayed in the right section when the component has value @default `false` */
20
+ /** Icon displayed in the left section by default */
21
+ icon?: string;
16
22
  limit?: number;
17
- /** Props passed down to the underlying `ScrollArea` component in the dropdown */
18
23
  /** Input autocomplete attribute */
19
24
  autoComplete?: string;
20
25
  }
21
26
  declare const __VLS_export: <Value extends string = string, Ext extends ComboboxItemExt = object>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
22
27
  props: import("vue").PublicProps & __VLS_PrettifyLocal<(SelectProps<Value, Ext> & {
28
+ /** Dropdown opened state */
23
29
  open?: boolean;
24
- modelValue?: ComboboxItem<Value, Ext> | null;
30
+ /** Value handler */
31
+ modelValue?: string | string[] | null;
32
+ /** Search handler */
25
33
  search?: string;
26
34
  }) & {
27
35
  onSelect?: ((args_0: number) => any) | undefined;
28
36
  onClear?: (() => any) | undefined;
29
37
  onClose?: ((args_0: import("..").ComboboxDropdownEventSource) => any) | undefined;
30
- onSubmit?: ((args_0: string, args_1: ComboboxItem) => any) | undefined;
31
- "onUpdate:modelValue"?: ((value: ComboboxItem<Value, Ext> | null) => any) | undefined;
38
+ onSubmit?: ((args_0: string, args_1: import("..").ComboboxItem) => any) | undefined;
39
+ "onUpdate:modelValue"?: ((value: string | string[] | null) => any) | undefined;
32
40
  onOpen?: ((args_0: import("..").ComboboxDropdownEventSource) => any) | undefined;
33
41
  "onUpdate:search"?: ((value: string) => any) | undefined;
34
42
  "onUpdate:open"?: ((value: boolean) => any) | undefined;
@@ -38,6 +46,11 @@ declare const __VLS_export: <Value extends string = string, Ext extends Combobox
38
46
  expose: (exposed: {}) => void;
39
47
  attrs: any;
40
48
  slots: {
49
+ selection?: (props: {
50
+ value: string | string[] | null;
51
+ display: string;
52
+ }) => any;
53
+ } & {
41
54
  label?: (props: {}) => any;
42
55
  } & {
43
56
  description?: (props: {}) => any;
@@ -48,7 +61,7 @@ declare const __VLS_export: <Value extends string = string, Ext extends Combobox
48
61
  } & {
49
62
  rightSection?: (props: {}) => any;
50
63
  };
51
- emit: (((evt: "select", args_0: number) => void) & ((evt: "clear") => void) & ((evt: "close", args_0: import("..").ComboboxDropdownEventSource) => void) & ((evt: "submit", args_0: string, args_1: ComboboxItem) => void) & ((evt: "open", args_0: import("..").ComboboxDropdownEventSource) => void)) & (((event: "update:modelValue", value: ComboboxItem<Value, Ext> | null) => void) & ((event: "update:search", value: string) => void) & ((event: "update:open", value: boolean) => void));
64
+ emit: (((evt: "select", args_0: number) => void) & ((evt: "clear") => void) & ((evt: "close", args_0: import("..").ComboboxDropdownEventSource) => void) & ((evt: "submit", args_0: string, args_1: import("..").ComboboxItem) => void) & ((evt: "open", args_0: import("..").ComboboxDropdownEventSource) => void)) & (((event: "update:modelValue", value: string | string[] | null) => void) & ((event: "update:search", value: string) => void) & ((event: "update:open", value: boolean) => void));
52
65
  }>) => import("vue").VNode & {
53
66
  __ctx?: Awaited<typeof __VLS_setup>;
54
67
  };
@@ -1,5 +1,5 @@
1
1
  <script setup>
2
- import { nextTick, watch } from "vue";
2
+ import { computed, nextTick, ref, watch } from "vue";
3
3
  import { useCombobox, useComboboxData } from "../combobox";
4
4
  import ComboboxOptionsDropdown from "../combobox/combobox-options-dropdown.vue";
5
5
  import ComboboxRoot from "../combobox/combobox-root.vue";
@@ -7,25 +7,31 @@ import ComboboxTarget from "../combobox/combobox-target.vue";
7
7
  import TextInput from "../input/text-input.vue";
8
8
  import ButtonInput from "../input/ui/button-input.vue";
9
9
  const {
10
- data,
10
+ options: data,
11
11
  disabled,
12
12
  searchable = false,
13
+ multiple = false,
13
14
  rightSectionPE = "none",
14
15
  readonly = false,
15
16
  allowDeselect = false,
17
+ closeOnSelect,
16
18
  autoComplete = "off",
19
+ icon,
17
20
  limit,
18
21
  iconPosition,
19
22
  nothingFoundMessage,
20
- withCheckIcon,
23
+ withCheckIcon = true,
21
24
  ...rest
22
25
  } = defineProps({
23
- data: { type: Array, required: true },
26
+ options: { type: Array, required: true },
24
27
  searchable: { type: Boolean, required: false },
28
+ multiple: { type: Boolean, required: false },
25
29
  withCheckIcon: { type: Boolean, required: false },
26
30
  iconPosition: { type: String, required: false },
27
31
  nothingFoundMessage: { type: String, required: false },
28
32
  allowDeselect: { type: Boolean, required: false },
33
+ closeOnSelect: { type: Boolean, required: false },
34
+ icon: { type: String, required: false },
29
35
  limit: { type: Number, required: false },
30
36
  autoComplete: { type: String, required: false },
31
37
  withAria: { type: Boolean, required: false },
@@ -44,7 +50,8 @@ const {
44
50
  });
45
51
  const emit = defineEmits(["clear", "select", "open", "close", "submit"]);
46
52
  const opened = defineModel("open", { type: Boolean, ...{ default: false } });
47
- const value = defineModel({ type: [Object, null], ...{ default: null } });
53
+ const value = defineModel({ type: [String, Array, null], ...{ default: null } });
54
+ const search = defineModel("search", { type: String, ...{ default: "" } });
48
55
  const { parsed, options } = useComboboxData(data);
49
56
  const store = useCombobox({
50
57
  opened,
@@ -54,6 +61,8 @@ const store = useCombobox({
54
61
  onClear: () => emit("clear"),
55
62
  onOpenDropdown: (source) => {
56
63
  emit("open", source);
64
+ if (searchable)
65
+ search.value = "";
57
66
  store.updateSelectedOptionIx("active", { scrollIntoView: true });
58
67
  },
59
68
  onCloseDropdown: (source) => {
@@ -61,81 +70,106 @@ const store = useCombobox({
61
70
  nextTick(() => store.resetSelectedOption());
62
71
  }
63
72
  });
64
- const search = defineModel("search", { type: String, ...{ default: "" } });
65
73
  watch(search, () => nextTick(() => store.resetSelectedOption()));
74
+ const display = computed(() => {
75
+ const v = value.value;
76
+ if (multiple && Array.isArray(v))
77
+ return v.map((val) => options.value[val]?.label ?? val).join(", ");
78
+ if (v && typeof v === "string")
79
+ return options.value[v]?.label ?? v;
80
+ return "";
81
+ });
82
+ const focused = ref(false);
83
+ const inputValue = computed({
84
+ get: () => searchable && focused.value ? search.value : display.value,
85
+ set: (val) => {
86
+ search.value = val;
87
+ }
88
+ });
89
+ function onSubmit(val) {
90
+ const shouldClose = closeOnSelect ?? !multiple;
91
+ if (multiple) {
92
+ const current = Array.isArray(value.value) ? value.value : [];
93
+ value.value = current.includes(val) ? current.filter((v) => v !== val) : [...current, val];
94
+ search.value = "";
95
+ } else {
96
+ const nextValue = allowDeselect && value.value === val ? null : val;
97
+ value.value = options.value[val] ? nextValue : null;
98
+ search.value = "";
99
+ }
100
+ if (shouldClose)
101
+ store.closeDropdown();
102
+ }
66
103
  </script>
67
104
 
68
105
  <template>
69
- <ComboboxRoot
70
- v-model:open='opened'
71
- width='target'
72
- :store
106
+ <ComboboxRoot
107
+ v-model:open='opened'
108
+ width='target'
109
+ :store
73
110
  @submit='(val, option) => {
74
111
  $emit("submit", val, option);
75
- const optionsLockup = allowDeselect ? options[val]?.value === value?.value ? null : options[val] : options[val];
76
- const nextValue = optionsLockup ? optionsLockup : null;
77
- value = nextValue;
78
- search = nextValue?.label ?? "";
79
- store.closeDropdown();
80
- }'
81
- >
82
- <ComboboxTarget :target-type='searchable ? "input" : "button"' :auto-complete>
83
- <component
84
- :is='searchable ? TextInput : ButtonInput'
85
- :id='store.listId'
86
- v-bind='{ ...rest, ...$attrs }'
87
- v-model='search'
88
- :disabled
89
- :right-section-p-e
90
- :readonly='readonly || !searchable'
91
- :class='$style.input'
92
- @blur='() => {
93
- searchable && store.closeDropdown();
94
- search = value?.label ?? "";
95
- }'
96
- @click.prevent.stop='() => searchable ? store.openDropdown() : store.toggleDropdown()'
97
- >
98
- {{ value?.label ?? value?.value ?? null }}
99
-
100
- <template v-if='$slots?.label' #label>
101
- <slot name='label' />
102
- </template>
103
- <template v-if='$slots?.description' #description>
104
- <slot name='description' />
105
- </template>
106
- <template v-if='$slots?.error' #error>
107
- <slot name='error' />
108
- </template>
109
-
110
- <template v-if='$slots.leftSection || value?.icon' #leftSection>
111
- <slot name='leftSection'>
112
- <Icon v-if='value?.icon' :name='value?.icon' />
113
- </slot>
114
- </template>
115
- <template #rightSection>
116
- <slot name='rightSection'>
117
- <Icon name='gravity-ui:chevrons-expand-vertical' />
118
- </slot>
119
- </template>
120
- </component>
121
- </ComboboxTarget>
122
- <ComboboxOptionsDropdown
123
- v-model='value'
124
- :data='parsed'
125
- :limit
126
- :with-check-icon
127
- :icon-position
128
- :nothing-found-message
129
- :aria-label='store.listId'
130
- :label-id='store.listId'
131
- />
132
- </ComboboxRoot>
112
+ onSubmit(val);
113
+ }'
114
+ >
115
+ <ComboboxTarget :target-type='searchable ? "input" : "button"' :auto-complete>
116
+ <component
117
+ :is='searchable ? TextInput : ButtonInput'
118
+ :id='store.listId'
119
+ v-bind='{ ...rest, ...$attrs }'
120
+ v-model='inputValue'
121
+ :disabled
122
+ :right-section-p-e
123
+ :readonly='readonly || !searchable'
124
+ :class='$style.input'
125
+ @focus='focused = true'
126
+ @blur='focused = false'
127
+ @click.prevent.stop='() => searchable ? store.openDropdown() : store.toggleDropdown()'
128
+ >
129
+ <slot v-if='display' name='selection' :value='value' :display='display'>
130
+ {{ display }}
131
+ </slot>
132
+
133
+ <template v-if='$slots?.label' #label>
134
+ <slot name='label' />
135
+ </template>
136
+ <template v-if='$slots?.description' #description>
137
+ <slot name='description' />
138
+ </template>
139
+ <template v-if='$slots?.error' #error>
140
+ <slot name='error' />
141
+ </template>
142
+
143
+ <template v-if='$slots.leftSection || icon' #leftSection>
144
+ <slot name='leftSection'>
145
+ <Icon v-if='icon' :name='icon' />
146
+ </slot>
147
+ </template>
148
+ <template #rightSection>
149
+ <slot name='rightSection'>
150
+ <Icon name='gravity-ui:chevrons-expand-vertical' />
151
+ </slot>
152
+ </template>
153
+ </component>
154
+ </ComboboxTarget>
155
+ <ComboboxOptionsDropdown
156
+ v-model='value'
157
+ v-model:search='search'
158
+ :data='parsed'
159
+ :limit
160
+ :with-check-icon
161
+ :icon-position
162
+ :nothing-found-message
163
+ :aria-label='store.listId'
164
+ :label-id='store.listId'
165
+ />
166
+ </ComboboxRoot>
133
167
  </template>
134
168
 
135
169
  <style module lang="postcss">
136
- .input {
137
- :where([readonly]) {
138
- cursor: pointer;
139
- }
140
- }
170
+ .input {
171
+ :where([readonly]) {
172
+ cursor: pointer;
173
+ }
174
+ }
141
175
  </style>
@@ -1,9 +1,11 @@
1
- import type { ComboboxData, ComboboxItem, ComboboxItemExt } from '../combobox/index.js';
1
+ import type { ComboboxData, ComboboxItemExt } from '../combobox/index.js';
2
2
  import type { TextInputProps } from '../input/index.js';
3
3
  export interface SelectProps<Value extends string = string, Ext extends ComboboxItemExt = object> extends Omit<TextInputProps, 'modelValue' | 'multiline' | 'resize' | 'is' | 'id'> {
4
- data: ComboboxData<Value, Ext>;
4
+ options: ComboboxData<Value, Ext>;
5
5
  /** Determines whether the select should be searchable @default `false` */
6
6
  searchable?: boolean;
7
+ /** If set, multiple options can be selected @default `false` */
8
+ multiple?: boolean;
7
9
  /** If set, the check icon is displayed near the selected option label @default `true` */
8
10
  withCheckIcon?: boolean;
9
11
  /** Position of the check icon relative to the option label @default `'left'` */
@@ -12,23 +14,29 @@ export interface SelectProps<Value extends string = string, Ext extends Combobox
12
14
  nothingFoundMessage?: string;
13
15
  /** If set, it becomes possible to deselect value by clicking on the selected option @default `true` */
14
16
  allowDeselect?: boolean;
17
+ /** If set, the dropdown will close after an option is selected @default `!multiple` */
18
+ closeOnSelect?: boolean;
15
19
  /** If set, the clear button is displayed in the right section when the component has value @default `false` */
20
+ /** Icon displayed in the left section by default */
21
+ icon?: string;
16
22
  limit?: number;
17
- /** Props passed down to the underlying `ScrollArea` component in the dropdown */
18
23
  /** Input autocomplete attribute */
19
24
  autoComplete?: string;
20
25
  }
21
26
  declare const __VLS_export: <Value extends string = string, Ext extends ComboboxItemExt = object>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
22
27
  props: import("vue").PublicProps & __VLS_PrettifyLocal<(SelectProps<Value, Ext> & {
28
+ /** Dropdown opened state */
23
29
  open?: boolean;
24
- modelValue?: ComboboxItem<Value, Ext> | null;
30
+ /** Value handler */
31
+ modelValue?: string | string[] | null;
32
+ /** Search handler */
25
33
  search?: string;
26
34
  }) & {
27
35
  onSelect?: ((args_0: number) => any) | undefined;
28
36
  onClear?: (() => any) | undefined;
29
37
  onClose?: ((args_0: import("..").ComboboxDropdownEventSource) => any) | undefined;
30
- onSubmit?: ((args_0: string, args_1: ComboboxItem) => any) | undefined;
31
- "onUpdate:modelValue"?: ((value: ComboboxItem<Value, Ext> | null) => any) | undefined;
38
+ onSubmit?: ((args_0: string, args_1: import("..").ComboboxItem) => any) | undefined;
39
+ "onUpdate:modelValue"?: ((value: string | string[] | null) => any) | undefined;
32
40
  onOpen?: ((args_0: import("..").ComboboxDropdownEventSource) => any) | undefined;
33
41
  "onUpdate:search"?: ((value: string) => any) | undefined;
34
42
  "onUpdate:open"?: ((value: boolean) => any) | undefined;
@@ -38,6 +46,11 @@ declare const __VLS_export: <Value extends string = string, Ext extends Combobox
38
46
  expose: (exposed: {}) => void;
39
47
  attrs: any;
40
48
  slots: {
49
+ selection?: (props: {
50
+ value: string | string[] | null;
51
+ display: string;
52
+ }) => any;
53
+ } & {
41
54
  label?: (props: {}) => any;
42
55
  } & {
43
56
  description?: (props: {}) => any;
@@ -48,7 +61,7 @@ declare const __VLS_export: <Value extends string = string, Ext extends Combobox
48
61
  } & {
49
62
  rightSection?: (props: {}) => any;
50
63
  };
51
- emit: (((evt: "select", args_0: number) => void) & ((evt: "clear") => void) & ((evt: "close", args_0: import("..").ComboboxDropdownEventSource) => void) & ((evt: "submit", args_0: string, args_1: ComboboxItem) => void) & ((evt: "open", args_0: import("..").ComboboxDropdownEventSource) => void)) & (((event: "update:modelValue", value: ComboboxItem<Value, Ext> | null) => void) & ((event: "update:search", value: string) => void) & ((event: "update:open", value: boolean) => void));
64
+ emit: (((evt: "select", args_0: number) => void) & ((evt: "clear") => void) & ((evt: "close", args_0: import("..").ComboboxDropdownEventSource) => void) & ((evt: "submit", args_0: string, args_1: import("..").ComboboxItem) => void) & ((evt: "open", args_0: import("..").ComboboxDropdownEventSource) => void)) & (((event: "update:modelValue", value: string | string[] | null) => void) & ((event: "update:search", value: string) => void) & ((event: "update:open", value: boolean) => void));
52
65
  }>) => import("vue").VNode & {
53
66
  __ctx?: Awaited<typeof __VLS_setup>;
54
67
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuance-ui",
3
- "version": "0.2.2",
4
- "description": "A UI Library for Modern Web Apps, powered by Vue.",
3
+ "version": "0.2.6",
4
+ "description": "A modern Vue UI library inspired by the best of the React ecosystem.",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/Igor-Iugin/nuance-ui.git"
@@ -17,69 +17,30 @@
17
17
  "types": "./dist/runtime/composals/index.d.ts",
18
18
  "import": "./dist/runtime/composals/index.js"
19
19
  },
20
- "./composals/*": {
21
- "types": "./dist/runtime/composals/*.d.ts",
22
- "import": "./dist/runtime/composals/*.js"
23
- },
24
- "./components/*": {
25
- "types": "./dist/runtime/components/*.d.ts",
26
- "import": "./dist/runtime/components/*.js"
20
+ "./components": {
21
+ "types": "./dist/runtime/components/index.d.ts",
22
+ "import": "./dist/runtime/components/index.js"
27
23
  },
28
24
  "./modals": {
29
25
  "types": "./dist/runtime/modals/index.d.ts",
30
26
  "import": "./dist/runtime/modals/index.js"
31
27
  },
32
- "./modals/*": {
33
- "types": "./dist/runtime/modals/*.d.ts",
34
- "import": "./dist/runtime/modals/*.js"
35
- },
36
28
  "./helpers": {
37
29
  "types": "./dist/runtime/helpers/index.d.ts",
38
30
  "import": "./dist/runtime/helpers/index.js"
39
31
  },
40
- "./helpers/*": {
41
- "types": "./dist/runtime/helpers/*.d.ts",
42
- "import": "./dist/runtime/helpers/*.js"
43
- },
44
32
  "./utils": {
45
33
  "types": "./dist/runtime/utils/index.d.ts",
46
34
  "import": "./dist/runtime/utils/index.js"
47
35
  },
48
- "./utils/*": {
49
- "types": "./dist/runtime/utils/*.d.ts",
50
- "import": "./dist/runtime/utils/*.js"
51
- },
52
36
  "./types": {
53
37
  "types": "./dist/runtime/types/index.d.ts",
54
38
  "import": "./dist/runtime/types/index.js"
55
- },
56
- "./types/*": {
57
- "types": "./dist/runtime/types/*.d.ts",
58
- "import": "./dist/runtime/types/*.js"
59
39
  }
60
40
  },
61
41
  "main": "./dist/module.mjs",
62
- "typesVersions": {
63
- "*": {
64
- ".": [
65
- "./dist/types.d.mts"
66
- ],
67
- "composals": [
68
- "./dist/runtime/composals/index.d.ts"
69
- ],
70
- "modals": [
71
- "./dist/runtime/modals/index.d.ts"
72
- ],
73
- "helpers": [
74
- "./dist/runtime/helpers/index.d.ts"
75
- ],
76
- "utils": [
77
- "./dist/runtime/utils/index.d.ts"
78
- ],
79
- "types": [
80
- "./dist/runtime/types/index.d.ts"
81
- ]
82
- }
42
+ "publishConfig": {
43
+ "access": "public"
83
44
  },
84
45
  "files": [
85
46
  "dist"
@@ -125,14 +86,14 @@
125
86
  "@nuxt/eslint": "1.10.0",
126
87
  "@nuxt/eslint-config": "^1.13.0",
127
88
  "@nuxt/module-builder": "^1.0.2",
128
- "@nuxt/schema": "^4.3.0",
89
+ "@nuxt/schema": "^4.4.2",
129
90
  "@nuxt/test-utils": "^4.0.0",
130
91
  "@nuxtjs/color-mode": "^4.0.0",
131
92
  "@nuxtjs/stylelint-module": "^5.2.1",
132
93
  "@types/node": "latest",
133
94
  "changelogen": "^0.6.2",
134
95
  "eslint": "^9.39.2",
135
- "nuxt": "^4.3.0",
96
+ "nuxt": "^4.4.2",
136
97
  "postcss": "^8.5.6",
137
98
  "postcss-preset-mantine": "^1.18.0",
138
99
  "postcss-simple-vars": "^7.0.1",
@@ -157,4 +118,4 @@
157
118
  "vue-components",
158
119
  "ui"
159
120
  ]
160
- }
121
+ }
@@ -1,2 +0,0 @@
1
- import type { ComboboxItemExt, ComboboxParsedItem, ComboboxParsedItemGroup } from '../../types/index.js';
2
- export declare function isOptionsGroup<Value extends string = string, Ext extends ComboboxItemExt = object>(item: ComboboxParsedItem<Value, Ext>): item is ComboboxParsedItemGroup<Value, Ext>;