@youcan/celeste 0.6.16 → 0.6.18

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-e6216767] {
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-e6216767] {
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-e6216767] {
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-e6216767],
2085
+ .selected-dropdown-image[data-v-e6216767] {
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-e6216767] {
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-e6216767] {
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-e6216767] {
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-e6216767] {
2127
2127
  position: absolute;
2128
2128
  width: 1px;
2129
2129
  height: 1px;
@@ -12,26 +12,29 @@ 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"];
33
+ const __default__ = {
34
+ inheritAttrs: false
35
+ };
34
36
  const _sfc_main = /* @__PURE__ */ Mo.defineComponent({
37
+ ...__default__,
35
38
  __name: "combobox",
36
39
  props: {
37
40
  options: {},
@@ -63,17 +66,29 @@ const _sfc_main = /* @__PURE__ */ Mo.defineComponent({
63
66
  const props = __props;
64
67
  const emits = __emit;
65
68
  const delegatedProps = Mo.computed(() => {
66
- const { open, modelValue, filterFunction: filterFunction2, ...delegated } = props;
69
+ const {
70
+ open,
71
+ filterFunction: filterFunction2,
72
+ options,
73
+ valueBy,
74
+ placeholder,
75
+ type,
76
+ size,
77
+ emptyLabel,
78
+ badgeProps,
79
+ searchable,
80
+ ...delegated
81
+ } = props;
67
82
  return delegated;
68
83
  });
69
84
  const forwarded = index.xe(delegatedProps, emits);
70
- const selected = Mo.ref(props.multiple ? [] : void 0);
85
+ const model = Mo.computed(() => props.modelValue);
71
86
  function isSelected(value) {
72
- if (!Array.isArray(selected.value) || !props.multiple)
87
+ if (!Array.isArray(props.modelValue) || !props.multiple)
73
88
  return;
74
89
  if (value === void 0 || value === null)
75
90
  return false;
76
- return selected.value.some((selectedItem) => {
91
+ return props.modelValue.some((selectedItem) => {
77
92
  const { value: selectedValue } = selectedItem;
78
93
  if (props.valueBy && Object.prototype.hasOwnProperty.call(value, props.valueBy) && Object.prototype.hasOwnProperty.call(selectedValue, props.valueBy)) {
79
94
  return value[props.valueBy] === selectedValue[props.valueBy];
@@ -97,112 +112,106 @@ const _sfc_main = /* @__PURE__ */ Mo.defineComponent({
97
112
  disabled: props.disabled
98
113
  }));
99
114
  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)
115
+ return Mo.openBlock(), Mo.createBlock(comboboxRoot_vue_vue_type_script_setup_true_lang._sfc_main, Mo.mergeProps(Mo.unref(forwarded), { "filter-function": filterFunction }), {
116
+ default: Mo.withCtx(() => [
117
+ Mo.createVNode(comboboxAnchor_vue_vue_type_script_setup_true_lang._sfc_main, { "as-child": "" }, {
118
+ default: Mo.withCtx(() => [
119
+ Mo.createVNode(comboboxTrigger, {
120
+ type: _ctx.type,
121
+ filled: !!model.value,
122
+ size: _ctx.size
123
+ }, {
124
+ default: Mo.withCtx(() => [
125
+ Mo.createElementVNode("div", _hoisted_1, [
126
+ model.value && !Array.isArray(model.value) ? (Mo.openBlock(), Mo.createElementBlock("div", _hoisted_2, [
127
+ model.value.icon ? (Mo.openBlock(), Mo.createElementBlock("i", {
128
+ key: 0,
129
+ class: Mo.normalizeClass(model.value.icon)
130
+ }, null, 2)) : Mo.createCommentVNode("", true),
131
+ model.value.image ? (Mo.openBlock(), Mo.createElementBlock("div", _hoisted_3, [
132
+ Mo.renderSlot(_ctx.$slots, "image", Mo.normalizeProps(Mo.guardReactiveProps({ selected: model.value })), () => [
133
+ Mo.createElementVNode("img", {
134
+ src: model.value.image,
135
+ alt: "Selected option",
136
+ class: "selected-dropdown-image"
137
+ }, null, 8, _hoisted_4)
138
+ ], true)
139
139
  ])) : 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))
140
+ ])) : Mo.renderSlot(_ctx.$slots, "prefix", {
141
+ key: 1,
142
+ class: "celeste-dropdown-anchor-trigger-prefix-default"
143
+ }, void 0, true)
144
144
  ]),
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))
145
+ _ctx.type !== "inline" ? (Mo.openBlock(), Mo.createElementBlock("div", _hoisted_5, [
146
+ _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)),
147
+ mergedBadgeProps.value && _ctx.badgeProps ? (Mo.openBlock(), Mo.createElementBlock("span", _hoisted_8, [
148
+ Mo.createVNode(badge, Mo.normalizeProps(Mo.guardReactiveProps(mergedBadgeProps.value)), null, 16)
149
+ ])) : Mo.createCommentVNode("", true)
150
+ ])) : Mo.createCommentVNode("", true),
151
+ _cache[0] || (_cache[0] = Mo.createElementVNode("div", { class: "celeste-dropdown-trigger" }, [
152
+ Mo.createElementVNode("i", { class: "i-celeste-arrow-down-s-line" })
153
+ ], -1))
154
+ ]),
155
+ _: 3
156
+ }, 8, ["type", "filled", "size"])
157
+ ]),
158
+ _: 3
159
+ }),
160
+ Mo.createVNode(comboboxList, null, {
161
+ default: Mo.withCtx(() => [
162
+ Mo.createElementVNode("div", {
163
+ class: Mo.normalizeClass(["celeste-dropdown-inner-input", { "sr-only": !_ctx.searchable }])
164
+ }, [
165
+ Mo.createVNode(comboboxInput, { searchable: _ctx.searchable }, null, 8, ["searchable"]),
166
+ _ctx.searchable ? (Mo.openBlock(), Mo.createBlock(comboboxSeparator, { key: 0 })) : Mo.createCommentVNode("", true)
167
+ ], 2),
168
+ Mo.createVNode(comboboxEmpty, null, Mo.createSlots({ _: 2 }, [
169
+ _ctx.emptyLabel ? {
170
+ name: "default",
171
+ fn: Mo.withCtx(() => [
172
+ Mo.createTextVNode(Mo.toDisplayString(_ctx.emptyLabel), 1)
194
173
  ]),
195
- _: 1
196
- })
197
- ]),
198
- _: 1
199
- })
200
- ]),
201
- _: 3
202
- }, 16, ["model-value"])
203
- ]);
174
+ key: "0"
175
+ } : void 0
176
+ ]), 1024),
177
+ Mo.createVNode(comboboxGroup, null, {
178
+ default: Mo.withCtx(() => [
179
+ (Mo.openBlock(true), Mo.createElementBlock(Mo.Fragment, null, Mo.renderList(props.options, (option) => {
180
+ return Mo.openBlock(), Mo.createBlock(comboboxItem, {
181
+ key: option.label,
182
+ label: option.label,
183
+ sublabel: option.sublabel,
184
+ description: option.description,
185
+ checkbox: props.multiple,
186
+ value: option,
187
+ selected: isSelected(option.value)
188
+ }, {
189
+ prefix: Mo.withCtx(() => [
190
+ option.icon ? (Mo.openBlock(), Mo.createElementBlock("i", {
191
+ key: 0,
192
+ class: Mo.normalizeClass(option.icon)
193
+ }, null, 2)) : Mo.createCommentVNode("", true),
194
+ option.image ? (Mo.openBlock(), Mo.createElementBlock("img", {
195
+ key: 1,
196
+ src: option.image,
197
+ alt: "option",
198
+ class: "celeste-dropdown-item-image"
199
+ }, null, 8, _hoisted_9)) : Mo.createCommentVNode("", true)
200
+ ]),
201
+ _: 2
202
+ }, 1032, ["label", "sublabel", "description", "checkbox", "value", "selected"]);
203
+ }), 128))
204
+ ]),
205
+ _: 1
206
+ })
207
+ ]),
208
+ _: 1
209
+ })
210
+ ]),
211
+ _: 3
212
+ }, 16);
204
213
  };
