cisse-vue-ui 0.5.21 → 0.5.23

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 (137) hide show
  1. package/dist/{ListSkeleton.vue_vue_type_script_setup_true_lang-D3_Oddwt.js → Button.vue_vue_type_script_setup_true_lang-CD9QPOeU.js} +114 -10
  2. package/dist/Button.vue_vue_type_script_setup_true_lang-CD9QPOeU.js.map +1 -0
  3. package/dist/{ListSkeleton.vue_vue_type_script_setup_true_lang-CrEu33_J.cjs → Button.vue_vue_type_script_setup_true_lang-Cev21KGJ.cjs} +113 -9
  4. package/dist/Button.vue_vue_type_script_setup_true_lang-Cev21KGJ.cjs.map +1 -0
  5. package/dist/{RangeSlider.vue_vue_type_script_setup_true_lang-ClH-pyK8.cjs → Combobox.vue_vue_type_script_setup_true_lang-D9TIId4E.cjs} +621 -266
  6. package/dist/Combobox.vue_vue_type_script_setup_true_lang-D9TIId4E.cjs.map +1 -0
  7. package/dist/{RangeSlider.vue_vue_type_script_setup_true_lang-B79_S1JL.js → Combobox.vue_vue_type_script_setup_true_lang-DCLKWzhc.js} +595 -240
  8. package/dist/Combobox.vue_vue_type_script_setup_true_lang-DCLKWzhc.js.map +1 -0
  9. package/dist/{Skeleton.vue_vue_type_script_setup_true_lang-CsDMGhaT.cjs → ConfirmDialog.vue_vue_type_script_setup_true_lang-CwHYxBhR.cjs} +290 -128
  10. package/dist/ConfirmDialog.vue_vue_type_script_setup_true_lang-CwHYxBhR.cjs.map +1 -0
  11. package/dist/{Skeleton.vue_vue_type_script_setup_true_lang-Q4PcIELi.js → ConfirmDialog.vue_vue_type_script_setup_true_lang-Dm4kLAnr.js} +291 -129
  12. package/dist/ConfirmDialog.vue_vue_type_script_setup_true_lang-Dm4kLAnr.js.map +1 -0
  13. package/dist/{Timeline.vue_vue_type_script_setup_true_lang-C5SKEGPG.cjs → DarkModeToggle.vue_vue_type_script_setup_true_lang-CSxGvdSP.cjs} +192 -408
  14. package/dist/DarkModeToggle.vue_vue_type_script_setup_true_lang-CSxGvdSP.cjs.map +1 -0
  15. package/dist/{Timeline.vue_vue_type_script_setup_true_lang-ykGksWXN.js → DarkModeToggle.vue_vue_type_script_setup_true_lang-D1Q43mhJ.js} +153 -369
  16. package/dist/DarkModeToggle.vue_vue_type_script_setup_true_lang-D1Q43mhJ.js.map +1 -0
  17. package/dist/{Dropdown.vue_vue_type_script_setup_true_lang-DKxcVBKu.cjs → Dropdown.vue_vue_type_script_setup_true_lang-DNeh9Gi-.cjs} +32 -15
  18. package/dist/Dropdown.vue_vue_type_script_setup_true_lang-DNeh9Gi-.cjs.map +1 -0
  19. package/dist/{Dropdown.vue_vue_type_script_setup_true_lang-C3pr8BwC.js → Dropdown.vue_vue_type_script_setup_true_lang-DXV811zB.js} +32 -15
  20. package/dist/Dropdown.vue_vue_type_script_setup_true_lang-DXV811zB.js.map +1 -0
  21. package/dist/{PageLayout.vue_vue_type_script_setup_true_lang-D22uNeS1.cjs → PageLayout.vue_vue_type_script_setup_true_lang-C0YzyJnK.cjs} +2 -2
  22. package/dist/{PageLayout.vue_vue_type_script_setup_true_lang-D22uNeS1.cjs.map → PageLayout.vue_vue_type_script_setup_true_lang-C0YzyJnK.cjs.map} +1 -1
  23. package/dist/{PageLayout.vue_vue_type_script_setup_true_lang-kT7np2ir.js → PageLayout.vue_vue_type_script_setup_true_lang-ClzYGS8h.js} +2 -2
  24. package/dist/{PageLayout.vue_vue_type_script_setup_true_lang-kT7np2ir.js.map → PageLayout.vue_vue_type_script_setup_true_lang-ClzYGS8h.js.map} +1 -1
  25. package/dist/components/core/AccordionItem.vue.d.ts +2 -0
  26. package/dist/components/core/DarkModeToggle.stories.d.ts +15 -0
  27. package/dist/components/core/DarkModeToggle.test.d.ts +1 -0
  28. package/dist/components/core/DarkModeToggle.vue.d.ts +21 -0
  29. package/dist/components/core/Dropdown.vue.d.ts +2 -0
  30. package/dist/components/core/Popover.vue.d.ts +2 -0
  31. package/dist/components/core/Tooltip.vue.d.ts +2 -0
  32. package/dist/components/core/index.cjs +23 -21
  33. package/dist/components/core/index.cjs.map +1 -1
  34. package/dist/components/core/index.d.ts +2 -0
  35. package/dist/components/core/index.js +17 -15
  36. package/dist/components/core/index.js.map +1 -1
  37. package/dist/components/core/index.test.d.ts +1 -0
  38. package/dist/components/feedback/ConfirmDialog.stories.d.ts +12 -0
  39. package/dist/components/feedback/ConfirmDialog.test.d.ts +1 -0
  40. package/dist/components/feedback/ConfirmDialog.vue.d.ts +53 -0
  41. package/dist/components/feedback/LoadingSpinner.vue.d.ts +6 -1
  42. package/dist/components/feedback/Modal.vue.d.ts +18 -3
  43. package/dist/components/feedback/Progress.vue.d.ts +1 -1
  44. package/dist/components/feedback/index.cjs +17 -16
  45. package/dist/components/feedback/index.cjs.map +1 -1
  46. package/dist/components/feedback/index.d.ts +2 -0
  47. package/dist/components/feedback/index.js +6 -5
  48. package/dist/components/feedback/index.test.d.ts +1 -0
  49. package/dist/components/form/Checkbox.vue.d.ts +2 -0
  50. package/dist/components/form/ColorPicker.vue.d.ts +3 -0
  51. package/dist/components/form/Combobox.stories.d.ts +15 -0
  52. package/dist/components/form/Combobox.test.d.ts +1 -0
  53. package/dist/components/form/Combobox.vue.d.ts +46 -0
  54. package/dist/components/form/DatePicker.vue.d.ts +2 -0
  55. package/dist/components/form/FormHelp.vue.d.ts +2 -0
  56. package/dist/components/form/Switch.vue.d.ts +2 -0
  57. package/dist/components/form/index.cjs +17 -16
  58. package/dist/components/form/index.cjs.map +1 -1
  59. package/dist/components/form/index.d.ts +2 -0
  60. package/dist/components/form/index.js +3 -2
  61. package/dist/components/form/index.test.d.ts +1 -0
  62. package/dist/components/index.cjs +57 -54
  63. package/dist/components/index.cjs.map +1 -1
  64. package/dist/components/index.js +35 -32
  65. package/dist/components/index.test.d.ts +1 -0
  66. package/dist/components/layout/index.cjs +1 -1
  67. package/dist/components/layout/index.js +1 -1
  68. package/dist/components/layout/index.test.d.ts +1 -0
  69. package/dist/components/type/index.test.d.ts +1 -0
  70. package/dist/composables/index.cjs +9 -2
  71. package/dist/composables/index.cjs.map +1 -1
  72. package/dist/composables/index.d.ts +2 -0
  73. package/dist/composables/index.js +15 -8
  74. package/dist/composables/index.js.map +1 -1
  75. package/dist/composables/index.test.d.ts +1 -0
  76. package/dist/composables/useDarkMode.test.d.ts +1 -0
  77. package/dist/composables/useDropdown.test.d.ts +1 -0
  78. package/dist/composables/useExportCSV.test.d.ts +1 -0
  79. package/dist/composables/useFocusTrap.d.ts +41 -0
  80. package/dist/composables/useFocusTrap.test.d.ts +1 -0
  81. package/dist/composables/useId.d.ts +42 -0
  82. package/dist/composables/useId.test.d.ts +1 -0
  83. package/dist/composables/useModal.d.ts +1 -1
  84. package/dist/composables/useModal.test.d.ts +1 -0
  85. package/dist/index-BMoLBt6A.js +75 -0
  86. package/dist/index-BMoLBt6A.js.map +1 -0
  87. package/dist/index-CJwlO351.js +347 -0
  88. package/dist/index-CJwlO351.js.map +1 -0
  89. package/dist/index-CUNU12xk.cjs +346 -0
  90. package/dist/index-CUNU12xk.cjs.map +1 -0
  91. package/dist/index-DwFvFW-3.cjs +74 -0
  92. package/dist/index-DwFvFW-3.cjs.map +1 -0
  93. package/dist/index.cjs +67 -57
  94. package/dist/index.cjs.map +1 -1
  95. package/dist/index.js +51 -41
  96. package/dist/index.js.map +1 -1
  97. package/dist/index.test.d.ts +1 -0
  98. package/dist/style.css +1 -1
  99. package/dist/types/form.d.ts +4 -0
  100. package/dist/types/index.test.d.ts +1 -0
  101. package/dist/useDarkMode-Cl5QWTlC.js +53 -0
  102. package/dist/useDarkMode-Cl5QWTlC.js.map +1 -0
  103. package/dist/useDarkMode-DLZcJEUQ.cjs +52 -0
  104. package/dist/useDarkMode-DLZcJEUQ.cjs.map +1 -0
  105. package/dist/useFocusTrap-AnlJsihM.js +120 -0
  106. package/dist/useFocusTrap-AnlJsihM.js.map +1 -0
  107. package/dist/useFocusTrap-kcxO8AeU.cjs +119 -0
  108. package/dist/useFocusTrap-kcxO8AeU.cjs.map +1 -0
  109. package/dist/useId-nxrBaIC9.cjs +25 -0
  110. package/dist/useId-nxrBaIC9.cjs.map +1 -0
  111. package/dist/useId-xeHj7rkg.js +26 -0
  112. package/dist/useId-xeHj7rkg.js.map +1 -0
  113. package/dist/{useToast-CRh_sG82.cjs → useToast-Bk60GArg.cjs} +1 -50
  114. package/dist/useToast-Bk60GArg.cjs.map +1 -0
  115. package/dist/{useToast-DwFOkewC.js → useToast-ina5g3mj.js} +6 -55
  116. package/dist/useToast-ina5g3mj.js.map +1 -0
  117. package/package.json +9 -8
  118. package/dist/Checkbox.vue_vue_type_script_setup_true_lang-B-nLCCNY.js +0 -54
  119. package/dist/Checkbox.vue_vue_type_script_setup_true_lang-B-nLCCNY.js.map +0 -1
  120. package/dist/Checkbox.vue_vue_type_script_setup_true_lang-DIoHDji4.cjs +0 -53
  121. package/dist/Checkbox.vue_vue_type_script_setup_true_lang-DIoHDji4.cjs.map +0 -1
  122. package/dist/Dropdown.vue_vue_type_script_setup_true_lang-C3pr8BwC.js.map +0 -1
  123. package/dist/Dropdown.vue_vue_type_script_setup_true_lang-DKxcVBKu.cjs.map +0 -1
  124. package/dist/ListSkeleton.vue_vue_type_script_setup_true_lang-CrEu33_J.cjs.map +0 -1
  125. package/dist/ListSkeleton.vue_vue_type_script_setup_true_lang-D3_Oddwt.js.map +0 -1
  126. package/dist/RangeSlider.vue_vue_type_script_setup_true_lang-B79_S1JL.js.map +0 -1
  127. package/dist/RangeSlider.vue_vue_type_script_setup_true_lang-ClH-pyK8.cjs.map +0 -1
  128. package/dist/Skeleton.vue_vue_type_script_setup_true_lang-CsDMGhaT.cjs.map +0 -1
  129. package/dist/Skeleton.vue_vue_type_script_setup_true_lang-Q4PcIELi.js.map +0 -1
  130. package/dist/Timeline.vue_vue_type_script_setup_true_lang-C5SKEGPG.cjs.map +0 -1
  131. package/dist/Timeline.vue_vue_type_script_setup_true_lang-ykGksWXN.js.map +0 -1
  132. package/dist/index-C3NAM2ds.js +0 -72
  133. package/dist/index-C3NAM2ds.js.map +0 -1
  134. package/dist/index-Ti1RIOEG.cjs +0 -71
  135. package/dist/index-Ti1RIOEG.cjs.map +0 -1
  136. package/dist/useToast-CRh_sG82.cjs.map +0 -1
  137. package/dist/useToast-DwFOkewC.js.map +0 -1
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ const vue = require("vue");
3
+ const FOCUSABLE_SELECTORS = [
4
+ "a[href]",
5
+ "button:not([disabled])",
6
+ "input:not([disabled])",
7
+ "select:not([disabled])",
8
+ "textarea:not([disabled])",
9
+ '[tabindex]:not([tabindex="-1"])',
10
+ '[contenteditable="true"]'
11
+ ].join(", ");
12
+ function useFocusTrap(options = {}) {
13
+ const { focusFirst = true, restoreFocus = true, initialFocus = null } = options;
14
+ const containerRef = vue.ref(null);
15
+ const isActive = vue.ref(false);
16
+ const previouslyFocusedElement = vue.ref(null);
17
+ function getFocusableElements() {
18
+ if (!containerRef.value) return [];
19
+ return Array.from(containerRef.value.querySelectorAll(FOCUSABLE_SELECTORS)).filter(
20
+ (el) => el.offsetParent !== null
21
+ // Element is visible
22
+ );
23
+ }
24
+ function getInitialFocusElement() {
25
+ if (!containerRef.value) return null;
26
+ if (initialFocus) {
27
+ if (typeof initialFocus === "string") {
28
+ return containerRef.value.querySelector(initialFocus);
29
+ }
30
+ return initialFocus;
31
+ }
32
+ const focusable = getFocusableElements();
33
+ return focusable[0] || null;
34
+ }
35
+ function handleKeyDown(event) {
36
+ if (event.key !== "Tab" || !containerRef.value) return;
37
+ const focusable = getFocusableElements();
38
+ if (focusable.length === 0) return;
39
+ const firstFocusable = focusable[0];
40
+ const lastFocusable = focusable[focusable.length - 1];
41
+ const activeElement = document.activeElement;
42
+ if (event.shiftKey) {
43
+ if (activeElement === firstFocusable || !containerRef.value.contains(activeElement)) {
44
+ event.preventDefault();
45
+ lastFocusable.focus();
46
+ }
47
+ } else {
48
+ if (activeElement === lastFocusable || !containerRef.value.contains(activeElement)) {
49
+ event.preventDefault();
50
+ firstFocusable.focus();
51
+ }
52
+ }
53
+ }
54
+ function activate() {
55
+ if (isActive.value) return;
56
+ previouslyFocusedElement.value = document.activeElement;
57
+ isActive.value = true;
58
+ document.addEventListener("keydown", handleKeyDown);
59
+ if (focusFirst) {
60
+ requestAnimationFrame(() => {
61
+ const initialElement = getInitialFocusElement();
62
+ if (initialElement) {
63
+ initialElement.focus();
64
+ }
65
+ });
66
+ }
67
+ }
68
+ function deactivate() {
69
+ if (!isActive.value) return;
70
+ isActive.value = false;
71
+ document.removeEventListener("keydown", handleKeyDown);
72
+ if (restoreFocus && previouslyFocusedElement.value) {
73
+ previouslyFocusedElement.value.focus();
74
+ previouslyFocusedElement.value = null;
75
+ }
76
+ }
77
+ const activeOption = options.active;
78
+ if (activeOption !== void 0) {
79
+ if (typeof activeOption === "boolean") {
80
+ if (activeOption) {
81
+ const unwatch = vue.watch(
82
+ containerRef,
83
+ (container) => {
84
+ if (container) {
85
+ activate();
86
+ unwatch();
87
+ }
88
+ },
89
+ { immediate: true }
90
+ );
91
+ }
92
+ } else {
93
+ vue.watch(
94
+ [activeOption, containerRef],
95
+ ([active, container]) => {
96
+ if (active && container) {
97
+ activate();
98
+ } else if (!active) {
99
+ deactivate();
100
+ }
101
+ },
102
+ { immediate: true }
103
+ );
104
+ }
105
+ }
106
+ if (vue.getCurrentInstance()) {
107
+ vue.onUnmounted(() => {
108
+ deactivate();
109
+ });
110
+ }
111
+ return {
112
+ containerRef,
113
+ activate,
114
+ deactivate,
115
+ isActive
116
+ };
117
+ }
118
+ exports.useFocusTrap = useFocusTrap;
119
+ //# sourceMappingURL=useFocusTrap-kcxO8AeU.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFocusTrap-kcxO8AeU.cjs","sources":["../src/composables/useFocusTrap.ts"],"sourcesContent":["import { ref, watch, onUnmounted, getCurrentInstance, type Ref } from 'vue'\r\n\r\nconst FOCUSABLE_SELECTORS = [\r\n 'a[href]',\r\n 'button:not([disabled])',\r\n 'input:not([disabled])',\r\n 'select:not([disabled])',\r\n 'textarea:not([disabled])',\r\n '[tabindex]:not([tabindex=\"-1\"])',\r\n '[contenteditable=\"true\"]',\r\n].join(', ')\r\n\r\nexport interface UseFocusTrapOptions {\r\n /** Whether the focus trap is active */\r\n active?: Ref<boolean> | boolean\r\n /** Focus the first focusable element when trap activates */\r\n focusFirst?: boolean\r\n /** Restore focus to the previously focused element when trap deactivates */\r\n restoreFocus?: boolean\r\n /** Initial element to focus (selector or element) */\r\n initialFocus?: string | HTMLElement | null\r\n}\r\n\r\nexport interface UseFocusTrapReturn {\r\n /** Ref to attach to the container element */\r\n containerRef: Ref<HTMLElement | null>\r\n /** Activate the focus trap manually */\r\n activate: () => void\r\n /** Deactivate the focus trap manually */\r\n deactivate: () => void\r\n /** Whether the focus trap is currently active */\r\n isActive: Ref<boolean>\r\n}\r\n\r\n/**\r\n * Composable for trapping focus within a container element (for modals, dialogs, etc.)\r\n *\r\n * @example\r\n * ```vue\r\n * <script setup>\r\n * const isOpen = ref(false)\r\n * const { containerRef } = useFocusTrap({ active: isOpen })\r\n * </script>\r\n *\r\n * <template>\r\n * <div v-if=\"isOpen\" ref=\"containerRef\" role=\"dialog\">\r\n * <button>First focusable</button>\r\n * <input type=\"text\" />\r\n * <button @click=\"isOpen = false\">Close</button>\r\n * </div>\r\n * </template>\r\n * ```\r\n */\r\nexport function useFocusTrap(options: UseFocusTrapOptions = {}): UseFocusTrapReturn {\r\n const { focusFirst = true, restoreFocus = true, initialFocus = null } = options\r\n\r\n const containerRef = ref<HTMLElement | null>(null)\r\n const isActive = ref(false)\r\n const previouslyFocusedElement = ref<HTMLElement | null>(null)\r\n\r\n function getFocusableElements(): HTMLElement[] {\r\n if (!containerRef.value) return []\r\n return Array.from(containerRef.value.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTORS)).filter(\r\n (el) => el.offsetParent !== null, // Element is visible\r\n )\r\n }\r\n\r\n function getInitialFocusElement(): HTMLElement | null {\r\n if (!containerRef.value) return null\r\n\r\n if (initialFocus) {\r\n if (typeof initialFocus === 'string') {\r\n return containerRef.value.querySelector<HTMLElement>(initialFocus)\r\n }\r\n return initialFocus\r\n }\r\n\r\n const focusable = getFocusableElements()\r\n return focusable[0] || null\r\n }\r\n\r\n function handleKeyDown(event: KeyboardEvent): void {\r\n if (event.key !== 'Tab' || !containerRef.value) return\r\n\r\n const focusable = getFocusableElements()\r\n if (focusable.length === 0) return\r\n\r\n const firstFocusable = focusable[0]\r\n const lastFocusable = focusable[focusable.length - 1]\r\n const activeElement = document.activeElement as HTMLElement\r\n\r\n if (event.shiftKey) {\r\n // Shift + Tab: move backwards\r\n if (activeElement === firstFocusable || !containerRef.value.contains(activeElement)) {\r\n event.preventDefault()\r\n lastFocusable.focus()\r\n }\r\n } else {\r\n // Tab: move forwards\r\n if (activeElement === lastFocusable || !containerRef.value.contains(activeElement)) {\r\n event.preventDefault()\r\n firstFocusable.focus()\r\n }\r\n }\r\n }\r\n\r\n function activate(): void {\r\n if (isActive.value) return\r\n\r\n // Store the currently focused element\r\n previouslyFocusedElement.value = document.activeElement as HTMLElement\r\n\r\n isActive.value = true\r\n\r\n // Add event listener\r\n document.addEventListener('keydown', handleKeyDown)\r\n\r\n // Focus initial element after a tick to ensure DOM is ready\r\n if (focusFirst) {\r\n requestAnimationFrame(() => {\r\n const initialElement = getInitialFocusElement()\r\n if (initialElement) {\r\n initialElement.focus()\r\n }\r\n })\r\n }\r\n }\r\n\r\n function deactivate(): void {\r\n if (!isActive.value) return\r\n\r\n isActive.value = false\r\n\r\n // Remove event listener\r\n document.removeEventListener('keydown', handleKeyDown)\r\n\r\n // Restore focus\r\n if (restoreFocus && previouslyFocusedElement.value) {\r\n previouslyFocusedElement.value.focus()\r\n previouslyFocusedElement.value = null\r\n }\r\n }\r\n\r\n // Handle reactive active option\r\n const activeOption = options.active\r\n if (activeOption !== undefined) {\r\n if (typeof activeOption === 'boolean') {\r\n if (activeOption) {\r\n // Wait for containerRef to be set\r\n const unwatch = watch(\r\n containerRef,\r\n (container) => {\r\n if (container) {\r\n activate()\r\n unwatch()\r\n }\r\n },\r\n { immediate: true },\r\n )\r\n }\r\n } else {\r\n // It's a Ref<boolean>\r\n watch(\r\n [activeOption, containerRef],\r\n ([active, container]) => {\r\n if (active && container) {\r\n activate()\r\n } else if (!active) {\r\n deactivate()\r\n }\r\n },\r\n { immediate: true },\r\n )\r\n }\r\n }\r\n\r\n // Cleanup on unmount (only when used inside a component)\r\n if (getCurrentInstance()) {\r\n onUnmounted(() => {\r\n deactivate()\r\n })\r\n }\r\n\r\n return {\r\n containerRef,\r\n activate,\r\n deactivate,\r\n isActive,\r\n }\r\n}\r\n"],"names":["ref","watch","getCurrentInstance","onUnmounted"],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ const vue = require("vue");
3
+ let idCounter = 0;
4
+ function generateId(prefix = "id") {
5
+ idCounter++;
6
+ return `cisse-${prefix}-${idCounter}`;
7
+ }
8
+ function resetIdCounter() {
9
+ idCounter = 0;
10
+ }
11
+ function useId(options = {}) {
12
+ const { prefix = "id", id: customId } = options;
13
+ const id = vue.ref(customId || generateId(prefix));
14
+ const related = (suffix) => {
15
+ return `${id.value}-${suffix}`;
16
+ };
17
+ return {
18
+ id,
19
+ related
20
+ };
21
+ }
22
+ exports.generateId = generateId;
23
+ exports.resetIdCounter = resetIdCounter;
24
+ exports.useId = useId;
25
+ //# sourceMappingURL=useId-nxrBaIC9.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useId-nxrBaIC9.cjs","sources":["../src/composables/useId.ts"],"sourcesContent":["import { ref, type Ref } from 'vue'\r\n\r\nlet idCounter = 0\r\n\r\n/**\r\n * Generates a unique ID for accessibility relationships (aria-labelledby, aria-describedby, etc.)\r\n * Pattern: cisse-{prefix}-{counter}\r\n */\r\nexport function generateId(prefix = 'id'): string {\r\n idCounter++\r\n return `cisse-${prefix}-${idCounter}`\r\n}\r\n\r\n/**\r\n * Resets the ID counter (useful for testing)\r\n */\r\nexport function resetIdCounter(): void {\r\n idCounter = 0\r\n}\r\n\r\nexport interface UseIdOptions {\r\n /** Prefix for the generated ID */\r\n prefix?: string\r\n /** Custom ID to use instead of generating one */\r\n id?: string\r\n}\r\n\r\nexport interface UseIdReturn {\r\n /** The unique ID (reactive) */\r\n id: Ref<string>\r\n /** Generate a related ID with a suffix (e.g., id-label, id-description) */\r\n related: (suffix: string) => string\r\n}\r\n\r\n/**\r\n * Composable for generating unique IDs for accessibility relationships\r\n *\r\n * @example\r\n * ```vue\r\n * <script setup>\r\n * const { id, related } = useId({ prefix: 'modal' })\r\n * // id.value = 'cisse-modal-1'\r\n * // related('title') = 'cisse-modal-1-title'\r\n * // related('description') = 'cisse-modal-1-description'\r\n * </script>\r\n *\r\n * <template>\r\n * <div :id=\"id\" role=\"dialog\" :aria-labelledby=\"related('title')\">\r\n * <h2 :id=\"related('title')\">Modal Title</h2>\r\n * </div>\r\n * </template>\r\n * ```\r\n */\r\nexport function useId(options: UseIdOptions = {}): UseIdReturn {\r\n const { prefix = 'id', id: customId } = options\r\n\r\n const id = ref(customId || generateId(prefix))\r\n\r\n const related = (suffix: string): string => {\r\n return `${id.value}-${suffix}`\r\n }\r\n\r\n return {\r\n id,\r\n related,\r\n }\r\n}\r\n"],"names":["ref"],"mappings":";;AAEA,IAAI,YAAY;AAMT,SAAS,WAAW,SAAS,MAAc;AAChD;AACA,SAAO,SAAS,MAAM,IAAI,SAAS;AACrC;AAKO,SAAS,iBAAuB;AACrC,cAAY;AACd;AAmCO,SAAS,MAAM,UAAwB,IAAiB;AAC7D,QAAM,EAAE,SAAS,MAAM,IAAI,aAAa;AAExC,QAAM,KAAKA,IAAAA,IAAI,YAAY,WAAW,MAAM,CAAC;AAE7C,QAAM,UAAU,CAAC,WAA2B;AAC1C,WAAO,GAAG,GAAG,KAAK,IAAI,MAAM;AAAA,EAC9B;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EAAA;AAEJ;;;;"}
@@ -0,0 +1,26 @@
1
+ import { ref } from "vue";
2
+ let idCounter = 0;
3
+ function generateId(prefix = "id") {
4
+ idCounter++;
5
+ return `cisse-${prefix}-${idCounter}`;
6
+ }
7
+ function resetIdCounter() {
8
+ idCounter = 0;
9
+ }
10
+ function useId(options = {}) {
11
+ const { prefix = "id", id: customId } = options;
12
+ const id = ref(customId || generateId(prefix));
13
+ const related = (suffix) => {
14
+ return `${id.value}-${suffix}`;
15
+ };
16
+ return {
17
+ id,
18
+ related
19
+ };
20
+ }
21
+ export {
22
+ generateId as g,
23
+ resetIdCounter as r,
24
+ useId as u
25
+ };
26
+ //# sourceMappingURL=useId-xeHj7rkg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useId-xeHj7rkg.js","sources":["../src/composables/useId.ts"],"sourcesContent":["import { ref, type Ref } from 'vue'\r\n\r\nlet idCounter = 0\r\n\r\n/**\r\n * Generates a unique ID for accessibility relationships (aria-labelledby, aria-describedby, etc.)\r\n * Pattern: cisse-{prefix}-{counter}\r\n */\r\nexport function generateId(prefix = 'id'): string {\r\n idCounter++\r\n return `cisse-${prefix}-${idCounter}`\r\n}\r\n\r\n/**\r\n * Resets the ID counter (useful for testing)\r\n */\r\nexport function resetIdCounter(): void {\r\n idCounter = 0\r\n}\r\n\r\nexport interface UseIdOptions {\r\n /** Prefix for the generated ID */\r\n prefix?: string\r\n /** Custom ID to use instead of generating one */\r\n id?: string\r\n}\r\n\r\nexport interface UseIdReturn {\r\n /** The unique ID (reactive) */\r\n id: Ref<string>\r\n /** Generate a related ID with a suffix (e.g., id-label, id-description) */\r\n related: (suffix: string) => string\r\n}\r\n\r\n/**\r\n * Composable for generating unique IDs for accessibility relationships\r\n *\r\n * @example\r\n * ```vue\r\n * <script setup>\r\n * const { id, related } = useId({ prefix: 'modal' })\r\n * // id.value = 'cisse-modal-1'\r\n * // related('title') = 'cisse-modal-1-title'\r\n * // related('description') = 'cisse-modal-1-description'\r\n * </script>\r\n *\r\n * <template>\r\n * <div :id=\"id\" role=\"dialog\" :aria-labelledby=\"related('title')\">\r\n * <h2 :id=\"related('title')\">Modal Title</h2>\r\n * </div>\r\n * </template>\r\n * ```\r\n */\r\nexport function useId(options: UseIdOptions = {}): UseIdReturn {\r\n const { prefix = 'id', id: customId } = options\r\n\r\n const id = ref(customId || generateId(prefix))\r\n\r\n const related = (suffix: string): string => {\r\n return `${id.value}-${suffix}`\r\n }\r\n\r\n return {\r\n id,\r\n related,\r\n }\r\n}\r\n"],"names":[],"mappings":";AAEA,IAAI,YAAY;AAMT,SAAS,WAAW,SAAS,MAAc;AAChD;AACA,SAAO,SAAS,MAAM,IAAI,SAAS;AACrC;AAKO,SAAS,iBAAuB;AACrC,cAAY;AACd;AAmCO,SAAS,MAAM,UAAwB,IAAiB;AAC7D,QAAM,EAAE,SAAS,MAAM,IAAI,aAAa;AAExC,QAAM,KAAK,IAAI,YAAY,WAAW,MAAM,CAAC;AAE7C,QAAM,UAAU,CAAC,WAA2B;AAC1C,WAAO,GAAG,GAAG,KAAK,IAAI,MAAM;AAAA,EAC9B;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EAAA;AAEJ;"}
@@ -49,54 +49,6 @@ function useNotifications() {
49
49
  clear
50
50
  };
