cisse-vue-ui 0.1.0 → 0.1.2

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 (85) hide show
  1. package/README.md +435 -6
  2. package/dist/Checkbox.vue_vue_type_script_setup_true_lang-DQD2I1Wk.cjs +621 -0
  3. package/dist/Checkbox.vue_vue_type_script_setup_true_lang-DQD2I1Wk.cjs.map +1 -0
  4. package/dist/Checkbox.vue_vue_type_script_setup_true_lang-DVkcMcSN.js +622 -0
  5. package/dist/Checkbox.vue_vue_type_script_setup_true_lang-DVkcMcSN.js.map +1 -0
  6. package/dist/CollapsibleCard.vue_vue_type_script_setup_true_lang-D2MeLTRV.cjs +1133 -0
  7. package/dist/CollapsibleCard.vue_vue_type_script_setup_true_lang-D2MeLTRV.cjs.map +1 -0
  8. package/dist/CollapsibleCard.vue_vue_type_script_setup_true_lang-Ixih38V0.js +1134 -0
  9. package/dist/CollapsibleCard.vue_vue_type_script_setup_true_lang-Ixih38V0.js.map +1 -0
  10. package/dist/{NotificationList.vue_vue_type_script_setup_true_lang-B2hjbMm4.js → EmptyState.vue_vue_type_script_setup_true_lang-CrVvFwXA.js} +163 -44
  11. package/dist/EmptyState.vue_vue_type_script_setup_true_lang-CrVvFwXA.js.map +1 -0
  12. package/dist/{NotificationList.vue_vue_type_script_setup_true_lang-Ci3zIvrv.cjs → EmptyState.vue_vue_type_script_setup_true_lang-mlqLBP5W.cjs} +163 -44
  13. package/dist/EmptyState.vue_vue_type_script_setup_true_lang-mlqLBP5W.cjs.map +1 -0
  14. package/dist/MenuItem.vue_vue_type_script_setup_true_lang-BWz86k7c.cjs +86 -0
  15. package/dist/MenuItem.vue_vue_type_script_setup_true_lang-BWz86k7c.cjs.map +1 -0
  16. package/dist/MenuItem.vue_vue_type_script_setup_true_lang-emN2qlfR.js +87 -0
  17. package/dist/MenuItem.vue_vue_type_script_setup_true_lang-emN2qlfR.js.map +1 -0
  18. package/dist/PageLayout.vue_vue_type_script_setup_true_lang-DTlUENg3.js +265 -0
  19. package/dist/PageLayout.vue_vue_type_script_setup_true_lang-DTlUENg3.js.map +1 -0
  20. package/dist/PageLayout.vue_vue_type_script_setup_true_lang-IcouTz4C.cjs +264 -0
  21. package/dist/PageLayout.vue_vue_type_script_setup_true_lang-IcouTz4C.cjs.map +1 -0
  22. package/dist/components/core/AutocompleteComponent.vue.d.ts +7 -1
  23. package/dist/components/core/Avatar.vue.d.ts +20 -0
  24. package/dist/components/core/Button.vue.d.ts +49 -0
  25. package/dist/components/core/CollapsibleCard.vue.d.ts +28 -0
  26. package/dist/components/core/Dropdown.vue.d.ts +52 -0
  27. package/dist/components/core/MenuItem.vue.d.ts +11 -1
  28. package/dist/components/core/Stepper.vue.d.ts +22 -0
  29. package/dist/components/core/TabPanel.vue.d.ts +21 -0
  30. package/dist/components/core/Tabs.vue.d.ts +39 -0
  31. package/dist/components/core/index.cjs +14 -6
  32. package/dist/components/core/index.cjs.map +1 -1
  33. package/dist/components/core/index.d.ts +12 -0
  34. package/dist/components/core/index.js +14 -6
  35. package/dist/components/core/index.js.map +1 -1
  36. package/dist/components/feedback/Alert.vue.d.ts +34 -0
  37. package/dist/components/feedback/EmptyState.vue.d.ts +29 -0
  38. package/dist/components/feedback/index.cjs +8 -6
  39. package/dist/components/feedback/index.cjs.map +1 -1
  40. package/dist/components/feedback/index.d.ts +3 -0
  41. package/dist/components/feedback/index.js +3 -1
  42. package/dist/components/form/Checkbox.vue.d.ts +20 -0
  43. package/dist/components/form/FormSelect.vue.d.ts +35 -6
  44. package/dist/components/form/Switch.vue.d.ts +21 -0
  45. package/dist/components/form/index.cjs +9 -7
  46. package/dist/components/form/index.cjs.map +1 -1
  47. package/dist/components/form/index.d.ts +2 -0
  48. package/dist/components/form/index.js +4 -2
  49. package/dist/components/index.cjs +34 -19
  50. package/dist/components/index.cjs.map +1 -1
  51. package/dist/components/index.d.ts +1 -0
  52. package/dist/components/index.js +26 -11
  53. package/dist/components/index.js.map +1 -1
  54. package/dist/components/layout/BaseLayout.vue.d.ts +58 -0
  55. package/dist/components/layout/PageLayout.vue.d.ts +37 -0
  56. package/dist/components/layout/index.cjs +6 -0
  57. package/dist/components/layout/index.cjs.map +1 -0
  58. package/dist/components/layout/index.d.ts +3 -0
  59. package/dist/components/layout/index.js +6 -0
  60. package/dist/components/layout/index.js.map +1 -0
  61. package/dist/index-Bt9enqyq.cjs +47 -0
  62. package/dist/index-Bt9enqyq.cjs.map +1 -0
  63. package/dist/index-CxPY8Qb7.js +48 -0
  64. package/dist/index-CxPY8Qb7.js.map +1 -0
  65. package/dist/index.cjs +35 -20
  66. package/dist/index.cjs.map +1 -1
  67. package/dist/index.js +29 -14
  68. package/dist/index.js.map +1 -1
  69. package/dist/style.css +2 -0
  70. package/dist/types/components.d.ts +7 -0
  71. package/package.json +12 -3
  72. package/dist/NotificationList.vue_vue_type_script_setup_true_lang-B2hjbMm4.js.map +0 -1
  73. package/dist/NotificationList.vue_vue_type_script_setup_true_lang-Ci3zIvrv.cjs.map +0 -1
  74. package/dist/SearchInput.vue_vue_type_script_setup_true_lang-Be73hShP.cjs +0 -234
  75. package/dist/SearchInput.vue_vue_type_script_setup_true_lang-Be73hShP.cjs.map +0 -1
  76. package/dist/SearchInput.vue_vue_type_script_setup_true_lang-DjT2qdcp.js +0 -235
  77. package/dist/SearchInput.vue_vue_type_script_setup_true_lang-DjT2qdcp.js.map +0 -1
  78. package/dist/TableAction.vue_vue_type_script_setup_true_lang-BHskhVhK.js +0 -540
  79. package/dist/TableAction.vue_vue_type_script_setup_true_lang-BHskhVhK.js.map +0 -1
  80. package/dist/TableAction.vue_vue_type_script_setup_true_lang-CojbKn7E.cjs +0 -539
  81. package/dist/TableAction.vue_vue_type_script_setup_true_lang-CojbKn7E.cjs.map +0 -1
  82. package/dist/index-BoCtJCg0.cjs +0 -32
  83. package/dist/index-BoCtJCg0.cjs.map +0 -1
  84. package/dist/index-CGhDI10m.js +0 -33
  85. package/dist/index-CGhDI10m.js.map +0 -1