205
214
  }
206
215
  });
207
- const combobox = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main, [["__scopeId", "data-v-424c9dad"]]);
216
+ const combobox = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main, [["__scopeId", "data-v-e6216767"]]);
208
217
  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,26 +11,29 @@ 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"];
32
+ const __default__ = {
33
+ inheritAttrs: false
34
+ };
33
35
  const _sfc_main = /* @__PURE__ */ defineComponent({
36
+ ...__default__,
34
37
  __name: "combobox",
35
38
  props: {
36
39
  options: {},
@@ -62,17 +65,29 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
62
65
  const props = __props;
63
66
  const emits = __emit;
64
67
  const delegatedProps = computed(() => {
65
- const { open, modelValue, filterFunction: filterFunction2, ...delegated } = props;
68
+ const {
69
+ open,
70
+ filterFunction: filterFunction2,
71
+ options,
72
+ valueBy,
73
+ placeholder,
74
+ type,
75
+ size,
76
+ emptyLabel,
77
+ badgeProps,
78
+ searchable,
79
+ ...delegated
80
+ } = props;
66
81
  return delegated;
67
82
  });
68
83
  const forwarded = xe(delegatedProps, emits);
69
- const selected = ref(props.multiple ? [] : void 0);
84
+ const model = computed(() => props.modelValue);
70
85
  function isSelected(value) {
71
- if (!Array.isArray(selected.value) || !props.multiple)
86
+ if (!Array.isArray(props.modelValue) || !props.multiple)
72
87
  return;
73
88
  if (value === void 0 || value === null)
74
89
  return false;
75
- return selected.value.some((selectedItem) => {
90
+ return props.modelValue.some((selectedItem) => {
76
91
  const { value: selectedValue } = selectedItem;
77
92
  if (props.valueBy && Object.prototype.hasOwnProperty.call(value, props.valueBy) && Object.prototype.hasOwnProperty.call(selectedValue, props.valueBy)) {
78
93
  return value[props.valueBy] === selectedValue[props.valueBy];
@@ -96,114 +111,108 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
96
111
  disabled: props.disabled
97
112
  }));
98
113
  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)
114
+ return openBlock(), createBlock(_sfc_main$1, mergeProps(unref(forwarded), { "filter-function": filterFunction }), {
115
+ default: withCtx(() => [
116
+ createVNode(_sfc_main$2, { "as-child": "" }, {
117
+ default: withCtx(() => [
118
+ createVNode(ComboboxTrigger, {
119
+ type: _ctx.type,
120
+ filled: !!model.value,
121
+ size: _ctx.size
122
+ }, {
123
+ default: withCtx(() => [
124
+ createElementVNode("div", _hoisted_1, [
125
+ model.value && !Array.isArray(model.value) ? (openBlock(), createElementBlock("div", _hoisted_2, [
126
+ model.value.icon ? (openBlock(), createElementBlock("i", {
127
+ key: 0,
128
+ class: normalizeClass(model.value.icon)
129
+ }, null, 2)) : createCommentVNode("", true),
130
+ model.value.image ? (openBlock(), createElementBlock("div", _hoisted_3, [
131
+ renderSlot(_ctx.$slots, "image", normalizeProps(guardReactiveProps({ selected: model.value })), () => [
132
+ createElementVNode("img", {
133
+ src: model.value.image,
134
+ alt: "Selected option",
135
+ class: "selected-dropdown-image"
136
+ }, null, 8, _hoisted_4)
137
+ ], true)
138
138
  ])) : 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))
139
+ ])) : renderSlot(_ctx.$slots, "prefix", {
140
+ key: 1,
141
+ class: "celeste-dropdown-anchor-trigger-prefix-default"
142
+ }, void 0, true)
143
143
  ]),
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))
144
+ _ctx.type !== "inline" ? (openBlock(), createElementBlock("div", _hoisted_5, [
145
+ _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)),
146
+ mergedBadgeProps.value && _ctx.badgeProps ? (openBlock(), createElementBlock("span", _hoisted_8, [
147
+ createVNode(Badge, normalizeProps(guardReactiveProps(mergedBadgeProps.value)), null, 16)
148
+ ])) : createCommentVNode("", true)
149
+ ])) : createCommentVNode("", true),
150
+ _cache[0] || (_cache[0] = createElementVNode("div", { class: "celeste-dropdown-trigger" }, [
151
+ createElementVNode("i", { class: "i-celeste-arrow-down-s-line" })
152
+ ], -1))
153
+ ]),
154
+ _: 3
155
+ }, 8, ["type", "filled", "size"])
156
+ ]),
157
+ _: 3
158
+ }),
159
+ createVNode(ComboboxList, null, {
160
+ default: withCtx(() => [
161
+ createElementVNode("div", {
162
+ class: normalizeClass(["celeste-dropdown-inner-input", { "sr-only": !_ctx.searchable }])
163
+ }, [
164
+ createVNode(ComboboxInput, { searchable: _ctx.searchable }, null, 8, ["searchable"]),
165
+ _ctx.searchable ? (openBlock(), createBlock(ComboboxSeparator, { key: 0 })) : createCommentVNode("", true)
166
+ ], 2),
167
+ createVNode(ComboboxEmpty, null, createSlots({ _: 2 }, [
168
+ _ctx.emptyLabel ? {
169
+ name: "default",
170
+ fn: withCtx(() => [
171
+ createTextVNode(toDisplayString(_ctx.emptyLabel), 1)
193
172
  ]),
194
- _: 1
195
- })
196
- ]),
197
- _: 1
198
- })
199
- ]),
200
- _: 3
201
- }, 16, ["model-value"])
202
- ]);
173
+ key: "0"
174
+ } : void 0
175
+ ]), 1024),
176
+ createVNode(ComboboxGroup, null, {
177
+ default: withCtx(() => [
178
+ (openBlock(true), createElementBlock(Fragment, null, renderList(props.options, (option) => {
179
+ return openBlock(), createBlock(ComboboxItem, {
180
+ key: option.label,
181
+ label: option.label,
182
+ sublabel: option.sublabel,
183
+ description: option.description,
184
+ checkbox: props.multiple,
185
+ value: option,
186
+ selected: isSelected(option.value)
187
+ }, {
188
+ prefix: withCtx(() => [
189
+ option.icon ? (openBlock(), createElementBlock("i", {
190
+ key: 0,
191
+ class: normalizeClass(option.icon)
192
+ }, null, 2)) : createCommentVNode("", true),
193
+ option.image ? (openBlock(), createElementBlock("img", {
194
+ key: 1,
195
+ src: option.image,
196
+ alt: "option",
197
+ class: "celeste-dropdown-item-image"
198
+ }, null, 8, _hoisted_9)) : createCommentVNode("", true)
199
+ ]),
200
+ _: 2
201
+ }, 1032, ["label", "sublabel", "description", "checkbox", "value", "selected"]);
202
+ }), 128))
203
+ ]),
204
+ _: 1
205
+ })
206
+ ]),
207
+ _: 1
208
+ })
209
+ ]),
210
+ _: 3
211
+ }, 16);
203
212
  };
