@youcan/celeste 0.6.16 → 0.6.17

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/celeste.css CHANGED
@@ -2068,21 +2068,21 @@ to {
2068
2068
  height: 40px;
2069
2069
  padding: var(--spacing-10);
2070
2070
  border-radius: var(--radius-10);
2071
- }[data-v-424c9dad] {
2071
+ }[data-v-8a46ca97] {
2072
2072
  box-sizing: border-box;
2073
2073
  }
2074
- .celeste-dropdown-anchor-trigger-prefix[data-v-424c9dad] {
2074
+ .celeste-dropdown-anchor-trigger-prefix[data-v-8a46ca97] {
2075
2075
  display: flex;
2076
2076
  align-items: center;
2077
2077
  justify-content: center;
2078
2078
  }
2079
- .celeste-dropdown-anchor-trigger-prefix-selected[data-v-424c9dad] {
2079
+ .celeste-dropdown-anchor-trigger-prefix-selected[data-v-8a46ca97] {
2080
2080
  display: flex;
2081
2081
  align-items: center;
2082
2082
  justify-content: center;
2083
2083
  }
2084
- .celeste-dropdown-item-image[data-v-424c9dad],
2085
- .selected-dropdown-image[data-v-424c9dad] {
2084
+ .celeste-dropdown-item-image[data-v-8a46ca97],
2085
+ .selected-dropdown-image[data-v-8a46ca97] {
2086
2086
  display: flex;
2087
2087
  align-items: center;
2088
2088
  justify-content: center;
@@ -2092,7 +2092,7 @@ to {
2092
2092
  object-fit: cover;
2093
2093
  border-radius: var(--radius-full);
2094
2094
  }
2095
- .celeste-dropdown-input[data-v-424c9dad] {
2095
+ .celeste-dropdown-input[data-v-8a46ca97] {
2096
2096
  display: flex;
2097
2097
  flex: 1 0 0;
2098
2098
  align-items: center;
@@ -2103,7 +2103,7 @@ to {
2103
2103
  cursor: pointer;
2104
2104
  gap: var(--spacing-8);
2105
2105
  }
2106
- .celeste-dropdown-trigger[data-v-424c9dad] {
2106
+ .celeste-dropdown-trigger[data-v-8a46ca97] {
2107
2107
  display: flex;
2108
2108
  place-items: center center;
2109
2109
  transition-property: transform;
@@ -2114,7 +2114,7 @@ to {
2114
2114
  color: var(--color-icon-soft-400);
2115
2115
  cursor: pointer;
2116
2116
  }
2117
- .celeste-dropdown-inner-input[data-v-424c9dad] {
2117
+ .celeste-dropdown-inner-input[data-v-8a46ca97] {
2118
2118
  display: flex;
2119
2119
  position: sticky;
2120
2120
  z-index: 50;
@@ -2123,7 +2123,7 @@ to {
2123
2123
  gap: var(--spacing-4);
2124
2124
  background-color: var(--color-bg-white-0);
2125
2125
  }
2126
- .celeste-dropdown-inner-input.sr-only[data-v-424c9dad] {
2126
+ .celeste-dropdown-inner-input.sr-only[data-v-8a46ca97] {
2127
2127
  position: absolute;
2128
2128
  width: 1px;
2129
2129
  height: 1px;
@@ -12,25 +12,24 @@ const comboboxRoot_vue_vue_type_script_setup_true_lang = require("./chunks/combo
12
12
  const comboboxSeparator = require("./combobox-separator.js");
13
13
  const comboboxTrigger = require("./combobox-trigger.js");
14
14
  const _pluginVue_exportHelper = require("./chunks/_plugin-vue_export-helper.js");
15
- const _hoisted_1 = { class: "root" };
16
- const _hoisted_2 = { class: "celeste-dropdown-anchor-trigger-prefix" };
17
- const _hoisted_3 = {
15
+ const _hoisted_1 = { class: "celeste-dropdown-anchor-trigger-prefix" };
16
+ const _hoisted_2 = {
18
17
  key: 0,
19
18
  class: "celeste-dropdown-anchor-trigger-prefix-selected"
20
19
  };
21
- const _hoisted_4 = { key: 1 };
22
- const _hoisted_5 = ["src"];
23
- const _hoisted_6 = {
20
+ const _hoisted_3 = { key: 1 };
21
+ const _hoisted_4 = ["src"];
22
+ const _hoisted_5 = {
24
23
  key: 0,
25
24
  class: "celeste-dropdown-input"
26
25
  };
27
- const _hoisted_7 = { key: 0 };
28
- const _hoisted_8 = { key: 1 };
29
- const _hoisted_9 = {
26
+ const _hoisted_6 = { key: 0 };
27
+ const _hoisted_7 = { key: 1 };
28
+ const _hoisted_8 = {
30
29
  key: 2,
31
30
  class: "celeste-input-badge"
32
31
  };
33
- const _hoisted_10 = ["src"];
32
+ const _hoisted_9 = ["src"];
34
33
  const _sfc_main = /* @__PURE__ */ Mo.defineComponent({
35
34
  __name: "combobox",
36
35
  props: {
@@ -63,17 +62,17 @@ const _sfc_main = /* @__PURE__ */ Mo.defineComponent({
63
62
  const props = __props;
64
63
  const emits = __emit;
65
64
  const delegatedProps = Mo.computed(() => {
66
- const { open, modelValue, filterFunction: filterFunction2, ...delegated } = props;
65
+ const { open, filterFunction, ...delegated } = props;
67
66
  return delegated;
68
67
  });
69
68
  const forwarded = index.xe(delegatedProps, emits);
70
- const selected = Mo.ref(props.multiple ? [] : void 0);
69
+ const model = Mo.computed(() => props.modelValue);
71
70
  function isSelected(value) {
72
- if (!Array.isArray(selected.value) || !props.multiple)
71
+ if (!Array.isArray(props.modelValue) || !props.multiple)
73
72
  return;
74
73
  if (value === void 0 || value === null)
75
74
  return false;
76
- return selected.value.some((selectedItem) => {
75
+ return props.modelValue.some((selectedItem) => {
77
76
  const { value: selectedValue } = selectedItem;
78
77
  if (props.valueBy && Object.prototype.hasOwnProperty.call(value, props.valueBy) && Object.prototype.hasOwnProperty.call(selectedValue, props.valueBy)) {
79
78
  return value[props.valueBy] === selectedValue[props.valueBy];
@@ -81,128 +80,111 @@ const _sfc_main = /* @__PURE__ */ Mo.defineComponent({
81
80
  return selectedValue === value;
82
81
  });
83
82
  }
84
- function filterFunction(list, searchTerm) {
85
- return list.filter((option) => {
86
- const { value, label } = option;
87
- if (!value || !label)
88
- return false;
89
- if (props.valueBy && typeof value === "object" && props.valueBy in value) {
90
- return String(value[props.valueBy]).toLowerCase().includes(searchTerm.toLowerCase()) || label.toString().toLowerCase().includes(searchTerm.toLowerCase());
91
- }
92
- return value.toString().toLowerCase().includes(searchTerm.toLowerCase()) || label.toString().toLowerCase().includes(searchTerm.toLowerCase());
93
- });
94
- }
95
83
  const mergedBadgeProps = Mo.computed(() => ({
96
84
  ...props.badgeProps,
97
85
  disabled: props.disabled
98
86
  }));
99
87
  return (_ctx, _cache) => {
100
- return Mo.openBlock(), Mo.createElementBlock("div", _hoisted_1, [
101
- Mo.createVNode(comboboxRoot_vue_vue_type_script_setup_true_lang._sfc_main, Mo.mergeProps(Mo.unref(forwarded), {
102
- "model-value": selected.value,
103
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => selected.value = $event),
104
- "filter-function": filterFunction
105
- }), {
106
- default: Mo.withCtx(() => [
107
- Mo.createVNode(comboboxAnchor_vue_vue_type_script_setup_true_lang._sfc_main, { "as-child": "" }, {
108
- default: Mo.withCtx(() => [
109
- Mo.createVNode(comboboxTrigger, {
110
- type: _ctx.type,
111
- filled: !!selected.value,
112
- size: _ctx.size
113
- }, {
114
- default: Mo.withCtx(() => [
115
- Mo.createElementVNode("div", _hoisted_2, [
116
- selected.value && !Array.isArray(selected.value) ? (Mo.openBlock(), Mo.createElementBlock("div", _hoisted_3, [
117
- selected.value.icon ? (Mo.openBlock(), Mo.createElementBlock("i", {
118
- key: 0,
119
- class: Mo.normalizeClass(selected.value.icon)
120
- }, null, 2)) : Mo.createCommentVNode("", true),
121
- selected.value.image ? (Mo.openBlock(), Mo.createElementBlock("div", _hoisted_4, [
122
- Mo.renderSlot(_ctx.$slots, "image", Mo.normalizeProps(Mo.guardReactiveProps({ selected: selected.value })), () => [
123
- Mo.createElementVNode("img", {
124
- src: selected.value.image,
125
- alt: "Selected option",
126
- class: "selected-dropdown-image"
127
- }, null, 8, _hoisted_5)
128
- ], true)
129
- ])) : Mo.createCommentVNode("", true)
130
- ])) : Mo.renderSlot(_ctx.$slots, "prefix", {
131
- key: 1,
132
- class: "celeste-dropdown-anchor-trigger-prefix-default"
133
- }, void 0, true)
134
- ]),
135
- _ctx.type !== "inline" ? (Mo.openBlock(), Mo.createElementBlock("div", _hoisted_6, [
136
- _ctx.multiple ? (Mo.openBlock(), Mo.createElementBlock("span", _hoisted_7, Mo.toDisplayString(_ctx.placeholder), 1)) : (Mo.openBlock(), Mo.createElementBlock("span", _hoisted_8, Mo.toDisplayString(selected.value && !Array.isArray(selected.value) ? selected.value.label : props.placeholder), 1)),
137
- mergedBadgeProps.value && _ctx.badgeProps ? (Mo.openBlock(), Mo.createElementBlock("span", _hoisted_9, [
138
- Mo.createVNode(badge, Mo.normalizeProps(Mo.guardReactiveProps(mergedBadgeProps.value)), null, 16)
88
+ return Mo.openBlock(), Mo.createBlock(comboboxRoot_vue_vue_type_script_setup_true_lang._sfc_main, Mo.mergeProps(Mo.unref(forwarded), { "filter-function": _ctx.filterFunction }), {
89
+ default: Mo.withCtx(() => [
90
+ Mo.createVNode(comboboxAnchor_vue_vue_type_script_setup_true_lang._sfc_main, { "as-child": "" }, {
91
+ default: Mo.withCtx(() => [
92
+ Mo.createVNode(comboboxTrigger, {
93
+ type: _ctx.type,
94
+ filled: !!model.value,
95
+ size: _ctx.size
96
+ }, {
97
+ default: Mo.withCtx(() => [
98
+ Mo.createElementVNode("div", _hoisted_1, [
99
+ model.value && !Array.isArray(model.value) ? (Mo.openBlock(), Mo.createElementBlock("div", _hoisted_2, [
100
+ model.value.icon ? (Mo.openBlock(), Mo.createElementBlock("i", {
101
+ key: 0,
102
+ class: Mo.normalizeClass(model.value.icon)
103
+ }, null, 2)) : Mo.createCommentVNode("", true),
104
+ model.value.image ? (Mo.openBlock(), Mo.createElementBlock("div", _hoisted_3, [
105
+ Mo.renderSlot(_ctx.$slots, "image", Mo.normalizeProps(Mo.guardReactiveProps({ selected: model.value })), () => [
106
+ Mo.createElementVNode("img", {
107
+ src: model.value.image,
108
+ alt: "Selected option",
109
+ class: "selected-dropdown-image"
110
+ }, null, 8, _hoisted_4)
111
+ ], true)
139
112
  ])) : Mo.createCommentVNode("", true)
140
- ])) : Mo.createCommentVNode("", true),
141
- _cache[1] || (_cache[1] = Mo.createElementVNode("div", { class: "celeste-dropdown-trigger" }, [
142
- Mo.createElementVNode("i", { class: "i-celeste-arrow-down-s-line" })
143
- ], -1))
113
+ ])) : Mo.renderSlot(_ctx.$slots, "prefix", {
114
+ key: 1,
115
+ class: "celeste-dropdown-anchor-trigger-prefix-default"
116
+ }, void 0, true)
144
117
  ]),
145
- _: 3
146
- }, 8, ["type", "filled", "size"])
147
- ]),
148
- _: 3
149
- }),
150
- Mo.createVNode(comboboxList, null, {
151
- default: Mo.withCtx(() => [
152
- Mo.createElementVNode("div", {
153
- class: Mo.normalizeClass(["celeste-dropdown-inner-input", { "sr-only": !_ctx.searchable }])
154
- }, [
155
- Mo.createVNode(comboboxInput, { searchable: _ctx.searchable }, null, 8, ["searchable"]),
156
- _ctx.searchable ? (Mo.openBlock(), Mo.createBlock(comboboxSeparator, { key: 0 })) : Mo.createCommentVNode("", true)
157
- ], 2),
158
- Mo.createVNode(comboboxEmpty, null, Mo.createSlots({ _: 2 }, [
159
- _ctx.emptyLabel ? {
160
- name: "default",
161
- fn: Mo.withCtx(() => [
162
- Mo.createTextVNode(Mo.toDisplayString(_ctx.emptyLabel), 1)
163
- ]),
164
- key: "0"
165
- } : void 0
166
- ]), 1024),
167
- Mo.createVNode(comboboxGroup, null, {
168
- default: Mo.withCtx(() => [
169
- (Mo.openBlock(true), Mo.createElementBlock(Mo.Fragment, null, Mo.renderList(props.options, (option) => {
170
- return Mo.openBlock(), Mo.createBlock(comboboxItem, {
171
- key: option.label,
172
- label: option.label,
173
- sublabel: option.sublabel,
174
- description: option.description,
175
- checkbox: props.multiple,
176
- value: option,
177
- selected: isSelected(option.value)
178
- }, {
179
- prefix: Mo.withCtx(() => [
180
- option.icon ? (Mo.openBlock(), Mo.createElementBlock("i", {
181
- key: 0,
182
- class: Mo.normalizeClass(option.icon)
183
- }, null, 2)) : Mo.createCommentVNode("", true),
184
- option.image ? (Mo.openBlock(), Mo.createElementBlock("img", {
185
- key: 1,
186
- src: option.image,
187
- alt: "option",
188
- class: "celeste-dropdown-item-image"
189
- }, null, 8, _hoisted_10)) : Mo.createCommentVNode("", true)
190
- ]),
191
- _: 2
192
- }, 1032, ["label", "sublabel", "description", "checkbox", "value", "selected"]);
193
- }), 128))
118
+ _ctx.type !== "inline" ? (Mo.openBlock(), Mo.createElementBlock("div", _hoisted_5, [
119
+ _ctx.multiple ? (Mo.openBlock(), Mo.createElementBlock("span", _hoisted_6, Mo.toDisplayString(_ctx.placeholder), 1)) : (Mo.openBlock(), Mo.createElementBlock("span", _hoisted_7, Mo.toDisplayString(model.value && !Array.isArray(model.value) ? model.value.label : props.placeholder), 1)),
120
+ mergedBadgeProps.value && _ctx.badgeProps ? (Mo.openBlock(), Mo.createElementBlock("span", _hoisted_8, [
121
+ Mo.createVNode(badge, Mo.normalizeProps(Mo.guardReactiveProps(mergedBadgeProps.value)), null, 16)
122
+ ])) : Mo.createCommentVNode("", true)
123
+ ])) : Mo.createCommentVNode("", true),
124
+ _cache[0] || (_cache[0] = Mo.createElementVNode("div", { class: "celeste-dropdown-trigger" }, [
125
+ Mo.createElementVNode("i", { class: "i-celeste-arrow-down-s-line" })
126
+ ], -1))
127
+ ]),
128
+ _: 3
129
+ }, 8, ["type", "filled", "size"])
130
+ ]),
131
+ _: 3
132
+ }),
133
+ Mo.createVNode(comboboxList, null, {
134
+ default: Mo.withCtx(() => [
135
+ Mo.createElementVNode("div", {
136
+ class: Mo.normalizeClass(["celeste-dropdown-inner-input", { "sr-only": !_ctx.searchable }])
137
+ }, [
138
+ Mo.createVNode(comboboxInput, { searchable: _ctx.searchable }, null, 8, ["searchable"]),
139
+ _ctx.searchable ? (Mo.openBlock(), Mo.createBlock(comboboxSeparator, { key: 0 })) : Mo.createCommentVNode("", true)
140
+ ], 2),
141
+ Mo.createVNode(comboboxEmpty, null, Mo.createSlots({ _: 2 }, [
142
+ _ctx.emptyLabel ? {
143
+ name: "default",
144
+ fn: Mo.withCtx(() => [
145
+ Mo.createTextVNode(Mo.toDisplayString(_ctx.emptyLabel), 1)
194
146
  ]),
195
- _: 1
196
- })
197
- ]),
198
- _: 1
199
- })
200
- ]),
201
- _: 3
202
- }, 16, ["model-value"])
203
- ]);
147
+ key: "0"
148
+ } : void 0
149
+ ]), 1024),
150
+ Mo.createVNode(comboboxGroup, null, {
151
+ default: Mo.withCtx(() => [
152
+ (Mo.openBlock(true), Mo.createElementBlock(Mo.Fragment, null, Mo.renderList(props.options, (option) => {
153
+ return Mo.openBlock(), Mo.createBlock(comboboxItem, {
154
+ key: option.label,
155
+ label: option.label,
156
+ sublabel: option.sublabel,
157
+ description: option.description,
158
+ checkbox: props.multiple,
159
+ value: option,
160
+ selected: isSelected(option.value)
161
+ }, {
162
+ prefix: Mo.withCtx(() => [
163
+ option.icon ? (Mo.openBlock(), Mo.createElementBlock("i", {
164
+ key: 0,
165
+ class: Mo.normalizeClass(option.icon)
166
+ }, null, 2)) : Mo.createCommentVNode("", true),
167
+ option.image ? (Mo.openBlock(), Mo.createElementBlock("img", {
168
+ key: 1,
169
+ src: option.image,
170
+ alt: "option",
171
+ class: "celeste-dropdown-item-image"
172
+ }, null, 8, _hoisted_9)) : Mo.createCommentVNode("", true)
173
+ ]),
174
+ _: 2
175
+ }, 1032, ["label", "sublabel", "description", "checkbox", "value", "selected"]);
176
+ }), 128))
177
+ ]),
178
+ _: 1
179
+ })
180
+ ]),
181
+ _: 1
182
+ })
183
+ ]),
184
+ _: 3
185
+ }, 16, ["filter-function"]);
204
186
  };
205
187
  }
206
188
  });
207
- const combobox = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main, [["__scopeId", "data-v-424c9dad"]]);
189
+ const combobox = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main, [["__scopeId", "data-v-8a46ca97"]]);
208
190
  module.exports = combobox;
@@ -24,22 +24,9 @@ declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<Co
24
24
  }>, {
25
25
  size: "xs" | "sm" | "md";
26
26
  placeholder: string;
27
- }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>, {
27
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>, {
28
28
  image?(_: {
29
- selected: {
30
- class?: import('vue').HTMLAttributes["class"];
31
- label: string;
32
- size?: "sm" | "lg" | undefined;
33
- checkbox?: boolean | undefined;
34
- sublabel?: string | undefined;
35
- description?: string | undefined;
36
- selected?: boolean | "indeterminate" | undefined;
37
- focused?: boolean | undefined;
38
- value: string | number | boolean | Record<string, any>;
39
- icon?: string | undefined;
40
- image?: string | undefined;
41
- disabled?: boolean | undefined;
42
- };
29
+ selected: ComboboxItemPropsType;
43
30
  }): any;
44
31
  prefix?(_: {
45
32
  class: string;
@@ -1,4 +1,4 @@
1
- import { defineComponent, computed, ref, openBlock, createElementBlock, createVNode, mergeProps, unref, withCtx, createElementVNode, normalizeClass, createCommentVNode, renderSlot, normalizeProps, guardReactiveProps, toDisplayString, createBlock, createSlots, createTextVNode, Fragment, renderList } from "vue";
1
+ import { defineComponent, computed, openBlock, createBlock, mergeProps, unref, withCtx, createVNode, createElementVNode, createElementBlock, normalizeClass, createCommentVNode, renderSlot, normalizeProps, guardReactiveProps, toDisplayString, createSlots, createTextVNode, Fragment, renderList } from "vue";
2
2
  import { x as xe } from "./chunks/index.js";
3
3
  import Badge from "./badge.js";
4
4
  import { _ as _sfc_main$2 } from "./chunks/combobox-anchor.js";
@@ -11,25 +11,24 @@ import { _ as _sfc_main$1 } from "./chunks/combobox-root.js";
11
11
  import ComboboxSeparator from "./combobox-separator.js";
12
12
  import ComboboxTrigger from "./combobox-trigger.js";
13
13
  import { _ as _export_sfc } from "./chunks/_plugin-vue_export-helper.js";
14
- const _hoisted_1 = { class: "root" };
15
- const _hoisted_2 = { class: "celeste-dropdown-anchor-trigger-prefix" };
16
- const _hoisted_3 = {
14
+ const _hoisted_1 = { class: "celeste-dropdown-anchor-trigger-prefix" };
15
+ const _hoisted_2 = {
17
16
  key: 0,
18
17
  class: "celeste-dropdown-anchor-trigger-prefix-selected"
19
18
  };
20
- const _hoisted_4 = { key: 1 };
21
- const _hoisted_5 = ["src"];
22
- const _hoisted_6 = {
19
+ const _hoisted_3 = { key: 1 };
20
+ const _hoisted_4 = ["src"];
21
+ const _hoisted_5 = {
23
22
  key: 0,
24
23
  class: "celeste-dropdown-input"
25
24
  };
26
- const _hoisted_7 = { key: 0 };
27
- const _hoisted_8 = { key: 1 };
28
- const _hoisted_9 = {
25
+ const _hoisted_6 = { key: 0 };
26
+ const _hoisted_7 = { key: 1 };
27
+ const _hoisted_8 = {
29
28
  key: 2,
30
29
  class: "celeste-input-badge"
31
30
  };
32
- const _hoisted_10 = ["src"];
31
+ const _hoisted_9 = ["src"];
33
32
  const _sfc_main = /* @__PURE__ */ defineComponent({
34
33
  __name: "combobox",
35
34
  props: {
@@ -62,17 +61,17 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
62
61
  const props = __props;
63
62
  const emits = __emit;
64
63
  const delegatedProps = computed(() => {
65
- const { open, modelValue, filterFunction: filterFunction2, ...delegated } = props;
64
+ const { open, filterFunction, ...delegated } = props;
66
65
  return delegated;
67
66
  });
68
67
  const forwarded = xe(delegatedProps, emits);
69
- const selected = ref(props.multiple ? [] : void 0);
68
+ const model = computed(() => props.modelValue);
70
69
  function isSelected(value) {
71
- if (!Array.isArray(selected.value) || !props.multiple)
70
+ if (!Array.isArray(props.modelValue) || !props.multiple)
72
71
  return;
73
72
  if (value === void 0 || value === null)
74
73
  return false;
75
- return selected.value.some((selectedItem) => {
74
+ return props.modelValue.some((selectedItem) => {
76
75
  const { value: selectedValue } = selectedItem;
77
76
  if (props.valueBy && Object.prototype.hasOwnProperty.call(value, props.valueBy) && Object.prototype.hasOwnProperty.call(selectedValue, props.valueBy)) {
78
77
  return value[props.valueBy] === selectedValue[props.valueBy];
@@ -80,130 +79,113 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
80
79
  return selectedValue === value;
81
80
  });
82
81
  }
83
- function filterFunction(list, searchTerm) {
84
- return list.filter((option) => {
85
- const { value, label } = option;
86
- if (!value || !label)
87
- return false;
88
- if (props.valueBy && typeof value === "object" && props.valueBy in value) {
89
- return String(value[props.valueBy]).toLowerCase().includes(searchTerm.toLowerCase()) || label.toString().toLowerCase().includes(searchTerm.toLowerCase());
90
- }
91
- return value.toString().toLowerCase().includes(searchTerm.toLowerCase()) || label.toString().toLowerCase().includes(searchTerm.toLowerCase());
92
- });
93
- }
94
82
  const mergedBadgeProps = computed(() => ({
95
83
  ...props.badgeProps,
96
84
  disabled: props.disabled
97
85
  }));
98
86
  return (_ctx, _cache) => {
99
- return openBlock(), createElementBlock("div", _hoisted_1, [
100
- createVNode(_sfc_main$1, mergeProps(unref(forwarded), {
101
- "model-value": selected.value,
102
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => selected.value = $event),
103
- "filter-function": filterFunction
104
- }), {
105
- default: withCtx(() => [
106
- createVNode(_sfc_main$2, { "as-child": "" }, {
107
- default: withCtx(() => [
108
- createVNode(ComboboxTrigger, {
109
- type: _ctx.type,
110
- filled: !!selected.value,
111
- size: _ctx.size
112
- }, {
113
- default: withCtx(() => [
114
- createElementVNode("div", _hoisted_2, [
115
- selected.value && !Array.isArray(selected.value) ? (openBlock(), createElementBlock("div", _hoisted_3, [
116
- selected.value.icon ? (openBlock(), createElementBlock("i", {
117
- key: 0,
118
- class: normalizeClass(selected.value.icon)
119
- }, null, 2)) : createCommentVNode("", true),
120
- selected.value.image ? (openBlock(), createElementBlock("div", _hoisted_4, [
121
- renderSlot(_ctx.$slots, "image", normalizeProps(guardReactiveProps({ selected: selected.value })), () => [
122
- createElementVNode("img", {
123
- src: selected.value.image,
124
- alt: "Selected option",
125
- class: "selected-dropdown-image"
126
- }, null, 8, _hoisted_5)
127
- ], true)
128
- ])) : createCommentVNode("", true)
129
- ])) : renderSlot(_ctx.$slots, "prefix", {
130
- key: 1,
131
- class: "celeste-dropdown-anchor-trigger-prefix-default"
132
- }, void 0, true)
133
- ]),
134
- _ctx.type !== "inline" ? (openBlock(), createElementBlock("div", _hoisted_6, [
135
- _ctx.multiple ? (openBlock(), createElementBlock("span", _hoisted_7, toDisplayString(_ctx.placeholder), 1)) : (openBlock(), createElementBlock("span", _hoisted_8, toDisplayString(selected.value && !Array.isArray(selected.value) ? selected.value.label : props.placeholder), 1)),
136
- mergedBadgeProps.value && _ctx.badgeProps ? (openBlock(), createElementBlock("span", _hoisted_9, [
137
- createVNode(Badge, normalizeProps(guardReactiveProps(mergedBadgeProps.value)), null, 16)
87
+ return openBlock(), createBlock(_sfc_main$1, mergeProps(unref(forwarded), { "filter-function": _ctx.filterFunction }), {
88
+ default: withCtx(() => [
89
+ createVNode(_sfc_main$2, { "as-child": "" }, {
90
+ default: withCtx(() => [
91
+ createVNode(ComboboxTrigger, {
92
+ type: _ctx.type,
93
+ filled: !!model.value,
94
+ size: _ctx.size
95
+ }, {
96
+ default: withCtx(() => [
97
+ createElementVNode("div", _hoisted_1, [
98
+ model.value && !Array.isArray(model.value) ? (openBlock(), createElementBlock("div", _hoisted_2, [
99
+ model.value.icon ? (openBlock(), createElementBlock("i", {
100
+ key: 0,
101
+ class: normalizeClass(model.value.icon)
102
+ }, null, 2)) : createCommentVNode("", true),
103
+ model.value.image ? (openBlock(), createElementBlock("div", _hoisted_3, [
104
+ renderSlot(_ctx.$slots, "image", normalizeProps(guardReactiveProps({ selected: model.value })), () => [
105
+ createElementVNode("img", {
106
+ src: model.value.image,
107
+ alt: "Selected option",
108
+ class: "selected-dropdown-image"
109
+ }, null, 8, _hoisted_4)
110
+ ], true)
138
111
  ])) : createCommentVNode("", true)
139
- ])) : createCommentVNode("", true),
140
- _cache[1] || (_cache[1] = createElementVNode("div", { class: "celeste-dropdown-trigger" }, [
141
- createElementVNode("i", { class: "i-celeste-arrow-down-s-line" })
142
- ], -1))
112
+ ])) : renderSlot(_ctx.$slots, "prefix", {
113
+ key: 1,
114
+ class: "celeste-dropdown-anchor-trigger-prefix-default"
115
+ }, void 0, true)
143
116
  ]),
144
- _: 3
145
- }, 8, ["type", "filled", "size"])
146
- ]),
147
- _: 3
148
- }),
149
- createVNode(ComboboxList, null, {
150
- default: withCtx(() => [
151
- createElementVNode("div", {
152
- class: normalizeClass(["celeste-dropdown-inner-input", { "sr-only": !_ctx.searchable }])
153
- }, [
154
- createVNode(ComboboxInput, { searchable: _ctx.searchable }, null, 8, ["searchable"]),
155
- _ctx.searchable ? (openBlock(), createBlock(ComboboxSeparator, { key: 0 })) : createCommentVNode("", true)
156
- ], 2),
157
- createVNode(ComboboxEmpty, null, createSlots({ _: 2 }, [
158
- _ctx.emptyLabel ? {
159
- name: "default",
160
- fn: withCtx(() => [
161
- createTextVNode(toDisplayString(_ctx.emptyLabel), 1)
162
- ]),
163
- key: "0"
164
- } : void 0
165
- ]), 1024),
166
- createVNode(ComboboxGroup, null, {
167
- default: withCtx(() => [
168
- (openBlock(true), createElementBlock(Fragment, null, renderList(props.options, (option) => {
169
- return openBlock(), createBlock(ComboboxItem, {
170
- key: option.label,
171
- label: option.label,
172
- sublabel: option.sublabel,
173
- description: option.description,
174
- checkbox: props.multiple,
175
- value: option,
176
- selected: isSelected(option.value)
177
- }, {
178
- prefix: withCtx(() => [
179
- option.icon ? (openBlock(), createElementBlock("i", {
180
- key: 0,
181
- class: normalizeClass(option.icon)
182
- }, null, 2)) : createCommentVNode("", true),
183
- option.image ? (openBlock(), createElementBlock("img", {
184
- key: 1,
185
- src: option.image,
186
- alt: "option",
187
- class: "celeste-dropdown-item-image"
188
- }, null, 8, _hoisted_10)) : createCommentVNode("", true)
189
- ]),
190
- _: 2
191
- }, 1032, ["label", "sublabel", "description", "checkbox", "value", "selected"]);
192
- }), 128))
117
+ _ctx.type !== "inline" ? (openBlock(), createElementBlock("div", _hoisted_5, [
118
+ _ctx.multiple ? (openBlock(), createElementBlock("span", _hoisted_6, toDisplayString(_ctx.placeholder), 1)) : (openBlock(), createElementBlock("span", _hoisted_7, toDisplayString(model.value && !Array.isArray(model.value) ? model.value.label : props.placeholder), 1)),
119
+ mergedBadgeProps.value && _ctx.badgeProps ? (openBlock(), createElementBlock("span", _hoisted_8, [
120
+ createVNode(Badge, normalizeProps(guardReactiveProps(mergedBadgeProps.value)), null, 16)
121
+ ])) : createCommentVNode("", true)
122
+ ])) : createCommentVNode("", true),
123
+ _cache[0] || (_cache[0] = createElementVNode("div", { class: "celeste-dropdown-trigger" }, [
124
+ createElementVNode("i", { class: "i-celeste-arrow-down-s-line" })
125
+ ], -1))
126
+ ]),
127
+ _: 3
128
+ }, 8, ["type", "filled", "size"])
129
+ ]),
130
+ _: 3
131
+ }),
132
+ createVNode(ComboboxList, null, {
133
+ default: withCtx(() => [
134
+ createElementVNode("div", {
135
+ class: normalizeClass(["celeste-dropdown-inner-input", { "sr-only": !_ctx.searchable }])
136
+ }, [
137
+ createVNode(ComboboxInput, { searchable: _ctx.searchable }, null, 8, ["searchable"]),
138
+ _ctx.searchable ? (openBlock(), createBlock(ComboboxSeparator, { key: 0 })) : createCommentVNode("", true)
139
+ ], 2),
140
+ createVNode(ComboboxEmpty, null, createSlots({ _: 2 }, [
141
+ _ctx.emptyLabel ? {
142
+ name: "default",
143
+ fn: withCtx(() => [
144
+ createTextVNode(toDisplayString(_ctx.emptyLabel), 1)
193
145
  ]),
194
- _: 1
195
- })
196
- ]),
197
- _: 1
198
- })
199
- ]),
200
- _: 3
201
- }, 16, ["model-value"])
202
- ]);
146
+ key: "0"
147
+ } : void 0
148
+ ]), 1024),
149
+ createVNode(ComboboxGroup, null, {
150
+ default: withCtx(() => [
151
+ (openBlock(true), createElementBlock(Fragment, null, renderList(props.options, (option) => {
152
+ return openBlock(), createBlock(ComboboxItem, {
153
+ key: option.label,
154
+ label: option.label,
155
+ sublabel: option.sublabel,
156
+ description: option.description,
157
+ checkbox: props.multiple,
158
+ value: option,
159
+ selected: isSelected(option.value)
160
+ }, {
161
+ prefix: withCtx(() => [
162
+ option.icon ? (openBlock(), createElementBlock("i", {
163
+ key: 0,
164
+ class: normalizeClass(option.icon)
165
+ }, null, 2)) : createCommentVNode("", true),
166
+ option.image ? (openBlock(), createElementBlock("img", {
167
+ key: 1,
168
+ src: option.image,
169
+ alt: "option",
170
+ class: "celeste-dropdown-item-image"
171
+ }, null, 8, _hoisted_9)) : createCommentVNode("", true)
172
+ ]),
173
+ _: 2
174
+ }, 1032, ["label", "sublabel", "description", "checkbox", "value", "selected"]);
175
+ }), 128))
176
+ ]),
177
+ _: 1
178
+ })
179
+ ]),
180
+ _: 1
181
+ })
182
+ ]),
183
+ _: 3
184
+ }, 16, ["filter-function"]);
203
185
  };
204
186
  }
205
187
  });
206
- const combobox = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-424c9dad"]]);
188
+ const combobox = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-8a46ca97"]]);
207
189
  export {
208
190
  combobox as default
209
191
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@youcan/celeste",
3
3
  "type": "module",
4
- "version": "0.6.16",
4
+ "version": "0.6.17",
5
5
  "author": "YouCan <tech@youcan.shop>",
6
6
  "keywords": [
7
7
  "youcan",
@@ -32,8 +32,8 @@
32
32
  "clsx": "^2.1.1",
33
33
  "radix-vue": "^1.9.12",
34
34
  "tinycolor2": "^1.6.0",
35
- "@youcan/celeste-icons": "0.6.16",
36
- "@youcan/celeste-tokens": "0.6.16"
35
+ "@youcan/celeste-icons": "0.6.17",
36
+ "@youcan/celeste-tokens": "0.6.17"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@chromatic-com/storybook": "^4.0.0",
@@ -4,7 +4,7 @@ import type { BadgeProps } from '../badge/badge.vue';
4
4
  import type { ComboboxItemPropsType } from './combobox-item.vue';
5
5
 
6
6
  import { useForwardPropsEmits } from 'radix-vue';
7
- import { computed, ref } from 'vue';
7
+ import { computed } from 'vue';
8
8
  import Badge from '../badge/badge.vue';
9
9
  import ComboboxAnchor from './combobox-anchor.vue';
10
10
  import ComboboxEmpty from './combobox-empty.vue';
@@ -23,22 +23,23 @@ const props = withDefaults(defineProps<ComboboxPropsType>(), {
23
23
  const emits = defineEmits<ComboboxRootEmits>();
24
24
 
25
25
  const delegatedProps = computed(() => {
26
- const { open, modelValue, filterFunction, ...delegated } = props;
26
+ const { open, filterFunction, ...delegated } = props;
27
27
 
28
28
  return delegated;
29
29
  });
30
30
 
31
31
  const forwarded = useForwardPropsEmits(delegatedProps, emits);
32
- const selected = ref<ComboboxItemPropsType[] | ComboboxItemPropsType | undefined>(props.multiple ? [] : undefined);
32
+
33
+ const model = computed(() => props.modelValue as ComboboxItemPropsType[] | ComboboxItemPropsType | undefined);
33
34
 
34
35
  function isSelected(value: ComboboxItemPropsType['value']): boolean | undefined {
35
- if (!Array.isArray(selected.value) || !props.multiple)
36
+ if (!Array.isArray(props.modelValue) || !props.multiple)
36
37
  return;
37
38
 
38
39
  if (value === undefined || value === null)
39
40
  return false;
40
41
 
41
- return selected.value.some((selectedItem: ComboboxItemPropsType) => {
42
+ return props.modelValue.some((selectedItem: ComboboxItemPropsType) => {
42
43
  const { value: selectedValue } = selectedItem;
43
44
 
44
45
  if (
@@ -52,26 +53,6 @@ function isSelected(value: ComboboxItemPropsType['value']): boolean | undefined
52
53
  });
53
54
  }
54
55
 
55
- function filterFunction(list: any[], searchTerm: string) {
56
- return list.filter((option: ComboboxItemPropsType) => {
57
- const { value, label } = option;
58
-
59
- if (!value || !label)
60
- return false;
61
-
62
- if (
63
- props.valueBy
64
- && typeof value === 'object'
65
- && props.valueBy in value) {
66
- return String(value[props.valueBy]).toLowerCase().includes(searchTerm.toLowerCase())
67
- || label.toString().toLowerCase().includes(searchTerm.toLowerCase());
68
- }
69
-
70
- return value.toString().toLowerCase().includes(searchTerm.toLowerCase())
71
- || label.toString().toLowerCase().includes(searchTerm.toLowerCase());
72
- });
73
- }
74
-
75
56
  const mergedBadgeProps = computed(() => ({
76
57
  ...props.badgeProps,
77
58
  disabled: props.disabled,
@@ -92,93 +73,90 @@ export interface ComboboxPropsType extends ComboboxRootProps {
92
73
  </script>
93
74
 
94
75
  <template>
95
- <div class="root">
96
- <ComboboxRoot
97
- v-bind="forwarded"
98
- v-model:model-value="selected"
99
- :filter-function="filterFunction"
100
- >
101
- <ComboboxAnchor as-child>
102
- <ComboboxTrigger
103
- :type="type"
104
- :filled="!!selected"
105
- :size="size"
106
- >
107
- <div class="celeste-dropdown-anchor-trigger-prefix">
108
- <div v-if="selected && !Array.isArray(selected)" class="celeste-dropdown-anchor-trigger-prefix-selected">
109
- <i v-if="selected.icon" :class="selected.icon" />
110
- <div v-if="selected.image">
111
- <slot name="image" v-bind="{ selected }">
112
- <img
113
- :src="selected.image"
114
- alt="Selected option"
115
- class="selected-dropdown-image"
116
- >
117
- </slot>
118
- </div>
76
+ <ComboboxRoot
77
+ v-bind="forwarded"
78
+ :filter-function="filterFunction"
79
+ >
80
+ <ComboboxAnchor as-child>
81
+ <ComboboxTrigger
82
+ :type="type"
83
+ :filled="!!model"
84
+ :size="size"
85
+ >
86
+ <div class="celeste-dropdown-anchor-trigger-prefix">
87
+ <div v-if="model && !Array.isArray(model)" class="celeste-dropdown-anchor-trigger-prefix-selected">
88
+ <i v-if="model.icon" :class="model.icon" />
89
+ <div v-if="model.image">
90
+ <slot name="image" v-bind="{ selected: model }">
91
+ <img
92
+ :src="model.image"
93
+ alt="Selected option"
94
+ class="selected-dropdown-image"
95
+ >
96
+ </slot>
119
97
  </div>
120
- <slot
121
- v-else
122
- name="prefix"
123
- class="celeste-dropdown-anchor-trigger-prefix-default"
124
- />
125
- </div>
126
-
127
- <div
128
- v-if="type !== 'inline'"
129
- class="celeste-dropdown-input"
130
- >
131
- <span v-if="multiple">{{ placeholder }}</span>
132
- <span v-else>
133
- {{ selected && !Array.isArray(selected) ? selected.label : props.placeholder }}
134
- </span>
135
- <span v-if="mergedBadgeProps && badgeProps" class="celeste-input-badge">
136
- <Badge v-bind="mergedBadgeProps" />
137
- </span>
138
98
  </div>
139
- <div class="celeste-dropdown-trigger">
140
- <i class="i-celeste-arrow-down-s-line" />
141
- </div>
142
- </ComboboxTrigger>
143
- </ComboboxAnchor>
144
-
145
- <ComboboxList>
146
- <div class="celeste-dropdown-inner-input" :class="{ 'sr-only': !searchable }">
147
- <ComboboxInput :searchable="searchable" />
148
- <ComboboxSeparator v-if="searchable" />
99
+ <slot
100
+ v-else
101
+ name="prefix"
102
+ class="celeste-dropdown-anchor-trigger-prefix-default"
103
+ />
149
104
  </div>
150
105
 
151
- <ComboboxEmpty>
152
- <template v-if="emptyLabel" #default>
153
- {{ emptyLabel }}
106
+ <div
107
+ v-if="type !== 'inline'"
108
+ class="celeste-dropdown-input"
109
+ >
110
+ <span v-if="multiple">{{ placeholder }}</span>
111
+ <span v-else>
112
+ {{ model && !Array.isArray(model) ? model.label : props.placeholder }}
113
+ </span>
114
+ <span v-if="mergedBadgeProps && badgeProps" class="celeste-input-badge">
115
+ <Badge v-bind="mergedBadgeProps" />
116
+ </span>
117
+ </div>
118
+ <div class="celeste-dropdown-trigger">
119
+ <i class="i-celeste-arrow-down-s-line" />
120
+ </div>
121
+ </ComboboxTrigger>
122
+ </ComboboxAnchor>
123
+
124
+ <ComboboxList>
125
+ <div class="celeste-dropdown-inner-input" :class="{ 'sr-only': !searchable }">
126
+ <ComboboxInput :searchable="searchable" />
127
+ <ComboboxSeparator v-if="searchable" />
128
+ </div>
129
+
130
+ <ComboboxEmpty>
131
+ <template v-if="emptyLabel" #default>
132
+ {{ emptyLabel }}
133
+ </template>
134
+ </ComboboxEmpty>
135
+
136
+ <ComboboxGroup>
137
+ <ComboboxItem
138
+ v-for="option in props.options"
139
+ :key="option.label"
140
+ :label="option.label"
141
+ :sublabel="option.sublabel"
142
+ :description="option.description"
143
+ :checkbox="props.multiple"
144
+ :value="option"
145
+ :selected="isSelected(option.value)"
146
+ >
147
+ <template #prefix>
148
+ <i v-if="option.icon" :class="option.icon" />
149
+ <img
150
+ v-if="option.image"
151
+ :src="option.image"
152
+ alt="option"
153
+ class="celeste-dropdown-item-image"
154
+ >
154
155
  </template>
155
- </ComboboxEmpty>
156
-
157
- <ComboboxGroup>
158
- <ComboboxItem
159
- v-for="option in props.options"
160
- :key="option.label"
161
- :label="option.label"
162
- :sublabel="option.sublabel"
163
- :description="option.description"
164
- :checkbox="props.multiple"
165
- :value="option"
166
- :selected="isSelected(option.value)"
167
- >
168
- <template #prefix>
169
- <i v-if="option.icon" :class="option.icon" />
170
- <img
171
- v-if="option.image"
172
- :src="option.image"
173
- alt="option"
174
- class="celeste-dropdown-item-image"
175
- >
176
- </template>
177
- </ComboboxItem>
178
- </ComboboxGroup>
179
- </ComboboxList>
180
- </ComboboxRoot>
181
- </div>
156
+ </ComboboxItem>
157
+ </ComboboxGroup>
158
+ </ComboboxList>
159
+ </ComboboxRoot>
182
160
  </template>
183
161
 
184
162
  <style lang="scss" scoped>
@@ -1,4 +1,5 @@
1
1
  import type { Meta, StoryObj } from '@storybook/vue3-vite';
2
+ import { ref } from 'vue';
2
3
  import Combobox from '../combobox.vue';
3
4
 
4
5
  const meta: Meta<typeof Combobox> = {
@@ -27,16 +28,83 @@ export const Default: Story = {
27
28
  args: {
28
29
  options: OPTIONS,
29
30
  valueBy: 'id',
31
+ placeholder: 'Select a person',
30
32
  },
31
33
 
32
34
  render: args => ({
33
35
  components: { Combobox },
34
36
  setup() {
35
- return { args };
37
+ const selectedValue = ref();
38
+
39
+ return { args, selectedValue };
36
40
  },
37
41
  template: `
38
- <Combobox v-bind="args">
39
- </Combobox>
42
+ <div>
43
+ <Combobox v-bind="args" v-model="selectedValue" />
44
+ <div style="margin-top: 16px; padding: 12px; background: #f5f5f5; border-radius: 8px; font-family: monospace;">
45
+ <strong>Selected:</strong> {{ selectedValue ? selectedValue.label : 'None' }}
46
+ <br>
47
+ <strong>Value:</strong> {{ selectedValue ? JSON.stringify(selectedValue.value) : 'None' }}
48
+ </div>
49
+ </div>
50
+ `,
51
+ }),
52
+ };
53
+
54
+ export const Multiple: Story = {
55
+ args: {
56
+ options: OPTIONS,
57
+ valueBy: 'id',
58
+ placeholder: 'Select multiple people',
59
+ multiple: true,
60
+ },
61
+
62
+ render: args => ({
63
+ components: { Combobox },
64
+ setup() {
65
+ const selectedValues = ref([]);
66
+
67
+ return { args, selectedValues };
68
+ },
69
+ template: `
70
+ <div>
71
+ <Combobox v-bind="args" v-model="selectedValues" />
72
+ <div style="margin-top: 16px; padding: 12px; background: #f5f5f5; border-radius: 8px; font-family: monospace;">
73
+ <strong>Selected ({{ selectedValues.length }}):</strong>
74
+ <ul v-if="selectedValues.length > 0" style="margin: 4px 0; padding-left: 20px;">
75
+ <li v-for="item in selectedValues" :key="item.value.id">
76
+ {{ item.label }} (ID: {{ item.value.id }})
77
+ </li>
78
+ </ul>
79
+ <span v-else>None</span>
80
+ </div>
81
+ </div>
82
+ `,
83
+ }),
84
+ };
85
+
86
+ export const Searchable: Story = {
87
+ args: {
88
+ options: OPTIONS,
89
+ valueBy: 'id',
90
+ placeholder: 'Search and select',
91
+ searchable: true,
92
+ },
93
+
94
+ render: args => ({
95
+ components: { Combobox },
96
+ setup() {
97
+ const selectedValue = ref();
98
+
99
+ return { args, selectedValue };
100
+ },
101
+ template: `
102
+ <div>
103
+ <Combobox v-bind="args" v-model="selectedValue" />
104
+ <div style="margin-top: 16px; padding: 12px; background: #f5f5f5; border-radius: 8px; font-family: monospace;">
105
+ <strong>Selected:</strong> {{ selectedValue ? selectedValue.label : 'None' }}
106
+ </div>
107
+ </div>
40
108
  `,
41
109
  }),
42
110
  };
@@ -46,16 +114,23 @@ export const Inline: Story = {
46
114
  options: OPTIONS,
47
115
  valueBy: 'id',
48
116
  type: 'inline',
117
+ placeholder: 'Inline style',
49
118
  },
50
119
 
51
120
  render: args => ({
52
121
  components: { Combobox },
53
122
  setup() {
54
- return { args };
123
+ const selectedValue = ref();
124
+
125
+ return { args, selectedValue };
55
126
  },
56
127
  template: `
57
- <Combobox v-bind="args">
58
- </Combobox>
128
+ <div>
129
+ <Combobox v-bind="args" v-model="selectedValue" />
130
+ <div style="margin-top: 16px; padding: 12px; background: #f5f5f5; border-radius: 8px; font-family: monospace;">
131
+ <strong>Selected:</strong> {{ selectedValue ? selectedValue.label : 'None' }}
132
+ </div>
133
+ </div>
59
134
  `,
60
135
  }),
61
136
  };
@@ -65,16 +140,23 @@ export const Compact: Story = {
65
140
  options: OPTIONS,
66
141
  valueBy: 'id',
67
142
  type: 'compact',
143
+ placeholder: 'Compact style',
68
144
  },
69
145
 
70
146
  render: args => ({
71
147
  components: { Combobox },
72
148
  setup() {
73
- return { args };
149
+ const selectedValue = ref();
150
+
151
+ return { args, selectedValue };
74
152
  },
75
153
  template: `
76
- <Combobox v-bind="args">
77
- </Combobox>
154
+ <div>
155
+ <Combobox v-bind="args" v-model="selectedValue" />
156
+ <div style="margin-top: 16px; padding: 12px; background: #f5f5f5; border-radius: 8px; font-family: monospace;">
157
+ <strong>Selected:</strong> {{ selectedValue ? selectedValue.label : 'None' }}
158
+ </div>
159
+ </div>
78
160
  `,
79
161
  }),
80
162
  };
@@ -84,16 +166,77 @@ export const CompactInput: Story = {
84
166
  options: OPTIONS,
85
167
  valueBy: 'id',
86
168
  type: 'compact-input',
169
+ placeholder: 'Compact input style',
87
170
  },
88
171
 
89
172
  render: args => ({
90
173
  components: { Combobox },
91
174
  setup() {
92
- return { args };
175
+ const selectedValue = ref();
176
+
177
+ return { args, selectedValue };
178
+ },
179
+ template: `
180
+ <div>
181
+ <Combobox v-bind="args" v-model="selectedValue" />
182
+ <div style="margin-top: 16px; padding: 12px; background: #f5f5f5; border-radius: 8px; font-family: monospace;">
183
+ <strong>Selected:</strong> {{ selectedValue ? selectedValue.label : 'None' }}
184
+ </div>
185
+ </div>
186
+ `,
187
+ }),
188
+ };
189
+
190
+ export const WithBadge: Story = {
191
+ args: {
192
+ options: OPTIONS,
193
+ valueBy: 'id',
194
+ placeholder: 'Select with badge',
195
+ badgeProps: {
196
+ label: 'New',
197
+ variant: 'fill',
198
+ },
199
+ },
200
+
201
+ render: args => ({
202
+ components: { Combobox },
203
+ setup() {
204
+ const selectedValue = ref();
205
+
206
+ return { args, selectedValue };
207
+ },
208
+ template: `
209
+ <div>
210
+ <Combobox v-bind="args" v-model="selectedValue" />
211
+ <div style="margin-top: 16px; padding: 12px; background: #f5f5f5; border-radius: 8px; font-family: monospace;">
212
+ <strong>Selected:</strong> {{ selectedValue ? selectedValue.label : 'None' }}
213
+ </div>
214
+ </div>
215
+ `,
216
+ }),
217
+ };
218
+
219
+ export const Preselected: Story = {
220
+ args: {
221
+ options: OPTIONS,
222
+ valueBy: 'id',
223
+ placeholder: 'Preselected option',
224
+ },
225
+
226
+ render: args => ({
227
+ components: { Combobox },
228
+ setup() {
229
+ const selectedValue = ref(OPTIONS[2]);
230
+
231
+ return { args, selectedValue };
93
232
  },
94
233
  template: `
95
- <Combobox v-bind="args">
96
- </Combobox>
234
+ <div>
235
+ <Combobox v-bind="args" v-model="selectedValue" />
236
+ <div style="margin-top: 16px; padding: 12px; background: #f5f5f5; border-radius: 8px; font-family: monospace;">
237
+ <strong>Selected:</strong> {{ selectedValue ? selectedValue.label : 'None' }}
238
+ </div>
239
+ </div>
97
240
  `,
98
241
  }),
99
242
  };