51
51
  }
52
- function useDarkMode(options = {}) {
53
- const {
54
- selector = "html",
55
- attribute = "class",
56
- storageKey = "dark-mode",
57
- defaultValue = false
58
- } = options;
59
- const isDark = vue.ref(defaultValue);
60
- const getInitialValue = () => {
61
- if (typeof window === "undefined") return defaultValue;
62
- const stored = localStorage.getItem(storageKey);
63
- if (stored !== null) {
64
- return stored === "true";
65
- }
66
- return window.matchMedia("(prefers-color-scheme: dark)").matches;
67
- };
68
- const updateDOM = (dark) => {
69
- if (typeof document === "undefined") return;
70
- const element = document.querySelector(selector);
71
- if (!element) return;
72
- if (attribute === "class") {
73
- element.classList.toggle("dark", dark);
74
- } else {
75
- element.setAttribute(attribute, dark ? "dark" : "light");
76
- }
77
- };
78
- const toggle = () => {
79
- isDark.value = !isDark.value;
80
- };
81
- const set = (value) => {
82
- isDark.value = value;
83
- };
84
- vue.watch(isDark, (newValue) => {
85
- updateDOM(newValue);
86
- if (typeof localStorage !== "undefined") {
87
- localStorage.setItem(storageKey, String(newValue));
88
- }
89
- });
90
- vue.onMounted(() => {
91
- isDark.value = getInitialValue();
92
- updateDOM(isDark.value);
93
- });
94
- return {
95
- isDark,
96
- toggle,
97
- set
98
- };
99
- }
100
52
  function useExportCSV() {
101
53
  const escapeCSV = (value) => {
102
54
  if (value === null || value === void 0) return "";
@@ -216,10 +168,9 @@ function useToast() {
216
168
  info
217
169
  };
218
170
  }
219
- exports.useDarkMode = useDarkMode;
220
171
  exports.useExportCSV = useExportCSV;
221
172
  exports.useModal = useModal;
222
173
  exports.useModals = useModals;
223
174
  exports.useNotifications = useNotifications;
224
175
  exports.useToast = useToast;
225
- //# sourceMappingURL=useToast-CRh_sG82.cjs.map
176
+ //# sourceMappingURL=useToast-Bk60GArg.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useToast-Bk60GArg.cjs","sources":["../node_modules/uid/dist/index.mjs","../src/composables/useNotifications.ts","../src/composables/useExportCSV.ts","../src/composables/useModal.ts","../src/composables/useToast.ts"],"sourcesContent":["var IDX=256, HEX=[], SIZE=256, BUFFER;\nwhile (IDX--) HEX[IDX] = (IDX + 256).toString(16).substring(1);\n\nexport function uid(len) {\n\tvar i=0, tmp=(len || 11);\n\tif (!BUFFER || ((IDX + tmp) > SIZE*2)) {\n\t\tfor (BUFFER='',IDX=0; i < SIZE; i++) {\n\t\t\tBUFFER += HEX[Math.random() * 256 | 0];\n\t\t}\n\t}\n\n\treturn BUFFER.substring(IDX, IDX++ + tmp);\n}\n","import { ref, readonly } from 'vue'\r\nimport { uid } from 'uid'\r\nimport type { Notification, NotificationType, NotificationOptions } from '@/types'\r\n\r\n// Global state (singleton pattern) - shared across all useNotifications() calls\r\nconst notifications = ref<Notification[]>([])\r\n\r\n/**\r\n * Composable for managing notifications/toasts\r\n * Uses singleton pattern - all components share the same notifications state\r\n */\r\nexport function useNotifications() {\r\n\r\n const notify = (\r\n type: NotificationType,\r\n message: string,\r\n options: NotificationOptions = {},\r\n ): string => {\r\n const id = uid()\r\n const notification: Notification = {\r\n id,\r\n type,\r\n message,\r\n title: options.title ?? null,\r\n duration: options.duration ?? 5000,\r\n }\r\n\r\n notifications.value.push(notification)\r\n\r\n if (notification.duration && notification.duration > 0) {\r\n setTimeout(() => remove(id), notification.duration)\r\n }\r\n\r\n return id\r\n }\r\n\r\n const success = (message: string, options?: NotificationOptions) =>\r\n notify('success', message, options)\r\n\r\n const warning = (message: string, options?: NotificationOptions) =>\r\n notify('warning', message, options)\r\n\r\n const error = (message: string, options?: NotificationOptions) =>\r\n notify('error', message, options)\r\n\r\n const info = (message: string, options?: NotificationOptions) =>\r\n notify('info', message, options)\r\n\r\n const remove = (id: string) => {\r\n notifications.value = notifications.value.filter((n) => n.id !== id)\r\n }\r\n\r\n const clear = () => {\r\n notifications.value = []\r\n }\r\n\r\n return {\r\n notifications: readonly(notifications),\r\n notify,\r\n success,\r\n warning,\r\n error,\r\n info,\r\n remove,\r\n clear,\r\n }\r\n}\r\n","/**\n * Composable for exporting data to CSV format\n */\nexport function useExportCSV() {\n const escapeCSV = (value: unknown): string => {\n if (value === null || value === undefined) return ''\n const str = String(value)\n if (str.includes(',') || str.includes('\"') || str.includes('\\n')) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`\n }\n return str\n }\n\n const exportToCSV = <T extends Record<string, unknown>>(\n data: T[],\n columns: { key: keyof T; label: string }[],\n filename: string = 'export.csv',\n ) => {\n if (!data || data.length === 0) {\n console.warn('No data to export')\n return\n }\n\n // Create header row\n const headers = columns.map((col) => escapeCSV(col.label)).join(',')\n\n // Create data rows\n const rows = data.map((item) =>\n columns.map((col) => escapeCSV(item[col.key])).join(','),\n )\n\n // Combine header and rows\n const csv = [headers, ...rows].join('\\n')\n\n // Create and trigger download\n const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' })\n const url = URL.createObjectURL(blob)\n const link = document.createElement('a')\n link.setAttribute('href', url)\n link.setAttribute('download', filename)\n link.style.visibility = 'hidden'\n document.body.appendChild(link)\n link.click()\n document.body.removeChild(link)\n URL.revokeObjectURL(url)\n }\n\n return {\n exportToCSV,\n escapeCSV,\n }\n}\n","import { ref, type Ref } from 'vue'\r\n\r\nexport interface UseModalReturn<T = unknown> {\r\n /** Whether the modal is currently open */\r\n isOpen: Ref<boolean>\r\n /** Data associated with the modal (e.g., item being edited) */\r\n data: Ref<T | null>\r\n /** Open the modal, optionally with data */\r\n open: (newData?: T) => void\r\n /** Close the modal and clear data */\r\n close: () => void\r\n /** Toggle the modal state */\r\n toggle: () => void\r\n}\r\n\r\n/**\r\n * Composable for managing modal state\r\n *\r\n * @example\r\n * ```ts\r\n * // Simple modal\r\n * const createModal = useModal()\r\n * createModal.open()\r\n * createModal.close()\r\n *\r\n * // Modal with data (e.g., for editing)\r\n * const editModal = useModal<User>()\r\n * editModal.open(selectedUser)\r\n * // Access editModal.data.value in modal\r\n *\r\n * // With onClose callback\r\n * const deleteModal = useModal<Item>({ onClose: () => refetch() })\r\n * ```\r\n */\r\nexport function useModal<T = unknown>(options?: {\r\n /** Initial open state */\r\n initialOpen?: boolean\r\n /** Initial data */\r\n initialData?: T | null\r\n /** Callback when modal opens */\r\n onOpen?: (data: T | null) => void\r\n /** Callback when modal closes */\r\n onClose?: () => void\r\n}): UseModalReturn<T> {\r\n const {\r\n initialOpen = false,\r\n initialData = null,\r\n onOpen,\r\n onClose,\r\n } = options ?? {}\r\n\r\n const isOpen = ref(initialOpen)\r\n const data = ref<T | null>(initialData) as Ref<T | null>\r\n\r\n const open = (newData?: T) => {\r\n data.value = newData ?? null\r\n isOpen.value = true\r\n onOpen?.(data.value)\r\n }\r\n\r\n const close = () => {\r\n isOpen.value = false\r\n data.value = null\r\n onClose?.()\r\n }\r\n\r\n const toggle = () => {\r\n if (isOpen.value) {\r\n close()\r\n } else {\r\n open()\r\n }\r\n }\r\n\r\n return {\r\n isOpen,\r\n data,\r\n open,\r\n close,\r\n toggle,\r\n }\r\n}\r\n\r\n/**\r\n * Create multiple related modals at once\r\n * Useful when a page has several modals (create, edit, delete, etc.)\r\n *\r\n * @example\r\n * ```ts\r\n * const modals = useModals({\r\n * create: useModal(),\r\n * edit: useModal<User>(),\r\n * delete: useModal<User>(),\r\n * })\r\n *\r\n * modals.create.open()\r\n * modals.edit.open(user)\r\n * modals.delete.close()\r\n * ```\r\n */\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nexport function useModals<T extends Record<string, UseModalReturn<any>>>(\r\n modals: T\r\n): T {\r\n return modals\r\n}\r\n","import { ref } from 'vue'\r\nimport type { ToastType } from '@/components/feedback/Toast.vue'\r\nimport type { ToastItem } from '@/components/feedback/ToastContainer.vue'\r\n\r\nexport interface ToastOptions {\r\n message: string\r\n type?: ToastType\r\n title?: string\r\n duration?: number\r\n}\r\n\r\nconst toasts = ref<ToastItem[]>([])\r\n\r\nlet toastId = 0\r\n\r\nexport function useToast() {\r\n const add = (options: ToastOptions): string => {\r\n const id = `toast-${++toastId}`\r\n const toast: ToastItem = {\r\n id,\r\n message: options.message,\r\n type: options.type || 'info',\r\n title: options.title,\r\n duration: options.duration ?? 5000,\r\n }\r\n toasts.value.push(toast)\r\n return id\r\n }\r\n\r\n const remove = (id: string) => {\r\n const index = toasts.value.findIndex((t) => t.id === id)\r\n if (index > -1) {\r\n toasts.value.splice(index, 1)\r\n }\r\n }\r\n\r\n const clear = () => {\r\n toasts.value = []\r\n }\r\n\r\n const success = (message: string, title?: string) => {\r\n return add({ message, title, type: 'success' })\r\n }\r\n\r\n const error = (message: string, title?: string) => {\r\n return add({ message, title, type: 'error' })\r\n }\r\n\r\n const warning = (message: string, title?: string) => {\r\n return add({ message, title, type: 'warning' })\r\n }\r\n\r\n const info = (message: string, title?: string) => {\r\n return add({ message, title, type: 'info' })\r\n }\r\n\r\n return {\r\n toasts,\r\n add,\r\n remove,\r\n clear,\r\n success,\r\n error,\r\n warning,\r\n info,\r\n }\r\n}\r\n"],"names":["ref","readonly"],"mappings":"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","x_google_ignoreList":[0]}
@@ -1,4 +1,4 @@
1
- import { readonly, ref, watch, onMounted } from "vue";
1
+ import { readonly, ref } from "vue";
2
2
  var IDX = 256, HEX = [], SIZE = 256, BUFFER;
3
3
  while (IDX--) HEX[IDX] = (IDX + 256).toString(16).substring(1);
4
4
  function uid(len) {
@@ -48,54 +48,6 @@ function useNotifications() {
48
48
  clear
49
49
  };
50
50
  }
51
- function useDarkMode(options = {}) {
52
- const {
53
- selector = "html",
54
- attribute = "class",
55
- storageKey = "dark-mode",
56
- defaultValue = false
57
- } = options;
58
- const isDark = ref(defaultValue);
59
- const getInitialValue = () => {
60
- if (typeof window === "undefined") return defaultValue;
61
- const stored = localStorage.getItem(storageKey);
62
- if (stored !== null) {
63
- return stored === "true";
64
- }
65
- return window.matchMedia("(prefers-color-scheme: dark)").matches;
66
- };
67
- const updateDOM = (dark) => {
68
- if (typeof document === "undefined") return;
69
- const element = document.querySelector(selector);
70
- if (!element) return;
71
- if (attribute === "class") {
72
- element.classList.toggle("dark", dark);
73
- } else {
74
- element.setAttribute(attribute, dark ? "dark" : "light");
75
- }
76
- };
77
- const toggle = () => {
78
- isDark.value = !isDark.value;
79
- };
80
- const set = (value) => {
81
- isDark.value = value;
82
- };
83
- watch(isDark, (newValue) => {
84
- updateDOM(newValue);
85
- if (typeof localStorage !== "undefined") {
86
- localStorage.setItem(storageKey, String(newValue));
87
- }
88
- });
89
- onMounted(() => {
90
- isDark.value = getInitialValue();
91
- updateDOM(isDark.value);
92
- });
93
- return {
94
- isDark,
95
- toggle,
96
- set
97
- };
98
- }
99
51
  function useExportCSV() {
100
52
  const escapeCSV = (value) => {
101
53
  if (value === null || value === void 0) return "";
@@ -216,11 +168,10 @@ function useToast() {
216
168
  };
217
169
  }
218
170
  export {
219
- useDarkMode as a,
220
- useExportCSV as b,
221
- useModal as c,
222
- useModals as d,
223
- useToast as e,
171
+ useExportCSV as a,
172
+ useModal as b,
173
+ useModals as c,
174
+ useToast as d,
224
175
  useNotifications as u
225
176
  };
226
- //# sourceMappingURL=useToast-DwFOkewC.js.map
177
+ //# sourceMappingURL=useToast-ina5g3mj.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useToast-ina5g3mj.js","sources":["../node_modules/uid/dist/index.mjs","../src/composables/useNotifications.ts","../src/composables/useExportCSV.ts","../src/composables/useModal.ts","../src/composables/useToast.ts"],"sourcesContent":["var IDX=256, HEX=[], SIZE=256, BUFFER;\nwhile (IDX--) HEX[IDX] = (IDX + 256).toString(16).substring(1);\n\nexport function uid(len) {\n\tvar i=0, tmp=(len || 11);\n\tif (!BUFFER || ((IDX + tmp) > SIZE*2)) {\n\t\tfor (BUFFER='',IDX=0; i < SIZE; i++) {\n\t\t\tBUFFER += HEX[Math.random() * 256 | 0];\n\t\t}\n\t}\n\n\treturn BUFFER.substring(IDX, IDX++ + tmp);\n}\n","import { ref, readonly } from 'vue'\r\nimport { uid } from 'uid'\r\nimport type { Notification, NotificationType, NotificationOptions } from '@/types'\r\n\r\n// Global state (singleton pattern) - shared across all useNotifications() calls\r\nconst notifications = ref<Notification[]>([])\r\n\r\n/**\r\n * Composable for managing notifications/toasts\r\n * Uses singleton pattern - all components share the same notifications state\r\n */\r\nexport function useNotifications() {\r\n\r\n const notify = (\r\n type: NotificationType,\r\n message: string,\r\n options: NotificationOptions = {},\r\n ): string => {\r\n const id = uid()\r\n const notification: Notification = {\r\n id,\r\n type,\r\n message,\r\n title: options.title ?? null,\r\n duration: options.duration ?? 5000,\r\n }\r\n\r\n notifications.value.push(notification)\r\n\r\n if (notification.duration && notification.duration > 0) {\r\n setTimeout(() => remove(id), notification.duration)\r\n }\r\n\r\n return id\r\n }\r\n\r\n const success = (message: string, options?: NotificationOptions) =>\r\n notify('success', message, options)\r\n\r\n const warning = (message: string, options?: NotificationOptions) =>\r\n notify('warning', message, options)\r\n\r\n const error = (message: string, options?: NotificationOptions) =>\r\n notify('error', message, options)\r\n\r\n const info = (message: string, options?: NotificationOptions) =>\r\n notify('info', message, options)\r\n\r\n const remove = (id: string) => {\r\n notifications.value = notifications.value.filter((n) => n.id !== id)\r\n }\r\n\r\n const clear = () => {\r\n notifications.value = []\r\n }\r\n\r\n return {\r\n notifications: readonly(notifications),\r\n notify,\r\n success,\r\n warning,\r\n error,\r\n info,\r\n remove,\r\n clear,\r\n }\r\n}\r\n","/**\n * Composable for exporting data to CSV format\n */\nexport function useExportCSV() {\n const escapeCSV = (value: unknown): string => {\n if (value === null || value === undefined) return ''\n const str = String(value)\n if (str.includes(',') || str.includes('\"') || str.includes('\\n')) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`\n }\n return str\n }\n\n const exportToCSV = <T extends Record<string, unknown>>(\n data: T[],\n columns: { key: keyof T; label: string }[],\n filename: string = 'export.csv',\n ) => {\n if (!data || data.length === 0) {\n console.warn('No data to export')\n return\n }\n\n // Create header row\n const headers = columns.map((col) => escapeCSV(col.label)).join(',')\n\n // Create data rows\n const rows = data.map((item) =>\n columns.map((col) => escapeCSV(item[col.key])).join(','),\n )\n\n // Combine header and rows\n const csv = [headers, ...rows].join('\\n')\n\n // Create and trigger download\n const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' })\n const url = URL.createObjectURL(blob)\n const link = document.createElement('a')\n link.setAttribute('href', url)\n link.setAttribute('download', filename)\n link.style.visibility = 'hidden'\n document.body.appendChild(link)\n link.click()\n document.body.removeChild(link)\n URL.revokeObjectURL(url)\n }\n\n return {\n exportToCSV,\n escapeCSV,\n }\n}\n","import { ref, type Ref } from 'vue'\r\n\r\nexport interface UseModalReturn<T = unknown> {\r\n /** Whether the modal is currently open */\r\n isOpen: Ref<boolean>\r\n /** Data associated with the modal (e.g., item being edited) */\r\n data: Ref<T | null>\r\n /** Open the modal, optionally with data */\r\n open: (newData?: T) => void\r\n /** Close the modal and clear data */\r\n close: () => void\r\n /** Toggle the modal state */\r\n toggle: () => void\r\n}\r\n\r\n/**\r\n * Composable for managing modal state\r\n *\r\n * @example\r\n * ```ts\r\n * // Simple modal\r\n * const createModal = useModal()\r\n * createModal.open()\r\n * createModal.close()\r\n *\r\n * // Modal with data (e.g., for editing)\r\n * const editModal = useModal<User>()\r\n * editModal.open(selectedUser)\r\n * // Access editModal.data.value in modal\r\n *\r\n * // With onClose callback\r\n * const deleteModal = useModal<Item>({ onClose: () => refetch() })\r\n * ```\r\n */\r\nexport function useModal<T = unknown>(options?: {\r\n /** Initial open state */\r\n initialOpen?: boolean\r\n /** Initial data */\r\n initialData?: T | null\r\n /** Callback when modal opens */\r\n onOpen?: (data: T | null) => void\r\n /** Callback when modal closes */\r\n onClose?: () => void\r\n}): UseModalReturn<T> {\r\n const {\r\n initialOpen = false,\r\n initialData = null,\r\n onOpen,\r\n onClose,\r\n } = options ?? {}\r\n\r\n const isOpen = ref(initialOpen)\r\n const data = ref<T | null>(initialData) as Ref<T | null>\r\n\r\n const open = (newData?: T) => {\r\n data.value = newData ?? null\r\n isOpen.value = true\r\n onOpen?.(data.value)\r\n }\r\n\r\n const close = () => {\r\n isOpen.value = false\r\n data.value = null\r\n onClose?.()\r\n }\r\n\r\n const toggle = () => {\r\n if (isOpen.value) {\r\n close()\r\n } else {\r\n open()\r\n }\r\n }\r\n\r\n return {\r\n isOpen,\r\n data,\r\n open,\r\n close,\r\n toggle,\r\n }\r\n}\r\n\r\n/**\r\n * Create multiple related modals at once\r\n * Useful when a page has several modals (create, edit, delete, etc.)\r\n *\r\n * @example\r\n * ```ts\r\n * const modals = useModals({\r\n * create: useModal(),\r\n * edit: useModal<User>(),\r\n * delete: useModal<User>(),\r\n * })\r\n *\r\n * modals.create.open()\r\n * modals.edit.open(user)\r\n * modals.delete.close()\r\n * ```\r\n */\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nexport function useModals<T extends Record<string, UseModalReturn<any>>>(\r\n modals: T\r\n): T {\r\n return modals\r\n}\r\n","import { ref } from 'vue'\r\nimport type { ToastType } from '@/components/feedback/Toast.vue'\r\nimport type { ToastItem } from '@/components/feedback/ToastContainer.vue'\r\n\r\nexport interface ToastOptions {\r\n message: string\r\n type?: ToastType\r\n title?: string\r\n duration?: number\r\n}\r\n\r\nconst toasts = ref<ToastItem[]>([])\r\n\r\nlet toastId = 0\r\n\r\nexport function useToast() {\r\n const add = (options: ToastOptions): string => {\r\n const id = `toast-${++toastId}`\r\n const toast: ToastItem = {\r\n id,\r\n message: options.message,\r\n type: options.type || 'info',\r\n title: options.title,\r\n duration: options.duration ?? 5000,\r\n }\r\n toasts.value.push(toast)\r\n return id\r\n }\r\n\r\n const remove = (id: string) => {\r\n const index = toasts.value.findIndex((t) => t.id === id)\r\n if (index > -1) {\r\n toasts.value.splice(index, 1)\r\n }\r\n }\r\n\r\n const clear = () => {\r\n toasts.value = []\r\n }\r\n\r\n const success = (message: string, title?: string) => {\r\n return add({ message, title, type: 'success' })\r\n }\r\n\r\n const error = (message: string, title?: string) => {\r\n return add({ message, title, type: 'error' })\r\n }\r\n\r\n const warning = (message: string, title?: string) => {\r\n return add({ message, title, type: 'warning' })\r\n }\r\n\r\n const info = (message: string, title?: string) => {\r\n return add({ message, title, type: 'info' })\r\n }\r\n\r\n return {\r\n toasts,\r\n add,\r\n remove,\r\n clear,\r\n success,\r\n error,\r\n warning,\r\n info,\r\n }\r\n}\r\n"],"names":[],"mappings":"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","x_google_ignoreList":[0]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cisse-vue-ui",
3
- "version": "0.5.21",
3
+ "version": "0.5.23",
4
4
  "description": "Vue 3 + TypeScript + Tailwind CSS v4 component library",
5
5
  "author": "Cisse",
6
6
  "license": "MIT",
@@ -98,7 +98,7 @@
98
98
  "build:css": "bunx @tailwindcss/cli -i ./src/styles/components.css -o ./dist/style.css --minify",
99
99
  "build:watch": "vite build --watch",
100
100
  "preview": "vite preview",
101
- "test": "vitest --config vitest.config.ts",
101
+ "test": "vitest --project unit",
102
102
  "test:storybook": "vitest --project storybook",
103
103
  "type-check": "vue-tsc --noEmit",
104
104
  "lint": "eslint . --fix",
@@ -124,10 +124,11 @@
124
124
  "@chromatic-com/storybook": "^4.1.3",
125
125
  "@eslint/js": "^9.39.1",
126
126
  "@iconify/vue": "^5.0.0",
127
- "@storybook/addon-a11y": "^10.1.6",
128
- "@storybook/addon-docs": "^10.1.6",
129
- "@storybook/addon-vitest": "^10.1.6",
130
- "@storybook/vue3-vite": "^10.1.6",
127
+ "@storybook/addon-a11y": "^10.1.10",
128
+ "@storybook/addon-docs": "^10.1.10",
129
+ "@storybook/addon-themes": "^10.1.10",
130
+ "@storybook/addon-vitest": "^10.1.10",
131
+ "@storybook/vue3-vite": "^10.1.10",
131
132
  "@tailwindcss/vite": "^4.1.17",
132
133
  "@types/node": "^22.19.1",
133
134
  "@vitejs/plugin-vue": "^6.0.2",
@@ -137,14 +138,14 @@
137
138
  "@vue/tsconfig": "^0.8.1",
138
139
  "ajv": "^8.17.1",
139
140
  "eslint": "^9.39.1",
140
- "eslint-plugin-storybook": "^10.1.6",
141
+ "eslint-plugin-storybook": "^10.1.10",
141
142
  "eslint-plugin-vue": "^10.6.2",
142
143
  "gh-pages": "^6.3.0",
143
144
  "globals": "^16.5.0",
144
145
  "happy-dom": "^20.0.11",
145
146
  "pinia": "^3.0.4",
146
147
  "playwright": "^1.57.0",
147
- "storybook": "^10.1.6",
148
+ "storybook": "^10.1.10",
148
149
  "tailwindcss": "^4.1.17",
149
150
  "typescript": "~5.9.3",
150
151
  "typescript-eslint": "^8.49.0",
@@ -1,54 +0,0 @@
1
- import { defineComponent, createElementBlock, openBlock, normalizeClass, createElementVNode, createCommentVNode, toDisplayString } from "vue";
2
- const _hoisted_1 = ["checked", "disabled", "indeterminate"];
3
- const _hoisted_2 = {
4
- key: 0,
5
- class: "flex flex-col"
6
- };
7
- const _hoisted_3 = {
8
- key: 0,
9
- class: "text-sm font-medium text-gray-900 dark:text-white"
10
- };
11
- const _hoisted_4 = {
12
- key: 1,
13
- class: "text-sm text-gray-500 dark:text-gray-400"
14
- };
15
- const _sfc_main = /* @__PURE__ */ defineComponent({
16
- __name: "Checkbox",
17
- props: {
18
- modelValue: { type: Boolean, default: false },
19
- label: {},
20
- description: {},
21
- disabled: { type: Boolean },
22
- indeterminate: { type: Boolean }
23
- },
24
- emits: ["update:modelValue"],
25
- setup(__props, { emit: __emit }) {
26
- const emit = __emit;
27
- const toggle = (event) => {
28
- const target = event.target;
29
- emit("update:modelValue", target.checked);
30
- };
31
- return (_ctx, _cache) => {
32
- return openBlock(), createElementBlock("label", {
33
- class: normalizeClass(["inline-flex items-start gap-3", __props.disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer"])
34
- }, [
35
- createElementVNode("input", {
36
- type: "checkbox",
37
- checked: __props.modelValue,
38
- disabled: __props.disabled,
39
- indeterminate: __props.indeterminate,
40
- class: "mt-0.5 size-4 rounded border-gray-300 text-primary/90 focus:ring-2 focus:ring-primary focus:ring-offset-2 disabled:cursor-not-allowed dark:border-gray-600 dark:bg-gray-800 dark:focus:ring-offset-gray-900",
41
- onChange: toggle
42
- }, null, 40, _hoisted_1),
43
- __props.label || __props.description ? (openBlock(), createElementBlock("div", _hoisted_2, [
44
- __props.label ? (openBlock(), createElementBlock("span", _hoisted_3, toDisplayString(__props.label), 1)) : createCommentVNode("", true),
45
- __props.description ? (openBlock(), createElementBlock("span", _hoisted_4, toDisplayString(__props.description), 1)) : createCommentVNode("", true)
46
- ])) : createCommentVNode("", true)
47
- ], 2);
48
- };
49
- }
50
- });
51
- export {
52
- _sfc_main as _
53
- };
54
- //# sourceMappingURL=Checkbox.vue_vue_type_script_setup_true_lang-B-nLCCNY.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Checkbox.vue_vue_type_script_setup_true_lang-B-nLCCNY.js","sources":["../src/components/form/Checkbox.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nwithDefaults(\n defineProps<{\n /** v-model value */\n modelValue?: boolean\n /** Label text */\n label?: string\n /** Description text */\n description?: string\n /** Disabled state */\n disabled?: boolean\n /** Indeterminate state */\n indeterminate?: boolean\n }>(),\n {\n modelValue: false,\n },\n)\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n}>()\n\nconst toggle = (event: Event) => {\n const target = event.target as HTMLInputElement\n emit('update:modelValue', target.checked)\n}\n</script>\n\n<template>\n <label\n class=\"inline-flex items-start gap-3\"\n :class=\"disabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer'\"\n >\n <input\n type=\"checkbox\"\n :checked=\"modelValue\"\n :disabled=\"disabled\"\n :indeterminate=\"indeterminate\"\n class=\"mt-0.5 size-4 rounded border-gray-300 text-primary/90 focus:ring-2 focus:ring-primary focus:ring-offset-2 disabled:cursor-not-allowed dark:border-gray-600 dark:bg-gray-800 dark:focus:ring-offset-gray-900\"\n @change=\"toggle\"\n >\n <div\n v-if=\"label || description\"\n class=\"flex flex-col\"\n >\n <span\n v-if=\"label\"\n class=\"text-sm font-medium text-gray-900 dark:text-white\"\n >\n {{ label }}\n </span>\n <span\n v-if=\"description\"\n class=\"text-sm text-gray-500 dark:text-gray-400\"\n >\n {{ description }}\n </span>\n </div>\n </label>\n</template>\n"],"names":["_createElementBlock","_normalizeClass","_createElementVNode","_openBlock","_toDisplayString"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAmBA,UAAM,OAAO;AAIb,UAAM,SAAS,CAAC,UAAiB;AAC/B,YAAM,SAAS,MAAM;AACrB,WAAK,qBAAqB,OAAO,OAAO;AAAA,IAC1C;;0BAIEA,mBA6BQ,SAAA;AAAA,QA5BN,OAAKC,eAAA,CAAC,iCACE,QAAA,WAAQ,kCAAA,gBAAA,CAAA;AAAA,MAAA;QAEhBC,mBAOC,SAAA;AAAA,UANC,MAAK;AAAA,UACJ,SAAS,QAAA;AAAA,UACT,UAAU,QAAA;AAAA,UACV,eAAe,QAAA;AAAA,UAChB,OAAM;AAAA,UACL,UAAQ;AAAA,QAAA;QAGH,QAAA,SAAS,QAAA,eADjBC,aAAAH,mBAgBM,OAhBN,YAgBM;AAAA,UAXI,QAAA,sBADRA,mBAKO,QALP,YAKOI,gBADF,QAAA,KAAK,GAAA,CAAA;UAGF,QAAA,4BADRJ,mBAKO,QALP,YAKOI,gBADF,QAAA,WAAW,GAAA,CAAA;;;;;;"}
@@ -1,53 +0,0 @@
1
- "use strict";
2
- const vue = require("vue");
3
- const _hoisted_1 = ["checked", "disabled", "indeterminate"];
4
- const _hoisted_2 = {
5
- key: 0,
6
- class: "flex flex-col"
7
- };
8
- const _hoisted_3 = {
9
- key: 0,
10
- class: "text-sm font-medium text-gray-900 dark:text-white"
11
- };
12
- const _hoisted_4 = {
13
- key: 1,
14
- class: "text-sm text-gray-500 dark:text-gray-400"
15
- };
16
- const _sfc_main = /* @__PURE__ */ vue.defineComponent({
17
- __name: "Checkbox",
18
- props: {
19
- modelValue: { type: Boolean, default: false },
20
- label: {},
21
- description: {},
22
- disabled: { type: Boolean },
23
- indeterminate: { type: Boolean }
24
- },
25
- emits: ["update:modelValue"],
26
- setup(__props, { emit: __emit }) {
27
- const emit = __emit;
28
- const toggle = (event) => {
29
- const target = event.target;
30
- emit("update:modelValue", target.checked);
31
- };
32
- return (_ctx, _cache) => {
33
- return vue.openBlock(), vue.createElementBlock("label", {
34
- class: vue.normalizeClass(["inline-flex items-start gap-3", __props.disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer"])
35
- }, [
36
- vue.createElementVNode("input", {
37
- type: "checkbox",
38
- checked: __props.modelValue,
39
- disabled: __props.disabled,
40
- indeterminate: __props.indeterminate,
41
- class: "mt-0.5 size-4 rounded border-gray-300 text-primary/90 focus:ring-2 focus:ring-primary focus:ring-offset-2 disabled:cursor-not-allowed dark:border-gray-600 dark:bg-gray-800 dark:focus:ring-offset-gray-900",
42
- onChange: toggle
43
- }, null, 40, _hoisted_1),
44
- __props.label || __props.description ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2, [
45
- __props.label ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_3, vue.toDisplayString(__props.label), 1)) : vue.createCommentVNode("", true),
46
- __props.description ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_4, vue.toDisplayString(__props.description), 1)) : vue.createCommentVNode("", true)
47
- ])) : vue.createCommentVNode("", true)
48
- ], 2);
49
- };
50
- }
51
- });
52
- exports._sfc_main = _sfc_main;
53
- //# sourceMappingURL=Checkbox.vue_vue_type_script_setup_true_lang-DIoHDji4.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Checkbox.vue_vue_type_script_setup_true_lang-DIoHDji4.cjs","sources":["../src/components/form/Checkbox.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nwithDefaults(\n defineProps<{\n /** v-model value */\n modelValue?: boolean\n /** Label text */\n label?: string\n /** Description text */\n description?: string\n /** Disabled state */\n disabled?: boolean\n /** Indeterminate state */\n indeterminate?: boolean\n }>(),\n {\n modelValue: false,\n },\n)\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n}>()\n\nconst toggle = (event: Event) => {\n const target = event.target as HTMLInputElement\n emit('update:modelValue', target.checked)\n}\n</script>\n\n<template>\n <label\n class=\"inline-flex items-start gap-3\"\n :class=\"disabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer'\"\n >\n <input\n type=\"checkbox\"\n :checked=\"modelValue\"\n :disabled=\"disabled\"\n :indeterminate=\"indeterminate\"\n class=\"mt-0.5 size-4 rounded border-gray-300 text-primary/90 focus:ring-2 focus:ring-primary focus:ring-offset-2 disabled:cursor-not-allowed dark:border-gray-600 dark:bg-gray-800 dark:focus:ring-offset-gray-900\"\n @change=\"toggle\"\n >\n <div\n v-if=\"label || description\"\n class=\"flex flex-col\"\n >\n <span\n v-if=\"label\"\n class=\"text-sm font-medium text-gray-900 dark:text-white\"\n >\n {{ label }}\n </span>\n <span\n v-if=\"description\"\n class=\"text-sm text-gray-500 dark:text-gray-400\"\n >\n {{ description }}\n </span>\n </div>\n </label>\n</template>\n"],"names":["_createElementBlock","_normalizeClass","_createElementVNode","_openBlock","_toDisplayString"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAmBA,UAAM,OAAO;AAIb,UAAM,SAAS,CAAC,UAAiB;AAC/B,YAAM,SAAS,MAAM;AACrB,WAAK,qBAAqB,OAAO,OAAO;AAAA,IAC1C;;8BAIEA,IAAAA,mBA6BQ,SAAA;AAAA,QA5BN,OAAKC,IAAAA,eAAA,CAAC,iCACE,QAAA,WAAQ,kCAAA,gBAAA,CAAA;AAAA,MAAA;QAEhBC,IAAAA,mBAOC,SAAA;AAAA,UANC,MAAK;AAAA,UACJ,SAAS,QAAA;AAAA,UACT,UAAU,QAAA;AAAA,UACV,eAAe,QAAA;AAAA,UAChB,OAAM;AAAA,UACL,UAAQ;AAAA,QAAA;QAGH,QAAA,SAAS,QAAA,eADjBC,IAAAA,aAAAH,IAAAA,mBAgBM,OAhBN,YAgBM;AAAA,UAXI,QAAA,0BADRA,IAAAA,mBAKO,QALP,YAKOI,IAAAA,gBADF,QAAA,KAAK,GAAA,CAAA;UAGF,QAAA,gCADRJ,IAAAA,mBAKO,QALP,YAKOI,IAAAA,gBADF,QAAA,WAAW,GAAA,CAAA;;;;;;;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"Dropdown.vue_vue_type_script_setup_true_lang-C3pr8BwC.js","sources":["../src/components/core/MenuItem.vue","../src/components/core/Dropdown.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { computed, resolveComponent } from 'vue'\nimport { Icon } from '@iconify/vue'\nimport type { MenuItemProps } from '@/types'\n\nconst props = withDefaults(\n defineProps<{\n menuItem: MenuItemProps\n /** Whether sidebar is expanded (shows labels) */\n expanded?: boolean\n /** Override active state directly */\n active?: boolean\n /** Current route path (pass from parent using useRoute().path) */\n currentPath?: string\n }>(),\n {\n expanded: true,\n active: undefined,\n currentPath: undefined,\n },\n)\n\nconst isRouteActive = computed(() => {\n // If active prop is explicitly set, use it\n if (props.active !== undefined) {\n return props.active\n }\n\n // Use currentPath prop if provided, otherwise fall back to window.location\n const path = props.currentPath ?? (typeof window !== 'undefined' ? window.location.pathname : '/')\n\n if (props.menuItem.link === '/') {\n return path === '/'\n }\n return path === props.menuItem.link || path.startsWith(props.menuItem.link + '/')\n})\n\n// Try to resolve RouterLink, fallback to 'a' tag\nconst linkComponent = computed(() => {\n try {\n const RouterLink = resolveComponent('RouterLink')\n if (typeof RouterLink !== 'string') {\n return RouterLink\n }\n } catch {\n // RouterLink not available\n }\n return 'a'\n})\n\nconst linkProps = computed(() => {\n if (linkComponent.value === 'a') {\n return { href: props.menuItem.link }\n }\n return { to: props.menuItem.link }\n})\n</script>\n\n<template>\n <component\n :is=\"linkComponent\"\n v-bind=\"linkProps\"\n :class=\"expanded ? 'flex-row' : 'flex-col'\"\n class=\"group relative flex items-center justify-center gap-2 px-5\"\n >\n <div class=\"relative\">\n <Icon\n :class=\"[\n isRouteActive\n ? 'text-white'\n : 'text-white/50 group-hover:text-white/80 dark:text-gray-700 dark:group-hover:text-gray-500',\n expanded ? 'size-6' : 'size-8',\n ]\"\n class=\"transition-all duration-300\"\n :icon=\"menuItem.icon\"\n />\n\n <span\n v-if=\"menuItem.notification\"\n class=\"absolute top-0.25 right-0.25 size-1.5 rounded-full bg-red-600\"\n />\n </div>\n\n <Transition\n enter-active-class=\"transition-all duration-300 ease-out\"\n enter-from-class=\"opacity-0 -translate-x-2\"\n enter-to-class=\"opacity-100 translate-x-0\"\n leave-active-class=\"transition-all duration-200 ease-in\"\n leave-from-class=\"opacity-100 translate-x-0\"\n leave-to-class=\"opacity-0 -translate-x-2\"\n >\n <span\n v-if=\"expanded\"\n :class=\"\n isRouteActive\n ? 'text-white'\n : 'text-white/50 group-hover:text-white/80 dark:text-gray-700 dark:group-hover:text-gray-500'\n \"\n class=\"text-sm font-semibold whitespace-nowrap\"\n >{{ menuItem.label }}</span>\n </Transition>\n </component>\n</template>\n","<script lang=\"ts\" setup>\r\nimport { ref, computed } from 'vue'\r\nimport { Icon } from '@iconify/vue'\r\nimport { useDropdown } from '@/composables/useDropdown'\r\n\r\nexport interface DropdownItem {\r\n key: string\r\n label: string\r\n icon?: string\r\n disabled?: boolean\r\n danger?: boolean\r\n divider?: boolean\r\n}\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n /** Dropdown items (optional if using default slot) */\r\n items?: DropdownItem[]\r\n /** Align dropdown */\r\n align?: 'left' | 'right'\r\n /** Dropdown width */\r\n width?: 'auto' | 'full' | 'sm' | 'md' | 'lg'\r\n /** Use teleport to body to avoid overflow clipping */\r\n teleport?: boolean\r\n }>(),\r\n {\r\n items: () => [],\r\n align: 'left',\r\n width: 'auto',\r\n teleport: true,\r\n },\r\n)\r\n\r\nconst emit = defineEmits<{\r\n select: [item: DropdownItem]\r\n}>()\r\n\r\nconst triggerRef = ref<HTMLElement>()\r\nconst menuRef = ref<HTMLElement>()\r\n\r\nconst { isOpen, dropdownStyle, toggle, close } = useDropdown(triggerRef, menuRef, {\r\n teleport: props.teleport,\r\n align: props.align,\r\n})\r\n\r\nconst selectItem = (item: DropdownItem) => {\r\n if (item.disabled || item.divider) return\r\n emit('select', item)\r\n close()\r\n}\r\n\r\nconst widthClasses = {\r\n auto: 'w-auto min-w-[10rem]',\r\n full: 'w-full',\r\n sm: 'w-32',\r\n md: 'w-48',\r\n lg: 'w-64',\r\n}\r\n\r\nconst computedDropdownStyle = computed(() => {\r\n if (!props.teleport) return {}\r\n const { width: _, ...rest } = dropdownStyle.value\r\n return rest\r\n})\r\n</script>\r\n\r\n<template>\r\n <div class=\"relative inline-block\">\r\n <div\n ref=\"triggerRef\"\n @click=\"toggle\"\n >\r\n <slot name=\"trigger\">\r\n <button\r\n type=\"button\"\r\n 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\"\r\n >\r\n <slot name=\"trigger-label\">\n Options\n </slot>\r\n <Icon\r\n icon=\"lucide:chevron-down\"\r\n :class=\"['size-4 transition-transform', isOpen && 'rotate-180']\"\r\n />\r\n </button>\r\n </slot>\r\n </div>\r\n\r\n <Teleport\n to=\"body\"\n :disabled=\"!teleport\"\n >\r\n <Transition\r\n enter-active-class=\"transition ease-out duration-100\"\r\n enter-from-class=\"transform opacity-0 scale-95\"\r\n enter-to-class=\"transform opacity-100 scale-100\"\r\n leave-active-class=\"transition ease-in duration-75\"\r\n leave-from-class=\"transform opacity-100 scale-100\"\r\n leave-to-class=\"transform opacity-0 scale-95\"\r\n >\r\n <div\r\n v-if=\"isOpen\"\r\n ref=\"menuRef\"\r\n :style=\"computedDropdownStyle\"\r\n :class=\"[\r\n 'z-[9999] rounded-lg border border-gray-200 bg-white py-1 shadow-lg dark:border-gray-700 dark:bg-gray-800',\r\n widthClasses[width],\r\n !teleport && (align === 'right' ? 'absolute mt-2 right-0' : 'absolute mt-2 left-0'),\r\n ]\"\r\n >\r\n <!-- Custom content via default slot -->\r\n <slot :close=\"close\">\r\n <!-- Default items rendering -->\r\n <template\n v-for=\"item in items\"\n :key=\"item.key\"\n >\r\n <div\r\n v-if=\"item.divider\"\r\n class=\"my-1 border-t border-gray-200 dark:border-gray-700\"\r\n />\r\n <button\r\n v-else\r\n type=\"button\"\r\n :disabled=\"item.disabled\"\r\n :class=\"[\r\n 'flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition-colors',\r\n item.disabled\r\n ? 'cursor-not-allowed opacity-50'\r\n : item.danger\r\n ? 'text-red-600 hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-900/20'\r\n : 'text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700',\r\n ]\"\r\n @click=\"selectItem(item)\"\r\n >\r\n <Icon\n v-if=\"item.icon\"\n :icon=\"item.icon\"\n class=\"size-4\"\n />\r\n {{ item.label }}\r\n </button>\r\n </template>\r\n </slot>\r\n </div>\r\n </Transition>\r\n </Teleport>\r\n </div>\r\n</template>\r\n"],"names":["_openBlock","_createBlock","_resolveDynamicComponent","_mergeProps","_createElementVNode","_hoisted_1","_createVNode","_unref","_normalizeClass","_createElementBlock","_hoisted_2","_Transition","_toDisplayString","_renderSlot","_Teleport","_Fragment","_renderList"],"mappings":";;;;;;;;;;;;;;;;;AAKA,UAAM,QAAQ;AAiBd,UAAM,gBAAgB,SAAS,MAAM;AAEnC,UAAI,MAAM,WAAW,QAAW;AAC9B,eAAO,MAAM;AAAA,MACf;AAGA,YAAM,OAAO,MAAM,gBAAgB,OAAO,WAAW,cAAc,OAAO,SAAS,WAAW;AAE9F,UAAI,MAAM,SAAS,SAAS,KAAK;AAC/B,eAAO,SAAS;AAAA,MAClB;AACA,aAAO,SAAS,MAAM,SAAS,QAAQ,KAAK,WAAW,MAAM,SAAS,OAAO,GAAG;AAAA,IAClF,CAAC;AAGD,UAAM,gBAAgB,SAAS,MAAM;AACnC,UAAI;AACF,cAAM,aAAa,iBAAiB,YAAY;AAChD,YAAI,OAAO,eAAe,UAAU;AAClC,iBAAO;AAAA,QACT;AAAA,MACF,QAAQ;AAAA,MAER;AACA,aAAO;AAAA,IACT,CAAC;AAED,UAAM,YAAY,SAAS,MAAM;AAC/B,UAAI,cAAc,UAAU,KAAK;AAC/B,eAAO,EAAE,MAAM,MAAM,SAAS,KAAA;AAAA,MAChC;AACA,aAAO,EAAE,IAAI,MAAM,SAAS,KAAA;AAAA,IAC9B,CAAC;;AAIC,aAAAA,UAAA,GAAAC,YA0CYC,wBAzCL,cAAA,KAAa,GADpBC,WAEU,UAwCE,OAxCO;AAAA,QAChB,OAAK,CAAE,QAAA,WAAQ,aAAA,YACV,4DAA4D;AAAA,MAAA;yBAElE,MAgBM;AAAA,UAhBNC,mBAgBM,OAhBNC,cAgBM;AAAA,YAfJC,YASEC,MAAA,IAAA,GAAA;AAAA,cARC,OAAKC,eAAA,CAAA;AAAA,gBAAc,cAAA;gBAA8J,QAAA,WAAQ,WAAA;AAAA,cAAA,GAMpL,6BAA6B,CAAA;AAAA,cAClC,MAAM,QAAA,SAAS;AAAA,YAAA;YAIV,QAAA,SAAS,gBADjBR,aAAAS,mBAGE,QAHFC,YAGE;;UAGJJ,YAiBaK,YAAA;AAAA,YAhBX,sBAAmB;AAAA,YACnB,oBAAiB;AAAA,YACjB,kBAAe;AAAA,YACf,sBAAmB;AAAA,YACnB,oBAAiB;AAAA,YACjB,kBAAe;AAAA,UAAA;6BAEf,MAQ4B;AAAA,cAPpB,QAAA,yBADRF,mBAQ4B,QAAA;AAAA;gBANzB,OAAKD,eAAA;AAAA,kBAAa,cAAA;kBAKb;AAAA,gBAAA,CAAyC;AAAA,cAAA,GAC7CI,gBAAA,QAAA,SAAS,KAAK,GAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACrFxB,UAAM,QAAQ;AAmBd,UAAM,OAAO;AAIb,UAAM,aAAa,IAAA;AACnB,UAAM,UAAU,IAAA;AAEhB,UAAM,EAAE,QAAQ,eAAe,QAAQ,UAAU,YAAY,YAAY,SAAS;AAAA,MAChF,UAAU,MAAM;AAAA,MAChB,OAAO,MAAM;AAAA,IAAA,CACd;AAED,UAAM,aAAa,CAAC,SAAuB;AACzC,UAAI,KAAK,YAAY,KAAK,QAAS;AACnC,WAAK,UAAU,IAAI;AACnB,YAAA;AAAA,IACF;AAEA,UAAM,eAAe;AAAA,MACnB,MAAM;AAAA,MACN,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IAAA;AAGN,UAAM,wBAAwB,SAAS,MAAM;AAC3C,UAAI,CAAC,MAAM,SAAU,QAAO,CAAA;AAC5B,YAAM,EAAE,OAAO,GAAG,GAAG,KAAA,IAAS,cAAc;AAC5C,aAAO;AAAA,IACT,CAAC;;AAIC,aAAAZ,UAAA,GAAAS,mBAgFM,OAhFN,YAgFM;AAAA,QA/EJL,mBAkBM,OAAA;AAAA,mBAjBA;AAAA,UAAJ,KAAI;AAAA,UACH,SAAK,OAAA,CAAA,MAAA,OAAA,CAAA;AAAA,uBAAEG,MAAA,MAAA,KAAAA,MAAA,MAAA,EAAA,GAAA,IAAA;AAAA,QAAA;UAERM,WAaO,4BAbP,MAaO;AAAA,YAZLT,mBAWS,UAXT,YAWS;AAAA,cAPPS,WAEO,kCAFP,MAEO;AAAA,0DAFoB,aAE3B,EAAA;AAAA,cAAA;cACAP,YAGEC,MAAA,IAAA,GAAA;AAAA,gBAFA,MAAK;AAAA,gBACJ,sDAAuCA,MAAA,MAAA,KAAM,YAAA,CAAA;AAAA,cAAA;;;;sBAMtDN,YA0DWa,UAAA;AAAA,UAzDT,IAAG;AAAA,UACF,WAAW,QAAA;AAAA,QAAA;UAEZR,YAqDaK,YAAA;AAAA,YApDX,sBAAmB;AAAA,YACnB,oBAAiB;AAAA,YACjB,kBAAe;AAAA,YACf,sBAAmB;AAAA,YACnB,oBAAiB;AAAA,YACjB,kBAAe;AAAA,UAAA;6BAEf,MA4CM;AAAA,cA3CEJ,MAAA,MAAA,kBADRE,mBA4CM,OAAA;AAAA;yBA1CA;AAAA,gBAAJ,KAAI;AAAA,gBACH,sBAAO,sBAAA,KAAqB;AAAA,gBAC5B,OAAKD,eAAA;AAAA;kBAA0I,aAAa,QAAA,KAAK;AAAA,kBAAiB,CAAA,QAAA,aAAa,QAAA,UAAK,UAAA,0BAAA;AAAA,gBAAA;;gBAOrMK,WAgCO,KAAA,QAAA,WAAA,EAhCA,OAAON,MAAA,KAAA,EAAA,GAAd,MAgCO;AAAA,oCA9BLE,mBA6BWM,UAAA,MAAAC,WA5BM,QAAA,OAAK,CAAb,SAAI;;sBACL,KAAA,KAAK;AAAA,oBAAA;sBAGH,KAAK,WADbhB,UAAA,GAAAS,mBAGE,OAHF,UAGE,mBACFA,mBAoBS,UAAA;AAAA;wBAlBP,MAAK;AAAA,wBACJ,UAAU,KAAK;AAAA,wBACf,OAAKD,eAAA;AAAA;0BAA0H,KAAK,6CAAuF,KAAK;;wBAQhO,SAAK,CAAA,WAAE,WAAW,IAAI;AAAA,sBAAA;wBAGf,KAAK,qBADbP,YAIEM,MAAA,IAAA,GAAA;AAAA;0BAFC,MAAM,KAAK;AAAA,0BACZ,OAAM;AAAA,wBAAA;wCACN,MACFK,gBAAG,KAAK,KAAK,GAAA,CAAA;AAAA,sBAAA;;;;;;;;;;;;;"}