204
213
  }
205
214
  });
206
- const combobox = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-424c9dad"]]);
215
+ const combobox = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-e6216767"]]);
207
216
  export {
208
217
  combobox as default
209
218
  };
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.18",
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.18",
36
+ "@youcan/celeste-tokens": "0.6.18"
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,35 @@ 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 {
27
+ open,
28
+ filterFunction,
29
+ options,
30
+ valueBy,
31
+ placeholder,
32
+ type,
33
+ size,
34
+ emptyLabel,
35
+ badgeProps,
36
+ searchable,
37
+ ...delegated
38
+ } = props;
27
39
 
28
40
  return delegated;
29
41
  });
30
42
 
31
43
  const forwarded = useForwardPropsEmits(delegatedProps, emits);
32
- const selected = ref<ComboboxItemPropsType[] | ComboboxItemPropsType | undefined>(props.multiple ? [] : undefined);
44
+
45
+ const model = computed(() => props.modelValue as ComboboxItemPropsType[] | ComboboxItemPropsType | undefined);
33
46
 
34
47
  function isSelected(value: ComboboxItemPropsType['value']): boolean | undefined {
35
- if (!Array.isArray(selected.value) || !props.multiple)
48
+ if (!Array.isArray(props.modelValue) || !props.multiple)
36
49
  return;
37
50
 
38
51
  if (value === undefined || value === null)
39
52
  return false;
40
53
 
41
- return selected.value.some((selectedItem: ComboboxItemPropsType) => {
54
+ return props.modelValue.some((selectedItem: ComboboxItemPropsType) => {
42
55
  const { value: selectedValue } = selectedItem;
43
56
 
44
57
  if (
@@ -89,96 +102,97 @@ export interface ComboboxPropsType extends ComboboxRootProps {
89
102
  badgeProps?: BadgeProps;
90
103
  searchable?: boolean;
91
104
  }
105
+
106
+ export default {
107
+ inheritAttrs: false,
108
+ };
92
109
  </script>
93
110
 
94
111
  <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>
112
+ <ComboboxRoot
113
+ v-bind="forwarded"
114
+ :filter-function="filterFunction"
115
+ >
116
+ <ComboboxAnchor as-child>
117
+ <ComboboxTrigger
118
+ :type="type"
119
+ :filled="!!model"
120
+ :size="size"
121
+ >
122
+ <div class="celeste-dropdown-anchor-trigger-prefix">
123
+ <div v-if="model && !Array.isArray(model)" class="celeste-dropdown-anchor-trigger-prefix-selected">
124
+ <i v-if="model.icon" :class="model.icon" />
125
+ <div v-if="model.image">
126
+ <slot name="image" v-bind="{ selected: model }">
127
+ <img
128
+ :src="model.image"
129
+ alt="Selected option"
130
+ class="selected-dropdown-image"
131
+ >
132
+ </slot>
119
133
  </div>
120
- <slot
121
- v-else
122
- name="prefix"
123
- class="celeste-dropdown-anchor-trigger-prefix-default"
124
- />
125
134
  </div>
135
+ <slot
136
+ v-else
137
+ name="prefix"
138
+ class="celeste-dropdown-anchor-trigger-prefix-default"
139
+ />
140
+ </div>
126
141
 
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
- </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" />
142
+ <div
143
+ v-if="type !== 'inline'"
144
+ class="celeste-dropdown-input"
145
+ >
146
+ <span v-if="multiple">{{ placeholder }}</span>
147
+ <span v-else>
148
+ {{ model && !Array.isArray(model) ? model.label : props.placeholder }}
149
+ </span>
150
+ <span v-if="mergedBadgeProps && badgeProps" class="celeste-input-badge">
151
+ <Badge v-bind="mergedBadgeProps" />
152
+ </span>
153
+ </div>
154
+ <div class="celeste-dropdown-trigger">
155
+ <i class="i-celeste-arrow-down-s-line" />
149
156
  </div>
157
+ </ComboboxTrigger>
158
+ </ComboboxAnchor>
150
159
 
151
- <ComboboxEmpty>
152
- <template v-if="emptyLabel" #default>
153
- {{ emptyLabel }}
154
- </template>
155
- </ComboboxEmpty>
160
+ <ComboboxList>
161
+ <div class="celeste-dropdown-inner-input" :class="{ 'sr-only': !searchable }">
162
+ <ComboboxInput :searchable="searchable" />
163
+ <ComboboxSeparator v-if="searchable" />
164
+ </div>
156
165
 
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>
166
+ <ComboboxEmpty>
167
+ <template v-if="emptyLabel" #default>
168
+ {{ emptyLabel }}
169
+ </template>
170
+ </ComboboxEmpty>
171
+
172
+ <ComboboxGroup>
173
+ <ComboboxItem
174
+ v-for="option in props.options"
175
+ :key="option.label"
176
+ :label="option.label"
177
+ :sublabel="option.sublabel"
178
+ :description="option.description"
179
+ :checkbox="props.multiple"
180
+ :value="option"
181
+ :selected="isSelected(option.value)"
182
+ >
183
+ <template #prefix>
184
+ <i v-if="option.icon" :class="option.icon" />
185
+ <img
186
+ v-if="option.image"
187
+ :src="option.image"
188
+ alt="option"
189
+ class="celeste-dropdown-item-image"
190
+ >
191
+ </template>
192
+ </ComboboxItem>
193
+ </ComboboxGroup>
194
+ </ComboboxList>
195
+ </ComboboxRoot>
182
196
  </template>
183
197
 
184
198
  <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
  };