@@ -0,0 +1,1133 @@
1
+ "use strict";
2
+ const vue = require("vue");
3
+ const BadgeType_vue_vue_type_script_setup_true_lang = require("./BadgeType.vue_vue_type_script_setup_true_lang-CJb63H1I.cjs");
4
+ const vue$1 = require("@iconify/vue");
5
+ const _hoisted_1$8 = { class: "flex flex-col overflow-hidden rounded-lg bg-white shadow-md dark:bg-slate-950" };
6
+ const _hoisted_2$6 = {
7
+ key: 0,
8
+ class: "flex items-center justify-between border-b border-gray-200 px-5 py-3 dark:border-gray-700"
9
+ };
10
+ const _hoisted_3$4 = { class: "flex flex-col gap-0.5" };
11
+ const _hoisted_4$2 = {
12
+ key: 0,
13
+ class: "text-md font-semibold text-gray-800 dark:text-gray-200"
14
+ };
15
+ const _hoisted_5$2 = {
16
+ key: 1,
17
+ class: "text-sm font-normal text-gray-600 dark:text-gray-400"
18
+ };
19
+ const _hoisted_6$1 = { class: "flex gap-2" };
20
+ const _sfc_main$a = /* @__PURE__ */ vue.defineComponent({
21
+ __name: "CardComponent",
22
+ props: {
23
+ title: {},
24
+ description: {}
25
+ },
26
+ setup(__props) {
27
+ return (_ctx, _cache) => {
28
+ return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$8, [
29
+ __props.title || __props.description || _ctx.$slots.title || _ctx.$slots.description || _ctx.$slots.actions ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2$6, [
30
+ vue.createElementVNode("div", _hoisted_3$4, [
31
+ __props.title || _ctx.$slots.title ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_4$2, [
32
+ vue.renderSlot(_ctx.$slots, "title", {}, () => [
33
+ vue.createTextVNode(vue.toDisplayString(__props.title), 1)
34
+ ])
35
+ ])) : vue.createCommentVNode("", true),
36
+ __props.description || _ctx.$slots.description ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_5$2, [
37
+ vue.renderSlot(_ctx.$slots, "description", {}, () => [
38
+ vue.createTextVNode(vue.toDisplayString(__props.description), 1)
39
+ ])
40
+ ])) : vue.createCommentVNode("", true)
41
+ ]),
42
+ vue.createElementVNode("div", _hoisted_6$1, [
43
+ vue.renderSlot(_ctx.$slots, "actions")
44
+ ])
45
+ ])) : vue.createCommentVNode("", true),
46
+ vue.renderSlot(_ctx.$slots, "default")
47
+ ]);
48
+ };
49
+ }
50
+ });
51
+ const _hoisted_1$7 = { class: "w-full divide-y divide-gray-300 text-left dark:divide-gray-700" };
52
+ const _hoisted_2$5 = { class: "bg-gray-100 text-sm font-semibold text-gray-600 uppercase dark:bg-gray-800 dark:text-gray-400" };
53
+ const _hoisted_3$3 = { class: "divide-y divide-gray-300 font-medium dark:divide-gray-700" };
54
+ const _hoisted_4$1 = { class: "flex items-center justify-end gap-2 px-3 py-4" };
55
+ const _hoisted_5$1 = { key: 0 };
56
+ const _sfc_main$9 = /* @__PURE__ */ vue.defineComponent({
57
+ __name: "TableComponent",
58
+ props: {
59
+ properties: {},
60
+ items: {}
61
+ },
62
+ setup(__props) {
63
+ const typeComponents = {
64
+ text: BadgeType_vue_vue_type_script_setup_true_lang._sfc_main$1,
65
+ number: BadgeType_vue_vue_type_script_setup_true_lang._sfc_main$2,
66
+ date: BadgeType_vue_vue_type_script_setup_true_lang._sfc_main$3,
67
+ boolean: BadgeType_vue_vue_type_script_setup_true_lang._sfc_main$4,
68
+ badge: BadgeType_vue_vue_type_script_setup_true_lang._sfc_main$5
69
+ };
70
+ const getTypeComponent = (type = "text") => {
71
+ return typeComponents[type] || BadgeType_vue_vue_type_script_setup_true_lang._sfc_main$1;
72
+ };
73
+ const visibleProperties = vue.computed(() => __props.properties.filter((p) => !p.hidden));
74
+ const getItemValue = (item, property) => {
75
+ if (property.name.includes(".")) {
76
+ let value = item;
77
+ for (const key of property.name.split(".")) {
78
+ if (value && typeof value === "object" && key in value) {
79
+ value = value[key];
80
+ } else {
81
+ return void 0;
82
+ }
83
+ }
84
+ return value;
85
+ }
86
+ return item[property.name];
87
+ };
88
+ const getAlignmentClass = (align) => {
89
+ switch (align) {
90
+ case "center":
91
+ return "text-center";
92
+ case "right":
93
+ return "text-right";
94
+ default:
95
+ return "text-left";
96
+ }
97
+ };
98
+ const getMainClass = (main) => {
99
+ if (main) {
100
+ return "text-sm font-semibold text-gray-900 dark:text-gray-100";
101
+ }
102
+ return "text-xs font-medium text-gray-600 dark:text-gray-400";
103
+ };
104
+ return (_ctx, _cache) => {
105
+ return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [
106
+ vue.createElementVNode("table", _hoisted_1$7, [
107
+ vue.createElementVNode("thead", _hoisted_2$5, [
108
+ vue.createElementVNode("tr", null, [
109
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(visibleProperties.value, (property) => {
110
+ return vue.openBlock(), vue.createElementBlock("th", {
111
+ key: property.name,
112
+ class: vue.normalizeClass([getAlignmentClass(property.align), "px-3 py-3"])
113
+ }, [
114
+ vue.renderSlot(_ctx.$slots, "header-" + property.name, { property }, () => [
115
+ vue.createTextVNode(vue.toDisplayString(property.label ?? property.name), 1)
116
+ ])
117
+ ], 2);
118
+ }), 128)),
119
+ _cache[0] || (_cache[0] = vue.createElementVNode("th", { class: "px-3 py-3 text-right" }, null, -1))
120
+ ])
121
+ ]),
122
+ vue.createElementVNode("tbody", _hoisted_3$3, [
123
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.items, (item) => {
124
+ return vue.openBlock(), vue.createElementBlock("tr", {
125
+ key: item.id,
126
+ class: "hover:bg-gray-50 dark:hover:bg-gray-800"
127
+ }, [
128
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(visibleProperties.value, (property) => {
129
+ return vue.openBlock(), vue.createElementBlock("td", {
130
+ key: property.name,
131
+ class: vue.normalizeClass([
132
+ getAlignmentClass(property.align),
133
+ getMainClass(property.main),
134
+ property.className,
135
+ "px-3 py-4"
136
+ ])
137
+ }, [
138
+ vue.renderSlot(_ctx.$slots, "item-" + property.name, {
139
+ item,
140
+ property,
141
+ value: getItemValue(item, property)
142
+ }, () => [
143
+ (vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(getTypeComponent(property.type || "text")), {
144
+ value: getItemValue(item, property)
145
+ }, null, 8, ["value"]))
146
+ ])
147
+ ], 2);
148
+ }), 128)),
149
+ vue.createElementVNode("td", _hoisted_4$1, [
150
+ vue.renderSlot(_ctx.$slots, "action", { item })
151
+ ])
152
+ ]);
153
+ }), 128))
154
+ ])
155
+ ]),
156
+ !__props.items || __props.items.length === 0 ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_5$1, [
157
+ vue.renderSlot(_ctx.$slots, "empty")
158
+ ])) : vue.createCommentVNode("", true)
159
+ ], 64);
160
+ };
161
+ }
162
+ });
163
+ const _hoisted_1$6 = {
164
+ key: 0,
165
+ class: "mb-2 block text-sm font-medium text-gray-700 dark:text-gray-300"
166
+ };
167
+ const _hoisted_2$4 = { class: "relative" };
168
+ const _hoisted_3$2 = ["disabled", "placeholder"];
169
+ const _hoisted_4 = ["disabled"];
170
+ const _hoisted_5 = {
171
+ key: 0,
172
+ class: "px-4 py-3 text-sm text-gray-500"
173
+ };
174
+ const _hoisted_6 = ["data-index", "onClick"];
175
+ const _hoisted_7 = { class: "flex-1 dark:text-white" };
176
+ const _hoisted_8 = { class: "text-xs text-gray-400" };
177
+ const _hoisted_9 = {
178
+ key: 1,
179
+ class: "mt-1 text-sm text-red-600"
180
+ };
181
+ const _sfc_main$8 = /* @__PURE__ */ vue.defineComponent({
182
+ __name: "AutocompleteComponent",
183
+ props: {
184
+ modelValue: {},
185
+ options: {},
186
+ placeholder: {},
187
+ disabled: { type: Boolean },
188
+ label: {},
189
+ error: {},
190
+ noResultsText: {},
191
+ teleport: { type: Boolean, default: true }
192
+ },
193
+ emits: ["update:modelValue"],
194
+ setup(__props, { emit: __emit }) {
195
+ const props = __props;
196
+ const emit = __emit;
197
+ const searchQuery = vue.ref("");
198
+ const isOpen = vue.ref(false);
199
+ const highlightedIndex = vue.ref(-1);
200
+ const inputRef = vue.ref(null);
201
+ const dropdownRef = vue.ref(null);
202
+ const containerRef = vue.ref(null);
203
+ const inputWrapperRef = vue.ref(null);
204
+ const dropdownPosition = vue.ref({ top: 0, left: 0, width: 0 });
205
+ const filteredOptions = vue.computed(() => {
206
+ if (!searchQuery.value) {
207
+ return props.options;
208
+ }
209
+ const query = searchQuery.value.toLowerCase();
210
+ return props.options.filter(
211
+ (option) => option.label.toLowerCase().includes(query) || option.value.toLowerCase().includes(query)
212
+ );
213
+ });
214
+ const selectedLabel = vue.computed(() => {
215
+ if (!props.modelValue) return "";
216
+ const option = props.options.find((opt) => opt.value === props.modelValue);
217
+ return (option == null ? void 0 : option.label) || "";
218
+ });
219
+ vue.watch(
220
+ () => props.modelValue,
221
+ () => {
222
+ if (!isOpen.value) {
223
+ searchQuery.value = selectedLabel.value;
224
+ }
225
+ },
226
+ { immediate: true }
227
+ );
228
+ const updatePosition = () => {
229
+ if (!inputWrapperRef.value || !props.teleport) return;
230
+ const rect = inputWrapperRef.value.getBoundingClientRect();
231
+ dropdownPosition.value = {
232
+ top: rect.bottom + window.scrollY + 8,
233
+ left: rect.left + window.scrollX,
234
+ width: rect.width
235
+ };
236
+ };
237
+ const openDropdown = () => {
238
+ if (props.disabled) return;
239
+ isOpen.value = true;
240
+ searchQuery.value = "";
241
+ highlightedIndex.value = -1;
242
+ vue.nextTick(() => {
243
+ var _a;
244
+ (_a = inputRef.value) == null ? void 0 : _a.focus();
245
+ updatePosition();
246
+ });
247
+ };
248
+ const closeDropdown = () => {
249
+ isOpen.value = false;
250
+ searchQuery.value = selectedLabel.value;
251
+ highlightedIndex.value = -1;
252
+ };
253
+ const selectOption = (option) => {
254
+ emit("update:modelValue", option.value);
255
+ searchQuery.value = option.label;
256
+ closeDropdown();
257
+ };
258
+ const clearSelection = () => {
259
+ emit("update:modelValue", null);
260
+ searchQuery.value = "";
261
+ highlightedIndex.value = -1;
262
+ vue.nextTick(() => {
263
+ var _a;
264
+ (_a = inputRef.value) == null ? void 0 : _a.focus();
265
+ });
266
+ };
267
+ const handleKeydown = (event) => {
268
+ if (!isOpen.value) return;
269
+ switch (event.key) {
270
+ case "ArrowDown":
271
+ event.preventDefault();
272
+ highlightedIndex.value = Math.min(
273
+ highlightedIndex.value + 1,
274
+ filteredOptions.value.length - 1
275
+ );
276
+ scrollToHighlighted();
277
+ break;
278
+ case "ArrowUp":
279
+ event.preventDefault();
280
+ highlightedIndex.value = Math.max(highlightedIndex.value - 1, 0);
281
+ scrollToHighlighted();
282
+ break;
283
+ case "Enter":
284
+ event.preventDefault();
285
+ if (highlightedIndex.value >= 0 && filteredOptions.value[highlightedIndex.value]) {
286
+ selectOption(filteredOptions.value[highlightedIndex.value]);
287
+ }
288
+ break;
289
+ case "Escape":
290
+ event.preventDefault();
291
+ closeDropdown();
292
+ break;
293
+ }
294
+ };
295
+ const scrollToHighlighted = () => {
296
+ vue.nextTick(() => {
297
+ if (dropdownRef.value) {
298
+ const highlightedElement = dropdownRef.value.querySelector(
299
+ `[data-index="${highlightedIndex.value}"]`
300
+ );
301
+ if (highlightedElement) {
302
+ highlightedElement.scrollIntoView({ block: "nearest" });
303
+ }
304
+ }
305
+ });
306
+ };
307
+ const handleClickOutside = (event) => {
308
+ var _a, _b;
309
+ const target = event.target;
310
+ const isInsideContainer = (_a = containerRef.value) == null ? void 0 : _a.contains(target);
311
+ const isInsideDropdown = (_b = dropdownRef.value) == null ? void 0 : _b.contains(target);
312
+ if (!isInsideContainer && !isInsideDropdown) {
313
+ closeDropdown();
314
+ }
315
+ };
316
+ vue.watch(isOpen, (newValue) => {
317
+ if (newValue) {
318
+ document.addEventListener("click", handleClickOutside);
319
+ window.addEventListener("scroll", updatePosition, true);
320
+ window.addEventListener("resize", updatePosition);
321
+ } else {
322
+ document.removeEventListener("click", handleClickOutside);
323
+ window.removeEventListener("scroll", updatePosition, true);
324
+ window.removeEventListener("resize", updatePosition);
325
+ }
326
+ });
327
+ vue.onUnmounted(() => {
328
+ document.removeEventListener("click", handleClickOutside);
329
+ window.removeEventListener("scroll", updatePosition, true);
330
+ window.removeEventListener("resize", updatePosition);
331
+ });
332
+ const dropdownStyle = vue.computed(() => {
333
+ if (!props.teleport) return {};
334
+ return {
335
+ position: "absolute",
336
+ top: `${dropdownPosition.value.top}px`,
337
+ left: `${dropdownPosition.value.left}px`,
338
+ width: `${dropdownPosition.value.width}px`
339
+ };
340
+ });
341
+ return (_ctx, _cache) => {
342
+ return vue.openBlock(), vue.createElementBlock("div", {
343
+ ref_key: "containerRef",
344
+ ref: containerRef,
345
+ class: "autocomplete-container"
346
+ }, [
347
+ __props.label ? (vue.openBlock(), vue.createElementBlock("label", _hoisted_1$6, vue.toDisplayString(__props.label), 1)) : vue.createCommentVNode("", true),
348
+ vue.createElementVNode("div", _hoisted_2$4, [
349
+ vue.createElementVNode("div", {
350
+ ref_key: "inputWrapperRef",
351
+ ref: inputWrapperRef,
352
+ class: vue.normalizeClass([{
353
+ "border-red-500": __props.error,
354
+ "border-gray-300 dark:border-gray-600": !__props.error && !isOpen.value,
355
+ "border-primary ring-2 ring-primary/20": isOpen.value,
356
+ "cursor-not-allowed opacity-50": __props.disabled
357
+ }, "flex items-center gap-2 rounded-lg border bg-white px-3 py-2 transition dark:bg-gray-800"])
358
+ }, [
359
+ vue.createVNode(vue.unref(vue$1.Icon), {
360
+ class: "size-5 text-gray-400",
361
+ icon: "lucide:search"
362
+ }),
363
+ vue.withDirectives(vue.createElementVNode("input", {
364
+ ref_key: "inputRef",
365
+ ref: inputRef,
366
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => searchQuery.value = $event),
367
+ disabled: __props.disabled,
368
+ placeholder: __props.placeholder || "Search...",
369
+ class: "flex-1 bg-transparent text-sm outline-none dark:text-white",
370
+ type: "text",
371
+ onFocus: openDropdown,
372
+ onKeydown: handleKeydown
373
+ }, null, 40, _hoisted_3$2), [
374
+ [vue.vModelText, searchQuery.value]
375
+ ]),
376
+ __props.modelValue && !__props.disabled ? (vue.openBlock(), vue.createElementBlock("button", {
377
+ key: 0,
378
+ class: "rounded p-1 transition hover:bg-gray-100 dark:hover:bg-gray-700",
379
+ type: "button",
380
+ onClick: vue.withModifiers(clearSelection, ["stop"])
381
+ }, [
382
+ vue.createVNode(vue.unref(vue$1.Icon), {
383
+ class: "size-4 text-gray-400",
384
+ icon: "lucide:x"
385
+ })
386
+ ])) : vue.createCommentVNode("", true),
387
+ vue.createElementVNode("button", {
388
+ disabled: __props.disabled,
389
+ class: "rounded p-1 transition hover:bg-gray-100 dark:hover:bg-gray-700",
390
+ type: "button",
391
+ onClick: _cache[1] || (_cache[1] = vue.withModifiers(($event) => isOpen.value ? closeDropdown() : openDropdown(), ["stop"]))
392
+ }, [
393
+ vue.createVNode(vue.unref(vue$1.Icon), {
394
+ class: vue.normalizeClass([{ "rotate-180": isOpen.value }, "size-4 text-gray-400 transition"]),
395
+ icon: "lucide:chevron-down"
396
+ }, null, 8, ["class"])
397
+ ], 8, _hoisted_4)
398
+ ], 2),
399
+ (vue.openBlock(), vue.createBlock(vue.Teleport, {
400
+ to: "body",
401
+ disabled: !__props.teleport
402
+ }, [
403
+ vue.createVNode(vue.Transition, {
404
+ "enter-active-class": "transition duration-100 ease-out",
405
+ "enter-from-class": "opacity-0 scale-95",
406
+ "enter-to-class": "opacity-100 scale-100",
407
+ "leave-active-class": "transition duration-75 ease-in",
408
+ "leave-from-class": "opacity-100 scale-100",
409
+ "leave-to-class": "opacity-0 scale-95"
410
+ }, {
411
+ default: vue.withCtx(() => [
412
+ isOpen.value ? (vue.openBlock(), vue.createElementBlock("div", {
413
+ key: 0,
414
+ ref_key: "dropdownRef",
415
+ ref: dropdownRef,
416
+ style: vue.normalizeStyle(dropdownStyle.value),
417
+ class: vue.normalizeClass([
418
+ "autocomplete-dropdown z-[9999] max-h-60 overflow-auto rounded-lg border border-gray-200 bg-white shadow-lg dark:border-gray-700 dark:bg-gray-800",
419
+ !__props.teleport && "absolute mt-2 w-full"
420
+ ])
421
+ }, [
422
+ filteredOptions.value.length === 0 ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_5, vue.toDisplayString(__props.noResultsText || "No results found"), 1)) : vue.createCommentVNode("", true),
423
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(filteredOptions.value, (option, index) => {
424
+ return vue.openBlock(), vue.createElementBlock("button", {
425
+ key: option.value,
426
+ class: vue.normalizeClass([{
427
+ "bg-gray-100 dark:bg-gray-700": highlightedIndex.value === index,
428
+ "bg-primary/10": __props.modelValue === option.value
429
+ }, "flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition hover:bg-gray-100 dark:hover:bg-gray-700"]),
430
+ "data-index": index,
431
+ type: "button",
432
+ onClick: ($event) => selectOption(option)
433
+ }, [
434
+ __props.modelValue === option.value ? (vue.openBlock(), vue.createBlock(vue.unref(vue$1.Icon), {
435
+ key: 0,
436
+ class: "size-4 text-primary",
437
+ icon: "lucide:check"
438
+ })) : vue.createCommentVNode("", true),
439
+ vue.createElementVNode("span", _hoisted_7, vue.toDisplayString(option.label), 1),
440
+ vue.createElementVNode("span", _hoisted_8, "(" + vue.toDisplayString(option.value) + ")", 1)
441
+ ], 10, _hoisted_6);
442
+ }), 128))
443
+ ], 6)) : vue.createCommentVNode("", true)
444
+ ]),
445
+ _: 1
446
+ })
447
+ ], 8, ["disabled"]))
448
+ ]),
449
+ __props.error ? (vue.openBlock(), vue.createElementBlock("p", _hoisted_9, vue.toDisplayString(__props.error), 1)) : vue.createCommentVNode("", true)
450
+ ], 512);
451
+ };
452
+ }
453
+ });
454
+ const _sfc_main$7 = /* @__PURE__ */ vue.defineComponent({
455
+ __name: "TableAction",
456
+ props: {
457
+ link: {},
458
+ icon: {},
459
+ color: {}
460
+ },
461
+ setup(__props) {
462
+ const colorClass = vue.computed(() => {
463
+ switch (__props.color) {
464
+ case "info":
465
+ return "border-blue-200 hover:bg-blue-100 dark:border-blue-800 dark:hover:bg-blue-900";
466
+ case "warning":
467
+ return "border-yellow-200 hover:bg-yellow-100 dark:border-yellow-800 dark:hover:bg-yellow-900";
468
+ case "success":
469
+ return "border-green-200 hover:bg-green-100 dark:border-green-800 dark:hover:bg-green-900";
470
+ case "error":
471
+ return "border-red-200 hover:bg-red-100 dark:border-red-800 dark:hover:bg-red-900";
472
+ default:
473
+ return "border-gray-200 hover:bg-gray-100 dark:border-gray-700 dark:bg-gray-900 dark:hover:bg-gray-800";
474
+ }
475
+ });
476
+ const iconColorClass = vue.computed(() => {
477
+ switch (__props.color) {
478
+ case "info":
479
+ return "text-blue-600 group-hover:text-blue-900 dark:text-blue-400 dark:group-hover:text-blue-100";
480
+ case "warning":
481
+ return "text-yellow-600 group-hover:text-yellow-900 dark:text-yellow-400 dark:group-hover:text-yellow-100";
482
+ case "success":
483
+ return "text-green-600 group-hover:text-green-900 dark:text-green-400 dark:group-hover:text-green-100";
484
+ case "error":
485
+ return "text-red-600 group-hover:text-red-900 dark:text-red-400 dark:group-hover:text-red-100";
486
+ default:
487
+ return "text-gray-600 group-hover:text-gray-900 dark:text-gray-400 dark:group-hover:text-gray-100";
488
+ }
489
+ });
490
+ const linkComponent = vue.computed(() => {
491
+ if (!__props.link) return "button";
492
+ try {
493
+ const RouterLink = vue.resolveComponent("RouterLink");
494
+ if (typeof RouterLink !== "string") {
495
+ return RouterLink;
496
+ }
497
+ } catch {
498
+ }
499
+ return "a";
500
+ });
501
+ const linkProps = vue.computed(() => {
502
+ if (!__props.link) return {};
503
+ if (linkComponent.value === "a") {
504
+ return { href: __props.link };
505
+ }
506
+ return { to: __props.link };
507
+ });
508
+ return (_ctx, _cache) => {
509
+ return vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(linkComponent.value), vue.mergeProps(linkProps.value, {
510
+ class: [colorClass.value, "group flex size-8 items-center justify-center rounded-lg border"]
511
+ }), {
512
+ default: vue.withCtx(() => [
513
+ vue.createVNode(vue.unref(vue$1.Icon), {
514
+ class: vue.normalizeClass([iconColorClass.value, "size-4"]),
515
+ icon: __props.icon
516
+ }, null, 8, ["class", "icon"])
517
+ ]),
518
+ _: 1
519
+ }, 16, ["class"]);
520
+ };
521
+ }
522
+ });
523
+ const _sfc_main$6 = /* @__PURE__ */ vue.defineComponent({
524
+ __name: "Button",
525
+ props: {
526
+ variant: { default: "primary" },
527
+ size: { default: "md" },
528
+ icon: {},
529
+ iconRight: {},
530
+ loading: { type: Boolean },
531
+ disabled: { type: Boolean },
532
+ block: { type: Boolean },
533
+ href: {},
534
+ to: {},
535
+ type: { default: "button" }
536
+ },
537
+ emits: ["click"],
538
+ setup(__props, { emit: __emit }) {
539
+ const props = __props;
540
+ const emit = __emit;
541
+ const variantClasses = {
542
+ primary: "bg-primary text-primary-foreground hover:bg-primary/90 focus:ring-primary",
543
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/90 focus:ring-secondary",
544
+ outline: "border border-gray-300 bg-transparent text-gray-700 hover:bg-gray-50 focus:ring-primary dark:border-gray-600 dark:text-gray-300 dark:hover:bg-gray-800",
545
+ ghost: "bg-transparent text-gray-700 hover:bg-gray-100 focus:ring-primary dark:text-gray-300 dark:hover:bg-gray-800",
546
+ danger: "bg-red-500 text-white hover:bg-red-600 focus:ring-red-500",
547
+ success: "bg-green-500 text-white hover:bg-green-600 focus:ring-green-500"
548
+ };
549
+ const sizeClasses = {
550
+ xs: "px-2 py-1 text-xs gap-1",
551
+ sm: "px-3 py-1.5 text-sm gap-1.5",
552
+ md: "px-4 py-2 text-sm gap-2",
553
+ lg: "px-5 py-2.5 text-base gap-2",
554
+ xl: "px-6 py-3 text-lg gap-2.5"
555
+ };
556
+ const iconSizeClasses = {
557
+ xs: "size-3",
558
+ sm: "size-4",
559
+ md: "size-4",
560
+ lg: "size-5",
561
+ xl: "size-6"
562
+ };
563
+ const classes = vue.computed(() => [
564
+ "inline-flex items-center justify-center font-medium rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed",
565
+ variantClasses[props.variant],
566
+ sizeClasses[props.size],
567
+ props.block && "w-full"
568
+ ]);
569
+ const component = vue.computed(() => {
570
+ if (props.to) {
571
+ try {
572
+ const RouterLink = vue.resolveComponent("RouterLink");
573
+ if (typeof RouterLink !== "string") return RouterLink;
574
+ } catch {
575
+ }
576
+ }
577
+ if (props.href) return "a";
578
+ return "button";
579
+ });
580
+ const componentProps = vue.computed(() => {
581
+ if (props.to) return { to: props.to };
582
+ if (props.href) return { href: props.href };
583
+ return { type: props.type, disabled: props.disabled || props.loading };
584
+ });
585
+ const handleClick = (event) => {
586
+ if (props.disabled || props.loading) return;
587
+ emit("click", event);
588
+ };
589
+ return (_ctx, _cache) => {
590
+ return vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(component.value), vue.mergeProps(componentProps.value, {
591
+ class: classes.value,
592
+ onClick: handleClick
593
+ }), {
594
+ default: vue.withCtx(() => [
595
+ __props.loading ? (vue.openBlock(), vue.createBlock(vue.unref(vue$1.Icon), {
596
+ key: 0,
597
+ icon: "lucide:loader-2",
598
+ class: vue.normalizeClass([iconSizeClasses[__props.size], "animate-spin"])
599
+ }, null, 8, ["class"])) : __props.icon ? (vue.openBlock(), vue.createBlock(vue.unref(vue$1.Icon), {
600
+ key: 1,
601
+ icon: __props.icon,
602
+ class: vue.normalizeClass(iconSizeClasses[__props.size])
603
+ }, null, 8, ["icon", "class"])) : vue.createCommentVNode("", true),
604
+ vue.renderSlot(_ctx.$slots, "default"),
605
+ __props.iconRight && !__props.loading ? (vue.openBlock(), vue.createBlock(vue.unref(vue$1.Icon), {
606
+ key: 2,
607
+ icon: __props.iconRight,
608
+ class: vue.normalizeClass(iconSizeClasses[__props.size])
609
+ }, null, 8, ["icon", "class"])) : vue.createCommentVNode("", true)
610
+ ]),
611
+ _: 3
612
+ }, 16, ["class"]);
613
+ };
614
+ }
615
+ });
616
+ const _hoisted_1$5 = { class: "relative inline-block" };
617
+ const _hoisted_2$3 = ["src", "alt"];
618
+ const _hoisted_3$1 = { key: 1 };
619
+ const _sfc_main$5 = /* @__PURE__ */ vue.defineComponent({
620
+ __name: "Avatar",
621
+ props: {
622
+ src: {},
623
+ alt: {},
624
+ name: {},
625
+ size: { default: "md" },
626
+ status: {},
627
+ rounded: { default: "full" }
628
+ },
629
+ setup(__props) {
630
+ const props = __props;
631
+ const imageError = vue.ref(false);
632
+ const sizeClasses = {
633
+ xs: "size-6 text-xs",
634
+ sm: "size-8 text-sm",
635
+ md: "size-10 text-base",
636
+ lg: "size-12 text-lg",
637
+ xl: "size-16 text-xl",
638
+ "2xl": "size-20 text-2xl"
639
+ };
640
+ const statusSizes = {
641
+ xs: "size-1.5",
642
+ sm: "size-2",
643
+ md: "size-2.5",
644
+ lg: "size-3",
645
+ xl: "size-4",
646
+ "2xl": "size-5"
647
+ };
648
+ const statusColors = {
649
+ online: "bg-green-500",
650
+ offline: "bg-gray-400",
651
+ away: "bg-yellow-500",
652
+ busy: "bg-red-500"
653
+ };
654
+ const roundedClasses = {
655
+ full: "rounded-full",
656
+ lg: "rounded-lg",
657
+ md: "rounded-md"
658
+ };
659
+ const initials = vue.computed(() => {
660
+ if (!props.name) return "";
661
+ return props.name.split(" ").map((n) => n[0]).slice(0, 2).join("").toUpperCase();
662
+ });
663
+ const showImage = vue.computed(() => props.src && !imageError.value);
664
+ return (_ctx, _cache) => {
665
+ return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$5, [
666
+ vue.createElementVNode("div", {
667
+ class: vue.normalizeClass([
668
+ "flex items-center justify-center overflow-hidden bg-gray-200 font-medium text-gray-600 dark:bg-gray-700 dark:text-gray-300",
669
+ sizeClasses[__props.size],
670
+ roundedClasses[__props.rounded]
671
+ ])
672
+ }, [
673
+ showImage.value ? (vue.openBlock(), vue.createElementBlock("img", {
674
+ key: 0,
675
+ src: __props.src,
676
+ alt: __props.alt || __props.name,
677
+ class: "size-full object-cover",
678
+ onError: _cache[0] || (_cache[0] = ($event) => imageError.value = true)
679
+ }, null, 40, _hoisted_2$3)) : initials.value ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_3$1, vue.toDisplayString(initials.value), 1)) : (vue.openBlock(), vue.createBlock(vue.unref(vue$1.Icon), {
680
+ key: 2,
681
+ icon: "lucide:user",
682
+ class: "size-1/2"
683
+ }))
684
+ ], 2),
685
+ __props.status ? (vue.openBlock(), vue.createElementBlock("span", {
686
+ key: 0,
687
+ class: vue.normalizeClass([
688
+ "absolute bottom-0 right-0 block rounded-full ring-2 ring-white dark:ring-gray-900",
689
+ statusSizes[__props.size],
690
+ statusColors[__props.status]
691
+ ])
692
+ }, null, 2)) : vue.createCommentVNode("", true)
693
+ ]);
694
+ };
695
+ }
696
+ });
697
+ const _hoisted_1$4 = ["aria-selected", "disabled", "onClick"];
698
+ const _hoisted_2$2 = { class: "mt-4" };
699
+ const _sfc_main$4 = /* @__PURE__ */ vue.defineComponent({
700
+ __name: "Tabs",
701
+ props: {
702
+ tabs: {},
703
+ modelValue: {},
704
+ variant: { default: "underline" }
705
+ },
706
+ emits: ["update:modelValue"],
707
+ setup(__props, { emit: __emit }) {
708
+ const props = __props;
709
+ const emit = __emit;
710
+ const activeTab = vue.computed({
711
+ get: () => {
712
+ var _a;
713
+ return props.modelValue || ((_a = props.tabs[0]) == null ? void 0 : _a.key);
714
+ },
715
+ set: (value) => emit("update:modelValue", value)
716
+ });
717
+ const selectTab = (tab) => {
718
+ if (tab.disabled) return;
719
+ activeTab.value = tab.key;
720
+ };
721
+ const variantClasses = {
722
+ underline: {
723
+ container: "border-b border-gray-200 dark:border-gray-700",
724
+ tab: "border-b-2 -mb-px px-4 py-2",
725
+ active: "border-primary text-primary dark:text-primary",
726
+ inactive: "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 dark:text-gray-400 dark:hover:text-gray-300"
727
+ },
728
+ pills: {
729
+ container: "gap-2",
730
+ tab: "px-4 py-2 rounded-lg",
731
+ active: "bg-primary text-white",
732
+ inactive: "text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-800"
733
+ },
734
+ boxed: {
735
+ container: "bg-gray-100 dark:bg-gray-800 p-1 rounded-lg gap-1",
736
+ tab: "px-4 py-2 rounded-md",
737
+ active: "bg-white dark:bg-gray-900 text-gray-900 dark:text-white shadow-sm",
738
+ inactive: "text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300"
739
+ }
740
+ };
741
+ vue.provide("activeTab", activeTab);
742
+ return (_ctx, _cache) => {
743
+ return vue.openBlock(), vue.createElementBlock("div", null, [
744
+ vue.createElementVNode("div", {
745
+ class: vue.normalizeClass([
746
+ "flex",
747
+ variantClasses[__props.variant].container
748
+ ]),
749
+ role: "tablist"
750
+ }, [
751
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.tabs, (tab) => {
752
+ return vue.openBlock(), vue.createElementBlock("button", {
753
+ key: tab.key,
754
+ type: "button",
755
+ role: "tab",
756
+ "aria-selected": activeTab.value === tab.key,
757
+ disabled: tab.disabled,
758
+ class: vue.normalizeClass([
759
+ "text-sm font-medium transition-colors focus:outline-none disabled:cursor-not-allowed disabled:opacity-50",
760
+ variantClasses[__props.variant].tab,
761
+ activeTab.value === tab.key ? variantClasses[__props.variant].active : variantClasses[__props.variant].inactive
762
+ ]),
763
+ onClick: ($event) => selectTab(tab)
764
+ }, vue.toDisplayString(tab.label), 11, _hoisted_1$4);
765
+ }), 128))
766
+ ], 2),
767
+ vue.createElementVNode("div", _hoisted_2$2, [
768
+ vue.renderSlot(_ctx.$slots, "default", { activeTab: activeTab.value })
769
+ ])
770
+ ]);
771
+ };
772
+ }
773
+ });
774
+ const _hoisted_1$3 = { role: "tabpanel" };
775
+ const _sfc_main$3 = /* @__PURE__ */ vue.defineComponent({
776
+ __name: "TabPanel",
777
+ props: {
778
+ value: {}
779
+ },
780
+ setup(__props) {
781
+ const props = __props;
782
+ const activeTab = vue.inject("activeTab");
783
+ const isActive = vue.computed(() => (activeTab == null ? void 0 : activeTab.value) === props.value);
784
+ return (_ctx, _cache) => {
785
+ return vue.withDirectives((vue.openBlock(), vue.createElementBlock("div", _hoisted_1$3, [
786
+ vue.renderSlot(_ctx.$slots, "default")
787
+ ], 512)), [
788
+ [vue.vShow, isActive.value]
789
+ ]);
790
+ };
791
+ }
792
+ });
793
+ const _hoisted_1$2 = {
794
+ type: "button",
795
+ class: "inline-flex items-center gap-2 rounded-lg border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700"
796
+ };
797
+ const _hoisted_2$1 = {
798
+ key: 0,
799
+ class: "my-1 border-t border-gray-200 dark:border-gray-700"
800
+ };
801
+ const _hoisted_3 = ["disabled", "onClick"];
802
+ const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({
803
+ __name: "Dropdown",
804
+ props: {
805
+ items: {},
806
+ align: { default: "left" },
807
+ width: { default: "auto" },
808
+ teleport: { type: Boolean, default: true }
809
+ },
810
+ emits: ["select"],
811
+ setup(__props, { emit: __emit }) {
812
+ const props = __props;
813
+ const emit = __emit;
814
+ const isOpen = vue.ref(false);
815
+ const dropdownRef = vue.ref();
816
+ const triggerRef = vue.ref();
817
+ const menuRef = vue.ref();
818
+ const dropdownPosition = vue.ref({ top: 0, left: 0, width: 0 });
819
+ const updatePosition = () => {
820
+ if (!triggerRef.value || !props.teleport) return;
821
+ const rect = triggerRef.value.getBoundingClientRect();
822
+ dropdownPosition.value = {
823
+ top: rect.bottom + window.scrollY + 8,
824
+ left: props.align === "right" ? rect.right + window.scrollX : rect.left + window.scrollX,
825
+ width: rect.width
826
+ };
827
+ };
828
+ const toggle = () => {
829
+ isOpen.value = !isOpen.value;
830
+ if (isOpen.value) {
831
+ vue.nextTick(updatePosition);
832
+ }
833
+ };
834
+ const close = () => {
835
+ isOpen.value = false;
836
+ };
837
+ const selectItem = (item) => {
838
+ if (item.disabled || item.divider) return;
839
+ emit("select", item);
840
+ close();
841
+ };
842
+ const handleClickOutside = (event) => {
843
+ var _a, _b;
844
+ const target = event.target;
845
+ const isInsideTrigger = (_a = triggerRef.value) == null ? void 0 : _a.contains(target);
846
+ const isInsideMenu = (_b = menuRef.value) == null ? void 0 : _b.contains(target);
847
+ if (!isInsideTrigger && !isInsideMenu) {
848
+ close();
849
+ }
850
+ };
851
+ vue.watch(isOpen, (newValue) => {
852
+ if (newValue) {
853
+ document.addEventListener("click", handleClickOutside);
854
+ window.addEventListener("scroll", updatePosition, true);
855
+ window.addEventListener("resize", updatePosition);
856
+ } else {
857
+ document.removeEventListener("click", handleClickOutside);
858
+ window.removeEventListener("scroll", updatePosition, true);
859
+ window.removeEventListener("resize", updatePosition);
860
+ }
861
+ });
862
+ vue.onUnmounted(() => {
863
+ document.removeEventListener("click", handleClickOutside);
864
+ window.removeEventListener("scroll", updatePosition, true);
865
+ window.removeEventListener("resize", updatePosition);
866
+ });
867
+ const widthClasses = {
868
+ auto: "w-auto min-w-[10rem]",
869
+ full: "w-full",
870
+ sm: "w-32",
871
+ md: "w-48",
872
+ lg: "w-64"
873
+ };
874
+ const dropdownStyle = vue.computed(() => {
875
+ if (!props.teleport) return {};
876
+ return {
877
+ position: "absolute",
878
+ top: `${dropdownPosition.value.top}px`,
879
+ left: props.align === "right" ? "auto" : `${dropdownPosition.value.left}px`,
880
+ right: props.align === "right" ? `${window.innerWidth - dropdownPosition.value.left - dropdownPosition.value.width}px` : "auto"
881
+ };
882
+ });
883
+ return (_ctx, _cache) => {
884
+ return vue.openBlock(), vue.createElementBlock("div", {
885
+ ref_key: "dropdownRef",
886
+ ref: dropdownRef,
887
+ class: "relative inline-block"
888
+ }, [
889
+ vue.createElementVNode("div", {
890
+ ref_key: "triggerRef",
891
+ ref: triggerRef,
892
+ onClick: toggle
893
+ }, [
894
+ vue.renderSlot(_ctx.$slots, "trigger", {}, () => [
895
+ vue.createElementVNode("button", _hoisted_1$2, [
896
+ vue.renderSlot(_ctx.$slots, "trigger-label", {}, () => [
897
+ _cache[0] || (_cache[0] = vue.createTextVNode("Options", -1))
898
+ ]),
899
+ vue.createVNode(vue.unref(vue$1.Icon), {
900
+ icon: "lucide:chevron-down",
901
+ class: vue.normalizeClass(["size-4 transition-transform", isOpen.value && "rotate-180"])
902
+ }, null, 8, ["class"])
903
+ ])
904
+ ])
905
+ ], 512),
906
+ (vue.openBlock(), vue.createBlock(vue.Teleport, {
907
+ to: "body",
908
+ disabled: !__props.teleport
909
+ }, [
910
+ vue.createVNode(vue.Transition, {
911
+ "enter-active-class": "transition ease-out duration-100",
912
+ "enter-from-class": "transform opacity-0 scale-95",
913
+ "enter-to-class": "transform opacity-100 scale-100",
914
+ "leave-active-class": "transition ease-in duration-75",
915
+ "leave-from-class": "transform opacity-100 scale-100",
916
+ "leave-to-class": "transform opacity-0 scale-95"
917
+ }, {
918
+ default: vue.withCtx(() => [
919
+ isOpen.value ? (vue.openBlock(), vue.createElementBlock("div", {
920
+ key: 0,
921
+ ref_key: "menuRef",
922
+ ref: menuRef,
923
+ style: vue.normalizeStyle(dropdownStyle.value),
924
+ class: vue.normalizeClass([
925
+ "z-[9999] rounded-lg border border-gray-200 bg-white py-1 shadow-lg dark:border-gray-700 dark:bg-gray-800",
926
+ widthClasses[__props.width],
927
+ !__props.teleport && (__props.align === "right" ? "absolute mt-2 right-0" : "absolute mt-2 left-0")
928
+ ])
929
+ }, [
930
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.items, (item) => {
931
+ return vue.openBlock(), vue.createElementBlock(vue.Fragment, {
932
+ key: item.key
933
+ }, [
934
+ item.divider ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2$1)) : (vue.openBlock(), vue.createElementBlock("button", {
935
+ key: 1,
936
+ type: "button",
937
+ disabled: item.disabled,
938
+ class: vue.normalizeClass([
939
+ "flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition-colors",
940
+ item.disabled ? "cursor-not-allowed opacity-50" : item.danger ? "text-red-600 hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-900/20" : "text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700"
941
+ ]),
942
+ onClick: ($event) => selectItem(item)
943
+ }, [
944
+ item.icon ? (vue.openBlock(), vue.createBlock(vue.unref(vue$1.Icon), {
945
+ key: 0,
946
+ icon: item.icon,
947
+ class: "size-4"
948
+ }, null, 8, ["icon"])) : vue.createCommentVNode("", true),
949
+ vue.createTextVNode(" " + vue.toDisplayString(item.label), 1)
950
+ ], 10, _hoisted_3))
951
+ ], 64);
952
+ }), 128))
953
+ ], 6)) : vue.createCommentVNode("", true)
954
+ ]),
955
+ _: 1
956
+ })
957
+ ], 8, ["disabled"]))
958
+ ], 512);
959
+ };
960
+ }
961
+ });
962
+ const _hoisted_1$1 = {
963
+ key: 2,
964
+ class: "text-sm font-semibold"
965
+ };
966
+ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
967
+ __name: "Stepper",
968
+ props: {
969
+ steps: {},
970
+ modelValue: {},
971
+ orientation: { default: "horizontal" }
972
+ },
973
+ emits: ["update:modelValue"],
974
+ setup(__props) {
975
+ const props = __props;
976
+ const getCurrentStepIndex = () => {
977
+ if (props.modelValue === void 0) return 0;
978
+ const index = props.steps.findIndex((s) => s.key === props.modelValue);
979
+ return index >= 0 ? index : 0;
980
+ };
981
+ const isStepComplete = (index) => index < getCurrentStepIndex();
982
+ const isStepActive = (index) => index === getCurrentStepIndex();
983
+ const isStepPending = (index) => index > getCurrentStepIndex();
984
+ return (_ctx, _cache) => {
985
+ return vue.openBlock(), vue.createElementBlock("div", {
986
+ class: vue.normalizeClass([
987
+ "w-full",
988
+ __props.orientation === "vertical" ? "flex flex-col" : ""
989
+ ])
990
+ }, [
991
+ vue.createElementVNode("div", {
992
+ class: vue.normalizeClass([
993
+ __props.orientation === "horizontal" ? "relative flex items-start justify-between" : "relative flex flex-col gap-4"
994
+ ])
995
+ }, [
996
+ __props.orientation === "horizontal" ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 0 }, [
997
+ _cache[0] || (_cache[0] = vue.createElementVNode("div", {
998
+ class: "absolute left-0 top-6 h-0.5 w-full bg-gray-200 dark:bg-gray-700",
999
+ "aria-hidden": "true"
1000
+ }, null, -1)),
1001
+ vue.createElementVNode("div", {
1002
+ class: "absolute left-0 top-6 h-0.5 bg-primary transition-all duration-500 ease-in-out",
1003
+ style: vue.normalizeStyle({
1004
+ width: `${getCurrentStepIndex() / (__props.steps.length - 1) * 100}%`
1005
+ }),
1006
+ "aria-hidden": "true"
1007
+ }, null, 4)
1008
+ ], 64)) : vue.createCommentVNode("", true),
1009
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.steps, (step, index) => {
1010
+ return vue.openBlock(), vue.createElementBlock("div", {
1011
+ key: step.key,
1012
+ class: vue.normalizeClass([
1013
+ "relative",
1014
+ __props.orientation === "horizontal" ? "flex flex-1 flex-col items-center" : "flex items-start gap-4"
1015
+ ])
1016
+ }, [
1017
+ __props.orientation === "vertical" && index < __props.steps.length - 1 ? (vue.openBlock(), vue.createElementBlock("div", {
1018
+ key: 0,
1019
+ class: vue.normalizeClass(["absolute left-6 top-12 h-full w-0.5 -translate-x-1/2", isStepComplete(index) ? "bg-primary" : "bg-gray-200 dark:bg-gray-700"])
1020
+ }, null, 2)) : vue.createCommentVNode("", true),
1021
+ vue.createElementVNode("div", {
1022
+ class: vue.normalizeClass(["relative z-10 flex size-12 shrink-0 items-center justify-center rounded-full border-2 transition-all duration-300", {
1023
+ "border-primary bg-primary text-white shadow-lg": isStepActive(index) || isStepComplete(index),
1024
+ "border-gray-300 bg-white text-gray-400 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-500": isStepPending(index)
1025
+ }])
1026
+ }, [
1027
+ isStepComplete(index) ? (vue.openBlock(), vue.createBlock(vue.unref(vue$1.Icon), {
1028
+ key: 0,
1029
+ icon: "lucide:check",
1030
+ class: "size-6"
1031
+ })) : step.icon ? (vue.openBlock(), vue.createBlock(vue.unref(vue$1.Icon), {
1032
+ key: 1,
1033
+ icon: step.icon,
1034
+ class: "size-6"
1035
+ }, null, 8, ["icon"])) : (vue.openBlock(), vue.createElementBlock("span", _hoisted_1$1, vue.toDisplayString(index + 1), 1))
1036
+ ], 2),
1037
+ vue.createElementVNode("div", {
1038
+ class: vue.normalizeClass([
1039
+ __props.orientation === "horizontal" ? "mt-4 flex flex-col items-center text-center" : "flex flex-col pt-2"
1040
+ ])
1041
+ }, [
1042
+ vue.createElementVNode("p", {
1043
+ class: vue.normalizeClass(["text-sm font-semibold transition-colors", {
1044
+ "text-primary dark:text-primary": isStepActive(index) || isStepComplete(index),
1045
+ "text-gray-500 dark:text-gray-400": isStepPending(index)
1046
+ }])
1047
+ }, vue.toDisplayString(step.title), 3),
1048
+ step.description ? (vue.openBlock(), vue.createElementBlock("p", {
1049
+ key: 0,
1050
+ class: vue.normalizeClass(["mt-1 text-xs", {
1051
+ "text-gray-600 dark:text-gray-300": isStepActive(index),
1052
+ "text-gray-500 dark:text-gray-400": !isStepActive(index)
1053
+ }])
1054
+ }, vue.toDisplayString(step.description), 3)) : vue.createCommentVNode("", true)
1055
+ ], 2)
1056
+ ], 2);
1057
+ }), 128))
1058
+ ], 2)
1059
+ ], 2);
1060
+ };
1061
+ }
1062
+ });
1063
+ const _hoisted_1 = { class: "overflow-hidden" };
1064
+ const _hoisted_2 = { class: "space-y-4 p-6" };
1065
+ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
1066
+ __name: "CollapsibleCard",
1067
+ props: {
1068
+ title: {},
1069
+ description: {},
1070
+ defaultExpanded: { type: Boolean, default: true }
1071
+ },
1072
+ setup(__props) {
1073
+ const props = __props;
1074
+ const isExpanded = vue.ref(props.defaultExpanded);
1075
+ const toggle = () => {
1076
+ isExpanded.value = !isExpanded.value;
1077
+ };
1078
+ return (_ctx, _cache) => {
1079
+ return vue.openBlock(), vue.createBlock(_sfc_main$a, {
1080
+ title: __props.title,
1081
+ description: __props.description
1082
+ }, {
1083
+ actions: vue.withCtx(() => [
1084
+ vue.renderSlot(_ctx.$slots, "actions"),
1085
+ vue.createElementVNode("button", {
1086
+ type: "button",
1087
+ class: "rounded-lg p-1.5 text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-800",
1088
+ onClick: toggle
1089
+ }, [
1090
+ vue.createVNode(vue.unref(vue$1.Icon), {
1091
+ icon: isExpanded.value ? "lucide:chevron-up" : "lucide:chevron-down",
1092
+ class: "size-5"
1093
+ }, null, 8, ["icon"])
1094
+ ])
1095
+ ]),
1096
+ default: vue.withCtx(() => [
1097
+ vue.createVNode(vue.Transition, {
1098
+ "enter-active-class": "transition-all duration-200 ease-out",
1099
+ "enter-from-class": "opacity-0 max-h-0",
1100
+ "enter-to-class": "opacity-100 max-h-[2000px]",
1101
+ "leave-active-class": "transition-all duration-200 ease-in",
1102
+ "leave-from-class": "opacity-100 max-h-[2000px]",
1103
+ "leave-to-class": "opacity-0 max-h-0"
1104
+ }, {
1105
+ default: vue.withCtx(() => [
1106
+ vue.withDirectives(vue.createElementVNode("div", _hoisted_1, [
1107
+ vue.createElementVNode("div", _hoisted_2, [
1108
+ vue.renderSlot(_ctx.$slots, "default")
1109
+ ])
1110
+ ], 512), [
1111
+ [vue.vShow, isExpanded.value]
1112
+ ])
1113
+ ]),
1114
+ _: 3
1115
+ })
1116
+ ]),
1117
+ _: 3
1118
+ }, 8, ["title", "description"]);
1119
+ };
1120
+ }
1121
+ });
1122
+ exports._sfc_main = _sfc_main$a;
1123
+ exports._sfc_main$1 = _sfc_main$9;
1124
+ exports._sfc_main$10 = _sfc_main;
1125
+ exports._sfc_main$2 = _sfc_main$8;
1126
+ exports._sfc_main$3 = _sfc_main$7;
1127
+ exports._sfc_main$4 = _sfc_main$6;
1128
+ exports._sfc_main$5 = _sfc_main$5;
1129
+ exports._sfc_main$6 = _sfc_main$4;
1130
+ exports._sfc_main$7 = _sfc_main$3;
1131
+ exports._sfc_main$8 = _sfc_main$2;
1132
+ exports._sfc_main$9 = _sfc_main$1;
1133
+ //# sourceMappingURL=CollapsibleCard.vue_vue_type_script_setup_true_lang-D2MeLTRV.cjs.map