cisse-vue-ui 0.8.0 → 0.8.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 (72) hide show
  1. package/README.md +879 -879
  2. package/dist/{CheckboxGroup.vue_vue_type_script_setup_true_lang-DJbuHoDj.cjs → CheckboxGroup.vue_vue_type_script_setup_true_lang-DuJr8cz3.cjs} +4 -4
  3. package/dist/CheckboxGroup.vue_vue_type_script_setup_true_lang-DuJr8cz3.cjs.map +1 -0
  4. package/dist/{CheckboxGroup.vue_vue_type_script_setup_true_lang-hHJdvUYS.js → CheckboxGroup.vue_vue_type_script_setup_true_lang-N4oS_DJD.js} +4 -4
  5. package/dist/CheckboxGroup.vue_vue_type_script_setup_true_lang-N4oS_DJD.js.map +1 -0
  6. package/dist/{ConfirmDialog.vue_vue_type_script_setup_true_lang-Bine-xfp.cjs → ConfirmDialog.vue_vue_type_script_setup_true_lang-BGUoa5fT.cjs} +58 -9
  7. package/dist/ConfirmDialog.vue_vue_type_script_setup_true_lang-BGUoa5fT.cjs.map +1 -0
  8. package/dist/{ConfirmDialog.vue_vue_type_script_setup_true_lang-DqkA1Zr-.js → ConfirmDialog.vue_vue_type_script_setup_true_lang-DWs2V7xX.js} +58 -9
  9. package/dist/ConfirmDialog.vue_vue_type_script_setup_true_lang-DWs2V7xX.js.map +1 -0
  10. package/dist/{Dropdown.vue_vue_type_script_setup_true_lang-56CxoSmj.js → Dropdown.vue_vue_type_script_setup_true_lang-A9Ax6iob.js} +110 -14
  11. package/dist/Dropdown.vue_vue_type_script_setup_true_lang-A9Ax6iob.js.map +1 -0
  12. package/dist/{Dropdown.vue_vue_type_script_setup_true_lang-Dd3ySRNB.cjs → Dropdown.vue_vue_type_script_setup_true_lang-DoJKvn30.cjs} +109 -13
  13. package/dist/Dropdown.vue_vue_type_script_setup_true_lang-DoJKvn30.cjs.map +1 -0
  14. package/dist/{FilterTabs.vue_vue_type_script_setup_true_lang-DzLwUVCW.js → FilterTabs.vue_vue_type_script_setup_true_lang-CcOgc2Y_.js} +2 -2
  15. package/dist/FilterTabs.vue_vue_type_script_setup_true_lang-CcOgc2Y_.js.map +1 -0
  16. package/dist/{FilterTabs.vue_vue_type_script_setup_true_lang-Bj3I5Sn7.cjs → FilterTabs.vue_vue_type_script_setup_true_lang-jW6Ikbvy.cjs} +2 -2
  17. package/dist/FilterTabs.vue_vue_type_script_setup_true_lang-jW6Ikbvy.cjs.map +1 -0
  18. package/dist/ListSkeleton.vue_vue_type_script_setup_true_lang-BwtEbaiT.js.map +1 -1
  19. package/dist/ListSkeleton.vue_vue_type_script_setup_true_lang-DtwwmfWr.cjs.map +1 -1
  20. package/dist/{PageHero.vue_vue_type_script_setup_true_lang-DQQGYAw0.js → PageHero.vue_vue_type_script_setup_true_lang-Gvocjdqh.js} +2 -2
  21. package/dist/PageHero.vue_vue_type_script_setup_true_lang-Gvocjdqh.js.map +1 -0
  22. package/dist/{PageHero.vue_vue_type_script_setup_true_lang-Bi97ypMD.cjs → PageHero.vue_vue_type_script_setup_true_lang-rbvfGvll.cjs} +2 -2
  23. package/dist/PageHero.vue_vue_type_script_setup_true_lang-rbvfGvll.cjs.map +1 -0
  24. package/dist/cisse-vue-ui.css +57 -57
  25. package/dist/components/core/MenuItem.stories.d.ts +1 -0
  26. package/dist/components/core/MenuItem.vue.d.ts +2 -13
  27. package/dist/components/core/index.cjs +2 -2
  28. package/dist/components/core/index.js +2 -2
  29. package/dist/components/feedback/PaginationControls.stories.d.ts +5 -0
  30. package/dist/components/feedback/PaginationControls.vue.d.ts +2 -0
  31. package/dist/components/feedback/index.cjs +1 -1
  32. package/dist/components/feedback/index.js +1 -1
  33. package/dist/components/form/index.cjs +1 -1
  34. package/dist/components/form/index.js +1 -1
  35. package/dist/components/index.cjs +5 -5
  36. package/dist/components/index.js +5 -5
  37. package/dist/components/layout/index.cjs +1 -1
  38. package/dist/components/layout/index.js +1 -1
  39. package/dist/composables/index.cjs +1 -1
  40. package/dist/composables/index.js +1 -1
  41. package/dist/composables/useDropdown.d.ts +4 -1
  42. package/dist/{index-DwqCXgDx.cjs → index-5dQNEzd8.cjs} +6 -6
  43. package/dist/{index-DwqCXgDx.cjs.map → index-5dQNEzd8.cjs.map} +1 -1
  44. package/dist/{index-rBD1MYh-.js → index-CDDUEkXf.js} +6 -6
  45. package/dist/index-CDDUEkXf.js.map +1 -0
  46. package/dist/index.cjs +7 -7
  47. package/dist/index.js +7 -7
  48. package/dist/style.css +1 -1
  49. package/dist/{useDropdown-DHFnd259.cjs → useDropdown-DK4c5JGL.cjs} +66 -10
  50. package/dist/useDropdown-DK4c5JGL.cjs.map +1 -0
  51. package/dist/{useDropdown-iVu14E6s.js → useDropdown-De0cKI83.js} +66 -10
  52. package/dist/useDropdown-De0cKI83.js.map +1 -0
  53. package/dist/useFocusTrap-AnlJsihM.js.map +1 -1
  54. package/dist/useFocusTrap-kcxO8AeU.cjs.map +1 -1
  55. package/dist/useId-nxrBaIC9.cjs.map +1 -1
  56. package/dist/useId-xeHj7rkg.js.map +1 -1
  57. package/dist/useToast-Bk60GArg.cjs.map +1 -1
  58. package/dist/useToast-ina5g3mj.js.map +1 -1
  59. package/package.json +169 -169
  60. package/dist/CheckboxGroup.vue_vue_type_script_setup_true_lang-DJbuHoDj.cjs.map +0 -1
  61. package/dist/CheckboxGroup.vue_vue_type_script_setup_true_lang-hHJdvUYS.js.map +0 -1
  62. package/dist/ConfirmDialog.vue_vue_type_script_setup_true_lang-Bine-xfp.cjs.map +0 -1
  63. package/dist/ConfirmDialog.vue_vue_type_script_setup_true_lang-DqkA1Zr-.js.map +0 -1
  64. package/dist/Dropdown.vue_vue_type_script_setup_true_lang-56CxoSmj.js.map +0 -1
  65. package/dist/Dropdown.vue_vue_type_script_setup_true_lang-Dd3ySRNB.cjs.map +0 -1
  66. package/dist/FilterTabs.vue_vue_type_script_setup_true_lang-Bj3I5Sn7.cjs.map +0 -1
  67. package/dist/FilterTabs.vue_vue_type_script_setup_true_lang-DzLwUVCW.js.map +0 -1
  68. package/dist/PageHero.vue_vue_type_script_setup_true_lang-Bi97ypMD.cjs.map +0 -1
  69. package/dist/PageHero.vue_vue_type_script_setup_true_lang-DQQGYAw0.js.map +0 -1
  70. package/dist/index-rBD1MYh-.js.map +0 -1
  71. package/dist/useDropdown-DHFnd259.cjs.map +0 -1
  72. package/dist/useDropdown-iVu14E6s.js.map +0 -1
@@ -189,11 +189,16 @@ const _hoisted_5$1 = {
189
189
  };
190
190
  const _hoisted_6 = ["value"];
191
191
  const _hoisted_7 = ["value"];
192
- const _hoisted_8 = { class: "flex justify-center sm:justify-end gap-2" };
192
+ const _hoisted_8 = { class: "flex justify-center sm:justify-end items-center gap-1" };
193
193
  const _hoisted_9 = ["disabled"];
194
194
  const _hoisted_10 = { class: "hidden sm:inline" };
195
- const _hoisted_11 = ["disabled"];
196
- const _hoisted_12 = { class: "hidden sm:inline" };
195
+ const _hoisted_11 = {
196
+ key: 0,
197
+ class: "px-2 py-2 text-sm text-gray-500 dark:text-gray-400"
198
+ };
199
+ const _hoisted_12 = ["disabled", "onClick"];
200
+ const _hoisted_13 = ["disabled"];
201
+ const _hoisted_14 = { class: "hidden sm:inline" };
197
202
  const _sfc_main$9 = /* @__PURE__ */ vue.defineComponent({
198
203
  __name: "PaginationControls",
199
204
  props: {
@@ -203,6 +208,8 @@ const _sfc_main$9 = /* @__PURE__ */ vue.defineComponent({
203
208
  pageSize: { default: 10 },
204
209
  pageSizeOptions: { default: () => [10, 20, 50, 100] },
205
210
  showPageSize: { type: Boolean, default: true },
211
+ showPageNumbers: { type: Boolean, default: true },
212
+ maxVisiblePages: { default: 7 },
206
213
  pageLabel: { default: "Page" },
207
214
  ofLabel: { default: "of" },
208
215
  itemsPerPageLabel: { default: "Items per page:" },
@@ -211,6 +218,34 @@ const _sfc_main$9 = /* @__PURE__ */ vue.defineComponent({
211
218
  },
212
219
  emits: ["update:page", "update:pageSize"],
213
220
  setup(__props, { emit: __emit }) {
221
+ const visiblePages = vue.computed(() => {
222
+ if (__props.totalPages <= __props.maxVisiblePages) {
223
+ return Array.from({ length: __props.totalPages }, (_, i) => i + 1);
224
+ }
225
+ const pages = [];
226
+ const sidePages = Math.floor((__props.maxVisiblePages - 3) / 2);
227
+ pages.push(1);
228
+ let rangeStart = Math.max(2, __props.currentPage - sidePages);
229
+ let rangeEnd = Math.min(__props.totalPages - 1, __props.currentPage + sidePages);
230
+ if (__props.currentPage <= sidePages + 2) {
231
+ rangeEnd = Math.min(__props.totalPages - 1, __props.maxVisiblePages - 2);
232
+ } else if (__props.currentPage >= __props.totalPages - sidePages - 1) {
233
+ rangeStart = Math.max(2, __props.totalPages - __props.maxVisiblePages + 3);
234
+ }
235
+ if (rangeStart > 2) {
236
+ pages.push("ellipsis-start");
237
+ }
238
+ for (let i = rangeStart; i <= rangeEnd; i++) {
239
+ pages.push(i);
240
+ }
241
+ if (rangeEnd < __props.totalPages - 1) {
242
+ pages.push("ellipsis-end");
243
+ }
244
+ if (__props.totalPages > 1) {
245
+ pages.push(__props.totalPages);
246
+ }
247
+ return pages;
248
+ });
214
249
  const emit = __emit;
215
250
  const changePage = (page) => {
216
251
  if (page >= 1 && page <= __props.totalPages && !__props.loading) {
@@ -245,7 +280,7 @@ const _sfc_main$9 = /* @__PURE__ */ vue.defineComponent({
245
280
  vue.createElementVNode("div", _hoisted_8, [
246
281
  vue.createElementVNode("button", {
247
282
  disabled: __props.currentPage === 1 || __props.loading,
248
- class: "focus:ring-primary inline-flex items-center gap-1 rounded-lg border border-gray-300 bg-white px-3 sm:px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700",
283
+ class: "focus:ring-primary inline-flex items-center gap-1 rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700",
249
284
  onClick: _cache[0] || (_cache[0] = ($event) => changePage(__props.currentPage - 1))
250
285
  }, [
251
286
  vue.createVNode(vue.unref(vue$1.Icon), {
@@ -254,17 +289,31 @@ const _sfc_main$9 = /* @__PURE__ */ vue.defineComponent({
254
289
  }),
255
290
  vue.createElementVNode("span", _hoisted_10, vue.toDisplayString(__props.previousLabel), 1)
256
291
  ], 8, _hoisted_9),
292
+ __props.showPageNumbers ? (vue.openBlock(true), vue.createElementBlock(vue.Fragment, { key: 0 }, vue.renderList(visiblePages.value, (page) => {
293
+ return vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: page }, [
294
+ page === "ellipsis-start" || page === "ellipsis-end" ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_11, " … ")) : (vue.openBlock(), vue.createElementBlock("button", {
295
+ key: 1,
296
+ disabled: __props.loading,
297
+ class: vue.normalizeClass([
298
+ "min-w-[40px] px-3 py-2 text-sm font-medium rounded-lg border transition-colors",
299
+ page === __props.currentPage ? "bg-primary-600 text-white border-primary-600 dark:bg-primary-500 dark:border-primary-500" : "bg-white text-gray-700 border-gray-300 hover:bg-gray-50 dark:bg-gray-800 dark:text-gray-200 dark:border-gray-600 dark:hover:bg-gray-700",
300
+ __props.loading ? "cursor-not-allowed opacity-50" : ""
301
+ ]),
302
+ onClick: ($event) => changePage(page)
303
+ }, vue.toDisplayString(page), 11, _hoisted_12))
304
+ ], 64);
305
+ }), 128)) : vue.createCommentVNode("", true),
257
306
  vue.createElementVNode("button", {
258
307
  disabled: __props.currentPage === __props.totalPages || __props.loading,
259
- class: "focus:ring-primary inline-flex items-center gap-1 rounded-lg border border-gray-300 bg-white px-3 sm:px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700",
308
+ class: "focus:ring-primary inline-flex items-center gap-1 rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700",
260
309
  onClick: _cache[1] || (_cache[1] = ($event) => changePage(__props.currentPage + 1))
261
310
  }, [
262
- vue.createElementVNode("span", _hoisted_12, vue.toDisplayString(__props.nextLabel), 1),
311
+ vue.createElementVNode("span", _hoisted_14, vue.toDisplayString(__props.nextLabel), 1),
263
312
  vue.createVNode(vue.unref(vue$1.Icon), {
264
313
  class: "size-4",
265
314
  icon: "lucide:chevron-right"
266
315
  })
267
- ], 8, _hoisted_11)
316
+ ], 8, _hoisted_13)
268
317
  ])
269
318
  ])) : vue.createCommentVNode("", true);
270
319
  };
@@ -762,7 +811,7 @@ const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({
762
811
  };
763
812
  }
764
813
  });
765
- const Progress = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main$2, [["__scopeId", "data-v-7ff636cf"]]);
814
+ const Progress = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main$2, [["__scopeId", "data-v-546a3ae5"]]);
766
815
  const _hoisted_1$1 = {
767
816
  key: 0,
768
817
  class: "space-y-2",
@@ -925,4 +974,4 @@ exports._sfc_main$6 = _sfc_main$5;
925
974
  exports._sfc_main$7 = _sfc_main$4;
926
975
  exports._sfc_main$8 = _sfc_main$3;
927
976
  exports._sfc_main$9 = _sfc_main$1;
928
- //# sourceMappingURL=ConfirmDialog.vue_vue_type_script_setup_true_lang-Bine-xfp.cjs.map
977
+ //# sourceMappingURL=ConfirmDialog.vue_vue_type_script_setup_true_lang-BGUoa5fT.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfirmDialog.vue_vue_type_script_setup_true_lang-BGUoa5fT.cjs","sources":["../src/components/feedback/LoadingSpinner.vue","../src/components/feedback/Modal.vue","../src/components/feedback/PaginationControls.vue","../src/components/feedback/NotificationComponent.vue","../src/components/feedback/NotificationList.vue","../src/components/feedback/Alert.vue","../src/components/feedback/EmptyState.vue","../src/components/feedback/Toast.vue","../src/components/feedback/ToastContainer.vue","../src/components/feedback/Progress.vue","../src/components/feedback/Skeleton.vue","../src/components/feedback/ConfirmDialog.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { computed } from 'vue'\nimport type { SpinnerSize } from '@/types'\n\nconst props = withDefaults(\n defineProps<{\n text?: string\n size?: SpinnerSize\n /** Accessible label for screen readers (defaults to 'Loading' or text prop) */\n ariaLabel?: string\n }>(),\n {\n size: 'md',\n ariaLabel: 'Loading',\n },\n)\n\nconst sizeClasses: Record<SpinnerSize, string> = {\n sm: 'size-8',\n md: 'size-12',\n lg: 'size-16',\n}\n\nconst accessibleLabel = computed(() => props.text || props.ariaLabel)\n</script>\n\n<template>\n <div\n class=\"flex items-center justify-center py-12\"\n role=\"status\"\n aria-live=\"polite\"\n :aria-label=\"accessibleLabel\"\n >\n <div class=\"text-center\">\n <div\n :class=\"sizeClasses[size]\"\n class=\"border-primary inline-block animate-spin rounded-full border-4 border-solid border-r-transparent\"\n aria-hidden=\"true\"\n />\n <p\n v-if=\"text\"\n class=\"mt-4 text-gray-600 dark:text-gray-400\"\n >\n {{ text }}\n </p>\n <span v-else class=\"sr-only\">{{ accessibleLabel }}</span>\n </div>\n </div>\n</template>\n","<script lang=\"ts\" setup>\r\nimport { Icon } from '@iconify/vue'\r\nimport { onMounted, onUnmounted, computed, ref } from 'vue'\r\nimport type { ModalSize } from '@/types'\r\nimport { useId } from '@/composables/useId'\r\nimport { useFocusTrap } from '@/composables/useFocusTrap'\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n title?: string\r\n size?: ModalSize\r\n closeOnBackdrop?: boolean\r\n closeOnEscape?: boolean\r\n closeButtonLabel?: string\r\n /** Teleport target (e.g., 'body', '#app'). Set to false to disable teleport. */\r\n teleport?: string | false\r\n /** Custom ID for the modal (auto-generated if not provided) */\r\n id?: string\r\n }>(),\r\n {\r\n title: '',\r\n size: 'default',\r\n closeOnBackdrop: true,\r\n closeOnEscape: true,\r\n closeButtonLabel: 'Close',\r\n teleport: 'body',\r\n },\r\n)\r\n\r\nconst {\r\n title,\r\n size,\r\n closeOnBackdrop,\r\n closeOnEscape,\r\n closeButtonLabel,\r\n} = props\r\n\r\nconst teleportDisabled = computed(() => props.teleport === false)\r\nconst teleportTarget = computed(() => props.teleport === false ? 'body' : props.teleport)\r\n\r\nconst emit = defineEmits<{\r\n close: []\r\n}>()\r\n\r\n// Generate unique IDs for ARIA relationships\r\nconst { id: modalId, related } = useId({ prefix: 'modal', id: props.id })\r\nconst titleId = computed(() => related('title'))\r\n\r\n// Focus trap\r\nconst isActive = ref(true)\r\nconst { containerRef: dialogRef } = useFocusTrap({\r\n active: isActive,\r\n focusFirst: true,\r\n restoreFocus: true,\r\n})\r\n\r\n// Check if modal has a title (for aria-labelledby)\r\nconst hasTitle = computed(() => Boolean(props.title))\r\n\r\nconst sizeClasses: Record<ModalSize, string> = {\r\n sm: 'max-w-md',\r\n default: 'max-w-3xl',\r\n lg: 'max-w-5xl',\r\n xl: 'max-w-7xl',\r\n full: 'max-w-full mx-4',\r\n}\r\n\r\nconst handleBackdropClick = () => {\r\n if (closeOnBackdrop) {\r\n emit('close')\r\n }\r\n}\r\n\r\nconst handleEscape = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape' && closeOnEscape) {\r\n emit('close')\r\n }\r\n}\r\n\r\nonMounted(() => {\r\n document.addEventListener('keydown', handleEscape)\r\n document.body.style.overflow = 'hidden'\r\n})\r\n\r\nonUnmounted(() => {\r\n document.removeEventListener('keydown', handleEscape)\r\n document.body.style.overflow = ''\r\n})\r\n</script>\r\n\r\n<template>\r\n <Teleport :to=\"teleportTarget\" :disabled=\"teleportDisabled\">\r\n <div\r\n class=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4\"\r\n @click.self=\"handleBackdropClick\"\r\n >\r\n <div\r\n ref=\"dialogRef\"\r\n :id=\"modalId\"\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n :aria-labelledby=\"hasTitle ? titleId : undefined\"\r\n :class=\"sizeClasses[size]\"\r\n class=\"flex max-h-[90vh] w-full flex-col rounded-lg bg-white shadow-xl dark:bg-gray-900\"\r\n >\r\n <!-- Header -->\r\n <div\r\n v-if=\"title || $slots.header || $slots.title\"\r\n class=\"flex items-center justify-between border-b border-gray-200 px-6 py-4 dark:border-gray-700\"\r\n >\r\n <h3\r\n :id=\"titleId\"\r\n class=\"text-xl font-semibold text-gray-900 dark:text-gray-100\"\r\n >\r\n <slot name=\"header\">\r\n <slot name=\"title\">\r\n {{ title }}\r\n </slot>\r\n </slot>\r\n </h3>\r\n <button\r\n class=\"rounded-lg p-1.5 text-gray-400 hover:bg-gray-100 hover:text-gray-900 dark:hover:bg-gray-800 dark:hover:text-gray-100\"\r\n type=\"button\"\r\n aria-label=\"Close dialog\"\r\n @click=\"emit('close')\"\r\n >\r\n <Icon\r\n class=\"size-5\"\r\n icon=\"lucide:x\"\r\n aria-hidden=\"true\"\r\n />\r\n <span class=\"sr-only\">{{ closeButtonLabel }}</span>\r\n </button>\r\n </div>\r\n\r\n <!-- Body -->\r\n <div class=\"flex-1 overflow-y-auto px-6 py-4\">\r\n <slot />\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div\r\n v-if=\"$slots.footer\"\r\n class=\"flex items-center justify-end gap-3 border-t border-gray-200 px-6 py-4 dark:border-gray-700\"\r\n >\r\n <slot name=\"footer\" />\r\n </div>\r\n </div>\r\n </div>\r\n </Teleport>\r\n</template>\r\n","<script lang=\"ts\" setup>\r\nimport { computed } from 'vue'\r\nimport { Icon } from '@iconify/vue'\r\n\r\nconst {\r\n currentPage,\r\n totalPages,\r\n loading = false,\r\n pageSize = 10,\r\n pageSizeOptions = [10, 20, 50, 100],\r\n showPageSize = true,\r\n showPageNumbers = true,\r\n maxVisiblePages = 7,\r\n pageLabel = 'Page',\r\n ofLabel = 'of',\r\n itemsPerPageLabel = 'Items per page:',\r\n previousLabel = 'Previous',\r\n nextLabel = 'Next',\r\n} = defineProps<{\r\n currentPage: number\r\n totalPages: number\r\n loading?: boolean\r\n pageSize?: number\r\n pageSizeOptions?: number[]\r\n showPageSize?: boolean\r\n showPageNumbers?: boolean\r\n maxVisiblePages?: number\r\n pageLabel?: string\r\n ofLabel?: string\r\n itemsPerPageLabel?: string\r\n previousLabel?: string\r\n nextLabel?: string\r\n}>()\r\n\r\ntype PageItem = number | 'ellipsis-start' | 'ellipsis-end'\r\n\r\nconst visiblePages = computed<PageItem[]>(() => {\r\n if (totalPages <= maxVisiblePages) {\r\n return Array.from({ length: totalPages }, (_, i) => i + 1)\r\n }\r\n\r\n const pages: PageItem[] = []\r\n const sidePages = Math.floor((maxVisiblePages - 3) / 2)\r\n\r\n // Always show first page\r\n pages.push(1)\r\n\r\n // Calculate range around current page\r\n let rangeStart = Math.max(2, currentPage - sidePages)\r\n let rangeEnd = Math.min(totalPages - 1, currentPage + sidePages)\r\n\r\n // Adjust range to show more pages on one side if near edges\r\n if (currentPage <= sidePages + 2) {\r\n rangeEnd = Math.min(totalPages - 1, maxVisiblePages - 2)\r\n } else if (currentPage >= totalPages - sidePages - 1) {\r\n rangeStart = Math.max(2, totalPages - maxVisiblePages + 3)\r\n }\r\n\r\n // Add ellipsis or pages after first page\r\n if (rangeStart > 2) {\r\n pages.push('ellipsis-start')\r\n }\r\n\r\n // Add range pages\r\n for (let i = rangeStart; i <= rangeEnd; i++) {\r\n pages.push(i)\r\n }\r\n\r\n // Add ellipsis or pages before last page\r\n if (rangeEnd < totalPages - 1) {\r\n pages.push('ellipsis-end')\r\n }\r\n\r\n // Always show last page\r\n if (totalPages > 1) {\r\n pages.push(totalPages)\r\n }\r\n\r\n return pages\r\n})\r\n\r\nconst emit = defineEmits<{\r\n 'update:page': [page: number]\r\n 'update:pageSize': [size: number]\r\n}>()\r\n\r\nconst changePage = (page: number) => {\r\n if (page >= 1 && page <= totalPages && !loading) {\r\n emit('update:page', page)\r\n }\r\n}\r\n\r\nconst changePageSize = (event: Event) => {\r\n const target = event.target as HTMLSelectElement\r\n emit('update:pageSize', Number(target.value))\r\n}\r\n</script>\r\n\r\n<template>\r\n <div\r\n v-if=\"totalPages > 1\"\r\n class=\"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 border-t border-gray-200 px-4 sm:px-6 py-4 dark:border-gray-700\"\r\n >\r\n <!-- Info and page size -->\r\n <div class=\"flex flex-col sm:flex-row sm:items-center gap-3 sm:gap-4\">\r\n <div class=\"text-sm text-gray-700 dark:text-gray-300 text-center sm:text-left\">\r\n {{ pageLabel }} {{ currentPage }} {{ ofLabel }} {{ totalPages }}\r\n </div>\r\n <div\r\n v-if=\"showPageSize\"\r\n class=\"flex items-center justify-center sm:justify-start gap-2\"\r\n >\r\n <label\r\n class=\"text-sm text-gray-600 dark:text-gray-400 hidden sm:inline\"\r\n for=\"page-size\"\r\n >\r\n {{ itemsPerPageLabel }}\r\n </label>\r\n <select\r\n id=\"page-size\"\r\n :value=\"pageSize\"\r\n class=\"focus:border-primary focus:ring-primary rounded border border-gray-300 bg-white px-2 py-1 text-sm text-gray-900 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100\"\r\n @change=\"changePageSize\"\r\n >\r\n <option\r\n v-for=\"size in pageSizeOptions\"\r\n :key=\"size\"\r\n :value=\"size\"\r\n >\r\n {{ size }}\r\n </option>\r\n </select>\r\n </div>\r\n </div>\r\n\r\n <!-- Navigation buttons -->\r\n <div class=\"flex justify-center sm:justify-end items-center gap-1\">\r\n <!-- Previous button -->\r\n <button\r\n :disabled=\"currentPage === 1 || loading\"\r\n class=\"focus:ring-primary inline-flex items-center gap-1 rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700\"\r\n @click=\"changePage(currentPage - 1)\"\r\n >\r\n <Icon\r\n class=\"size-4\"\r\n icon=\"lucide:chevron-left\"\r\n />\r\n <span class=\"hidden sm:inline\">{{ previousLabel }}</span>\r\n </button>\r\n\r\n <!-- Page numbers -->\r\n <template v-if=\"showPageNumbers\">\r\n <template\r\n v-for=\"page in visiblePages\"\r\n :key=\"page\"\r\n >\r\n <!-- Ellipsis -->\r\n <span\r\n v-if=\"page === 'ellipsis-start' || page === 'ellipsis-end'\"\r\n class=\"px-2 py-2 text-sm text-gray-500 dark:text-gray-400\"\r\n >\r\n …\r\n </span>\r\n <!-- Page number button -->\r\n <button\r\n v-else\r\n :disabled=\"loading\"\r\n :class=\"[\r\n 'min-w-[40px] px-3 py-2 text-sm font-medium rounded-lg border transition-colors',\r\n page === currentPage\r\n ? 'bg-primary-600 text-white border-primary-600 dark:bg-primary-500 dark:border-primary-500'\r\n : 'bg-white text-gray-700 border-gray-300 hover:bg-gray-50 dark:bg-gray-800 dark:text-gray-200 dark:border-gray-600 dark:hover:bg-gray-700',\r\n loading ? 'cursor-not-allowed opacity-50' : ''\r\n ]\"\r\n @click=\"changePage(page)\"\r\n >\r\n {{ page }}\r\n </button>\r\n </template>\r\n </template>\r\n\r\n <!-- Next button -->\r\n <button\r\n :disabled=\"currentPage === totalPages || loading\"\r\n class=\"focus:ring-primary inline-flex items-center gap-1 rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700\"\r\n @click=\"changePage(currentPage + 1)\"\r\n >\r\n <span class=\"hidden sm:inline\">{{ nextLabel }}</span>\r\n <Icon\r\n class=\"size-4\"\r\n icon=\"lucide:chevron-right\"\r\n />\r\n </button>\r\n </div>\r\n </div>\r\n</template>\r\n","<script lang=\"ts\" setup>\nimport type { Notification } from '@/types'\nimport { computed, onMounted } from 'vue'\nimport { Icon } from '@iconify/vue'\n\nconst props = defineProps<{\n notification: Notification\n autoDismiss?: boolean\n duration?: number\n}>()\n\nconst emit = defineEmits<{\n dismiss: [id: string]\n}>()\n\nconst iconName = computed(() => {\n switch (props.notification.type) {\n case 'success':\n return 'lucide:check-circle'\n case 'info':\n return 'lucide:info'\n case 'warning':\n return 'lucide:alert-triangle'\n case 'error':\n return 'lucide:x-circle'\n default:\n return 'lucide:bell'\n }\n})\n\nconst iconColor = computed(() => {\n switch (props.notification.type) {\n case 'success':\n return 'text-green-600 dark:text-green-400'\n case 'info':\n return 'text-blue-600 dark:text-blue-400'\n case 'warning':\n return 'text-yellow-600 dark:text-yellow-400'\n case 'error':\n return 'text-red-600 dark:text-red-400'\n default:\n return 'text-gray-600 dark:text-gray-400'\n }\n})\n\nconst bgColor = computed(() => {\n switch (props.notification.type) {\n case 'success':\n return 'bg-green-50 dark:bg-green-950'\n case 'info':\n return 'bg-blue-50 dark:bg-blue-950'\n case 'warning':\n return 'bg-yellow-50 dark:bg-yellow-950'\n case 'error':\n return 'bg-red-50 dark:bg-red-950'\n default:\n return 'bg-gray-50 dark:bg-gray-950'\n }\n})\n\nconst handleDismiss = () => {\n if (props.notification.id) {\n emit('dismiss', props.notification.id)\n }\n}\n\nonMounted(() => {\n const duration = props.notification.duration ?? props.duration ?? 5000\n if (props.autoDismiss !== false && duration > 0) {\n setTimeout(() => {\n handleDismiss()\n }, duration)\n }\n})\n</script>\n\n<template>\n <div\n class=\"flex max-w-md items-start space-x-3 rounded-lg border border-gray-200 bg-white p-4 shadow-lg dark:border-gray-800 dark:bg-black\"\n >\n <div :class=\"[bgColor, 'flex items-center justify-center rounded-full p-2']\">\n <Icon\n :class=\"iconColor\"\n :icon=\"iconName\"\n class=\"size-5\"\n />\n </div>\n\n <div class=\"flex min-w-0 flex-1 flex-col\">\n <h4\n v-if=\"notification.title\"\n class=\"text-sm font-semibold text-gray-900 dark:text-gray-100\"\n >\n {{ notification.title }}\n </h4>\n <p\n v-if=\"notification.message\"\n class=\"mt-1 text-sm text-gray-600 dark:text-gray-400\"\n >\n {{ notification.message }}\n </p>\n </div>\n\n <button\n class=\"shrink-0 text-gray-400 transition-colors hover:text-gray-600 dark:text-gray-600 dark:hover:text-gray-400\"\n @click=\"handleDismiss\"\n >\n <Icon\n class=\"size-4\"\n icon=\"lucide:x\"\n />\n </button>\n </div>\n</template>\n","<script lang=\"ts\" setup>\r\nimport { computed } from 'vue'\r\nimport type { Notification } from '@/types'\r\nimport NotificationComponent from './NotificationComponent.vue'\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n notifications: Notification[]\r\n autoDismiss?: boolean\r\n duration?: number\r\n /** Position of the container */\r\n position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'\r\n /** Custom top offset (e.g., '80px', '5rem') to account for fixed headers */\r\n topOffset?: string\r\n }>(),\r\n {\r\n position: 'top-right',\r\n },\r\n)\r\n\r\nconst emit = defineEmits<{\r\n dismiss: [id: string]\r\n}>()\r\n\r\nconst positionClasses: Record<string, string> = {\r\n 'top-right': 'top-5 right-5',\r\n 'top-left': 'top-5 left-5',\r\n 'bottom-right': 'bottom-5 right-5',\r\n 'bottom-left': 'bottom-5 left-5',\r\n}\r\n\r\nconst isTopPosition = computed(() => props.position?.startsWith('top'))\r\n\r\nconst topStyle = computed(() => {\r\n if (!isTopPosition.value || !props.topOffset) return {}\r\n return { top: props.topOffset }\r\n})\r\n</script>\r\n\r\n<template>\r\n <Teleport to=\"body\">\r\n <div\r\n :class=\"['fixed z-50 flex flex-col gap-3 w-full max-w-sm', positionClasses[position]]\"\r\n :style=\"topStyle\"\r\n >\r\n <TransitionGroup\r\n enter-active-class=\"transition duration-300 ease-out\"\r\n enter-from-class=\"opacity-0 translate-x-4\"\r\n enter-to-class=\"opacity-100 translate-x-0\"\r\n leave-active-class=\"transition duration-200 ease-in\"\r\n leave-from-class=\"opacity-100 translate-x-0\"\r\n leave-to-class=\"opacity-0 translate-x-4\"\r\n >\r\n <NotificationComponent\r\n v-for=\"notification in notifications\"\r\n :key=\"notification.id\"\r\n :notification=\"notification\"\r\n :auto-dismiss=\"autoDismiss\"\r\n :duration=\"duration\"\r\n @dismiss=\"emit('dismiss', $event)\"\r\n />\r\n </TransitionGroup>\r\n </div>\r\n </Teleport>\r\n</template>\r\n","<script lang=\"ts\" setup>\nimport { Icon } from '@iconify/vue'\n\nexport type AlertVariant = 'info' | 'success' | 'warning' | 'error'\n\nconst props = withDefaults(\n defineProps<{\n /** Alert variant */\n variant?: AlertVariant\n /** Title text */\n title?: string\n /** Show close button */\n dismissible?: boolean\n /** Custom icon */\n icon?: string\n }>(),\n {\n variant: 'info',\n },\n)\n\nconst emit = defineEmits<{\n dismiss: []\n}>()\n\nconst variantStyles: Record<AlertVariant, { bg: string; border: string; icon: string; iconColor: string }> = {\n info: {\n bg: 'bg-blue-50 dark:bg-blue-900/20',\n border: 'border-blue-200 dark:border-blue-800',\n icon: 'lucide:info',\n iconColor: 'text-blue-500',\n },\n success: {\n bg: 'bg-green-50 dark:bg-green-900/20',\n border: 'border-green-200 dark:border-green-800',\n icon: 'lucide:check-circle',\n iconColor: 'text-green-500',\n },\n warning: {\n bg: 'bg-yellow-50 dark:bg-yellow-900/20',\n border: 'border-yellow-200 dark:border-yellow-800',\n icon: 'lucide:alert-triangle',\n iconColor: 'text-yellow-500',\n },\n error: {\n bg: 'bg-red-50 dark:bg-red-900/20',\n border: 'border-red-200 dark:border-red-800',\n icon: 'lucide:alert-circle',\n iconColor: 'text-red-500',\n },\n}\n\nconst styles = variantStyles[props.variant]\n</script>\n\n<template>\n <div\n :class=\"[\n 'flex gap-3 rounded-lg border p-4',\n styles.bg,\n styles.border,\n ]\"\n role=\"alert\"\n >\n <Icon\n :icon=\"icon || styles.icon\"\n :class=\"['size-5 shrink-0', styles.iconColor]\"\n aria-hidden=\"true\"\n />\n <div class=\"flex-1\">\n <h4\n v-if=\"title\"\n class=\"mb-1 font-medium text-gray-900 dark:text-white\"\n >\n {{ title }}\n </h4>\n <div class=\"text-sm text-gray-700 dark:text-gray-300\">\n <slot />\n </div>\n </div>\n <button\n v-if=\"dismissible\"\n type=\"button\"\n class=\"shrink-0 rounded p-1 text-gray-400 hover:bg-gray-200 hover:text-gray-600 dark:hover:bg-gray-700 dark:hover:text-gray-300\"\n aria-label=\"Dismiss alert\"\n @click=\"emit('dismiss')\"\n >\n <Icon\n icon=\"lucide:x\"\n class=\"size-4\"\n aria-hidden=\"true\"\n />\n </button>\n </div>\n</template>\n","<script lang=\"ts\" setup>\nimport { Icon } from '@iconify/vue'\n\nwithDefaults(\n defineProps<{\n /** Message to display */\n message?: string\n /** Icon name (iconify format) */\n icon?: string\n /** Title text */\n title?: string\n }>(),\n {\n message: 'No results found',\n icon: 'lucide:inbox',\n },\n)\n</script>\n\n<template>\n <div class=\"py-12 text-center\">\n <Icon\n v-if=\"icon\"\n :icon=\"icon\"\n class=\"mx-auto mb-4 size-12 text-gray-400 dark:text-gray-500\"\n />\n <h3\n v-if=\"title\"\n class=\"mb-2 text-lg font-medium text-gray-900 dark:text-white\"\n >\n {{ title }}\n </h3>\n <p class=\"text-gray-500 dark:text-gray-400\">\n <slot>{{ message }}</slot>\n </p>\n <div\n v-if=\"$slots.action\"\n class=\"mt-4\"\n >\n <slot name=\"action\" />\n </div>\n </div>\n</template>\n","<script lang=\"ts\" setup>\r\nimport { Icon } from '@iconify/vue'\r\n\r\nexport type ToastType = 'success' | 'error' | 'warning' | 'info'\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n /** Toast message */\r\n message: string\r\n /** Toast type */\r\n type?: ToastType\r\n /** Title (optional) */\r\n title?: string\r\n /** Show close button */\r\n closable?: boolean\r\n /** Duration in ms (0 = no auto-close) */\r\n duration?: number\r\n }>(),\r\n {\r\n type: 'info',\r\n closable: true,\r\n duration: 5000,\r\n },\r\n)\r\n\r\nconst emit = defineEmits<{\r\n close: []\r\n}>()\r\n\r\nconst typeConfig: Record<ToastType, { icon: string; bg: string; iconColor: string }> = {\r\n success: {\r\n icon: 'lucide:check-circle',\r\n bg: 'bg-green-50 border-green-200 dark:bg-green-950 dark:border-green-800',\r\n iconColor: 'text-green-500',\r\n },\r\n error: {\r\n icon: 'lucide:x-circle',\r\n bg: 'bg-red-50 border-red-200 dark:bg-red-950 dark:border-red-800',\r\n iconColor: 'text-red-500',\r\n },\r\n warning: {\r\n icon: 'lucide:alert-triangle',\r\n bg: 'bg-yellow-50 border-yellow-200 dark:bg-yellow-950 dark:border-yellow-800',\r\n iconColor: 'text-yellow-500',\r\n },\r\n info: {\r\n icon: 'lucide:info',\r\n bg: 'bg-blue-50 border-blue-200 dark:bg-blue-950 dark:border-blue-800',\r\n iconColor: 'text-blue-500',\r\n },\r\n}\r\n\r\nconst config = typeConfig[props.type]\r\n\r\n// Auto-close\r\nif (props.duration > 0) {\r\n setTimeout(() => {\r\n emit('close')\r\n }, props.duration)\r\n}\r\n</script>\r\n\r\n<template>\r\n <div\r\n :class=\"[\r\n 'flex items-start gap-3 rounded-lg border p-4 shadow-lg',\r\n config.bg,\r\n ]\"\r\n role=\"alert\"\r\n >\r\n <Icon\r\n :icon=\"config.icon\"\r\n :class=\"['size-5 shrink-0', config.iconColor]\"\r\n aria-hidden=\"true\"\r\n />\r\n <div class=\"flex-1 min-w-0\">\r\n <p\r\n v-if=\"title\"\r\n class=\"font-medium text-gray-900 dark:text-white\"\r\n >\r\n {{ title }}\r\n </p>\r\n <p class=\"text-sm text-gray-700 dark:text-gray-300\">\r\n {{ message }}\r\n </p>\r\n </div>\r\n <button\r\n v-if=\"closable\"\r\n type=\"button\"\r\n class=\"shrink-0 rounded p-1 text-gray-400 hover:bg-gray-200 hover:text-gray-600 dark:hover:bg-gray-700 dark:hover:text-gray-300\"\r\n aria-label=\"Dismiss notification\"\r\n @click=\"emit('close')\"\r\n >\r\n <Icon\r\n icon=\"lucide:x\"\r\n class=\"size-4\"\r\n aria-hidden=\"true\"\r\n />\r\n </button>\r\n </div>\r\n</template>\r\n","<script lang=\"ts\" setup>\r\nimport { computed } from 'vue'\r\nimport Toast from './Toast.vue'\r\nimport type { ToastType } from './Toast.vue'\r\n\r\nexport interface ToastItem {\r\n id: string\r\n message: string\r\n type?: ToastType\r\n title?: string\r\n duration?: number\r\n}\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n /** Array of toast items */\r\n toasts: ToastItem[]\r\n /** Position of the container */\r\n position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'top-center' | 'bottom-center'\r\n /** Custom top offset (e.g., '80px', '5rem') to account for fixed headers */\r\n topOffset?: string\r\n }>(),\r\n {\r\n position: 'top-right',\r\n },\r\n)\r\n\r\nconst emit = defineEmits<{\r\n close: [id: string]\r\n}>()\r\n\r\nconst positionClasses: Record<string, string> = {\r\n 'top-right': 'right-4',\r\n 'top-left': 'left-4',\r\n 'bottom-right': 'bottom-4 right-4',\r\n 'bottom-left': 'bottom-4 left-4',\r\n 'top-center': 'left-1/2 -translate-x-1/2',\r\n 'bottom-center': 'bottom-4 left-1/2 -translate-x-1/2',\r\n}\r\n\r\nconst isTopPosition = computed(() => props.position?.startsWith('top'))\r\n\r\nconst topStyle = computed(() => {\r\n if (!isTopPosition.value) return {}\r\n return { top: props.topOffset || '1rem' }\r\n})\r\n</script>\r\n\r\n<template>\r\n <Teleport to=\"body\">\r\n <div\r\n :class=\"['fixed z-9999 flex flex-col gap-2 w-full max-w-sm', positionClasses[position]]\"\r\n :style=\"topStyle\"\r\n aria-live=\"polite\"\r\n aria-atomic=\"false\"\r\n >\r\n <TransitionGroup\r\n enter-active-class=\"transition duration-300 ease-out\"\r\n enter-from-class=\"opacity-0 translate-x-4\"\r\n enter-to-class=\"opacity-100 translate-x-0\"\r\n leave-active-class=\"transition duration-200 ease-in\"\r\n leave-from-class=\"opacity-100 translate-x-0\"\r\n leave-to-class=\"opacity-0 translate-x-4\"\r\n >\r\n <Toast\r\n v-for=\"toast in toasts\"\r\n :key=\"toast.id\"\r\n :message=\"toast.message\"\r\n :type=\"toast.type\"\r\n :title=\"toast.title\"\r\n :duration=\"toast.duration\"\r\n @close=\"emit('close', toast.id)\"\r\n />\r\n </TransitionGroup>\r\n </div>\r\n </Teleport>\r\n</template>\r\n","<script lang=\"ts\" setup>\r\nimport { computed } from 'vue'\r\n\r\nexport type ProgressSize = 'sm' | 'md' | 'lg'\r\nexport type ProgressVariant = 'default' | 'success' | 'warning' | 'error'\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n /** Current value (0-100) */\r\n value: number\r\n /** Maximum value */\r\n max?: number\r\n /** Size variant */\r\n size?: ProgressSize\r\n /** Color variant */\r\n variant?: ProgressVariant\r\n /** Show percentage label */\r\n showLabel?: boolean\r\n /** Striped animation */\r\n striped?: boolean\r\n /** Animated stripes */\r\n animated?: boolean\r\n /** Indeterminate state (loading) */\r\n indeterminate?: boolean\r\n }>(),\r\n {\r\n max: 100,\r\n size: 'md',\r\n variant: 'default',\r\n showLabel: false,\r\n striped: false,\r\n animated: false,\r\n indeterminate: false,\r\n },\r\n)\r\n\r\nconst percentage = computed(() => {\r\n if (props.indeterminate) return 100\r\n return Math.min(Math.max((props.value / props.max) * 100, 0), 100)\r\n})\r\n\r\nconst sizeClasses: Record<ProgressSize, string> = {\r\n sm: 'h-1',\r\n md: 'h-2',\r\n lg: 'h-4',\r\n}\r\n\r\nconst variantClasses: Record<ProgressVariant, string> = {\r\n default: 'bg-primary',\r\n success: 'bg-green-500',\r\n warning: 'bg-yellow-500',\r\n error: 'bg-red-500',\r\n}\r\n</script>\r\n\r\n<template>\r\n <div class=\"w-full\">\r\n <div\n v-if=\"showLabel && !indeterminate\"\n class=\"mb-1 flex justify-between text-sm\"\n >\r\n <span class=\"text-gray-600 dark:text-gray-400\">Progress</span>\r\n <span class=\"font-medium text-gray-900 dark:text-white\">{{ Math.round(percentage) }}%</span>\r\n </div>\r\n <div\r\n :class=\"[\r\n 'w-full overflow-hidden rounded-full bg-gray-200 dark:bg-gray-700',\r\n sizeClasses[size],\r\n ]\"\r\n role=\"progressbar\"\r\n :aria-valuenow=\"indeterminate ? undefined : value\"\r\n :aria-valuemin=\"0\"\r\n :aria-valuemax=\"max\"\r\n >\r\n <div\r\n :class=\"[\r\n 'h-full rounded-full transition-all duration-300',\r\n variantClasses[variant],\r\n striped && 'bg-stripes',\r\n animated && 'animate-stripes',\r\n indeterminate && 'animate-indeterminate',\r\n ]\"\r\n :style=\"{ width: indeterminate ? '30%' : `${percentage}%` }\"\r\n />\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<style scoped>\r\n.bg-stripes {\r\n background-image: linear-gradient(\r\n 45deg,\r\n rgba(255, 255, 255, 0.15) 25%,\r\n transparent 25%,\r\n transparent 50%,\r\n rgba(255, 255, 255, 0.15) 50%,\r\n rgba(255, 255, 255, 0.15) 75%,\r\n transparent 75%,\r\n transparent\r\n );\r\n background-size: 1rem 1rem;\r\n}\r\n\r\n.animate-stripes {\r\n animation: stripes 1s linear infinite;\r\n}\r\n\r\n@keyframes stripes {\r\n from {\r\n background-position: 1rem 0;\r\n }\r\n to {\r\n background-position: 0 0;\r\n }\r\n}\r\n\r\n.animate-indeterminate {\r\n animation: indeterminate 1.5s ease-in-out infinite;\r\n}\r\n\r\n@keyframes indeterminate {\r\n 0% {\r\n transform: translateX(-100%);\r\n }\r\n 100% {\r\n transform: translateX(400%);\r\n }\r\n}\r\n</style>\r\n","<script lang=\"ts\" setup>\r\nexport type SkeletonVariant = 'text' | 'circular' | 'rectangular' | 'rounded'\r\n\r\nwithDefaults(\r\n defineProps<{\r\n /** Variant style */\r\n variant?: SkeletonVariant\r\n /** Width (CSS value) */\r\n width?: string\r\n /** Height (CSS value) */\r\n height?: string\r\n /** Number of lines (for text variant) */\r\n lines?: number\r\n /** Animate the skeleton */\r\n animate?: boolean\r\n }>(),\r\n {\r\n variant: 'text',\r\n animate: true,\r\n lines: 1,\r\n },\r\n)\r\n\r\nconst variantClasses: Record<SkeletonVariant, string> = {\r\n text: 'h-4 rounded',\r\n circular: 'rounded-full',\r\n rectangular: '',\r\n rounded: 'rounded-lg',\r\n}\r\n</script>\r\n\r\n<template>\r\n <div\r\n v-if=\"variant === 'text' && lines > 1\"\r\n class=\"space-y-2\"\r\n aria-hidden=\"true\"\r\n >\r\n <div\r\n v-for=\"i in lines\"\r\n :key=\"i\"\r\n :class=\"[\r\n 'bg-gray-200 dark:bg-gray-700',\r\n variantClasses[variant],\r\n animate && 'animate-pulse',\r\n ]\"\r\n :style=\"{\r\n width: i === lines ? '75%' : width || '100%',\r\n height: height,\r\n }\"\r\n />\r\n </div>\r\n <div\r\n v-else\r\n :class=\"[\r\n 'bg-gray-200 dark:bg-gray-700',\r\n variantClasses[variant],\r\n animate && 'animate-pulse',\r\n ]\"\r\n :style=\"{\r\n width: width || (variant === 'circular' ? '3rem' : '100%'),\r\n height: height || (variant === 'circular' ? '3rem' : variant === 'text' ? '1rem' : '6rem'),\r\n }\"\r\n aria-hidden=\"true\"\r\n />\r\n</template>\r\n","<script lang=\"ts\" setup>\r\nimport { Icon } from '@iconify/vue'\r\nimport Modal from './Modal.vue'\r\nimport Button from '@/components/core/Button.vue'\r\n\r\nexport type ConfirmDialogVariant = 'info' | 'warning' | 'danger' | 'success'\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n /** Whether the dialog is open */\r\n open?: boolean\r\n /** Dialog title */\r\n title?: string\r\n /** Dialog message */\r\n message?: string\r\n /** Confirm button text */\r\n confirmText?: string\r\n /** Cancel button text */\r\n cancelText?: string\r\n /** Dialog variant (affects icon and confirm button color) */\r\n variant?: ConfirmDialogVariant\r\n /** Show loading state on confirm button */\r\n loading?: boolean\r\n /** Icon to display */\r\n icon?: string\r\n /** Teleport target (e.g., 'body', '#app'). Set to false to disable teleport. */\r\n teleport?: string | false\r\n }>(),\r\n {\r\n open: false,\r\n title: 'Confirm',\r\n message: 'Are you sure you want to proceed?',\r\n confirmText: 'Confirm',\r\n cancelText: 'Cancel',\r\n variant: 'info',\r\n loading: false,\r\n teleport: 'body',\r\n },\r\n)\r\n\r\nconst emit = defineEmits<{\r\n confirm: []\r\n cancel: []\r\n}>()\r\n\r\nconst variantConfig: Record<ConfirmDialogVariant, { icon: string; iconClass: string; buttonVariant: 'primary' | 'danger' | 'success' }> = {\r\n info: {\r\n icon: 'lucide:info',\r\n iconClass: 'text-blue-500',\r\n buttonVariant: 'primary',\r\n },\r\n warning: {\r\n icon: 'lucide:alert-triangle',\r\n iconClass: 'text-yellow-500',\r\n buttonVariant: 'primary',\r\n },\r\n danger: {\r\n icon: 'lucide:alert-circle',\r\n iconClass: 'text-red-500',\r\n buttonVariant: 'danger',\r\n },\r\n success: {\r\n icon: 'lucide:check-circle',\r\n iconClass: 'text-green-500',\r\n buttonVariant: 'success',\r\n },\r\n}\r\n\r\nconst config = variantConfig[props.variant]\r\n</script>\r\n\r\n<template>\r\n <Modal\r\n v-if=\"open\"\r\n size=\"sm\"\r\n :close-on-backdrop=\"!loading\"\r\n :close-on-escape=\"!loading\"\r\n :teleport=\"teleport\"\r\n @close=\"emit('cancel')\"\r\n >\r\n <div class=\"text-center\">\r\n <!-- Icon -->\r\n <div class=\"mx-auto mb-4 flex size-14 items-center justify-center rounded-full bg-gray-100 dark:bg-gray-800\">\r\n <Icon\r\n :icon=\"icon || config.icon\"\r\n :class=\"[config.iconClass, 'size-8']\"\r\n />\r\n </div>\r\n\r\n <!-- Title -->\r\n <h3 class=\"mb-2 text-lg font-semibold text-gray-900 dark:text-gray-100\">\r\n {{ title }}\r\n </h3>\r\n\r\n <!-- Message -->\r\n <p class=\"mb-6 text-gray-600 dark:text-gray-400\">\r\n <slot>{{ message }}</slot>\r\n </p>\r\n\r\n <!-- Actions -->\r\n <div class=\"flex justify-center gap-3\">\r\n <Button\r\n variant=\"outline\"\r\n :disabled=\"loading\"\r\n @click=\"emit('cancel')\"\r\n >\r\n {{ cancelText }}\r\n </Button>\r\n <Button\r\n :variant=\"config.buttonVariant\"\r\n :loading=\"loading\"\r\n @click=\"emit('confirm')\"\r\n >\r\n {{ confirmText }}\r\n </Button>\r\n </div>\r\n </div>\r\n </Modal>\r\n</template>\r\n"],"names":["computed","_createElementBlock","_createElementVNode","_hoisted_2","_normalizeClass","_hoisted_3","_toDisplayString","_hoisted_4","useId","ref","useFocusTrap","onMounted","onUnmounted","_createBlock","_Teleport","_unref","$slots","_openBlock","_renderSlot","_createVNode","Icon","_hoisted_5","_hoisted_6","_hoisted_1","_Fragment","_renderList","_TransitionGroup","NotificationComponent","Toast","_normalizeStyle","Modal","Button"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAIA,UAAM,QAAQ;AAad,UAAM,cAA2C;AAAA,MAC/C,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IAAA;AAGN,UAAM,kBAAkBA,IAAAA,SAAS,MAAM,MAAM,QAAQ,MAAM,SAAS;;8BAIlEC,IAAAA,mBAoBM,OAAA;AAAA,QAnBJ,OAAM;AAAA,QACN,MAAK;AAAA,QACL,aAAU;AAAA,QACT,cAAY,gBAAA;AAAA,MAAA;QAEbC,IAAAA,mBAaM,OAbNC,cAaM;AAAA,UAZJD,IAAAA,mBAIE,OAAA;AAAA,YAHC,OAAKE,IAAAA,eAAA,CAAE,YAAY,QAAA,IAAI,GAClB,kGAAkG,CAAA;AAAA,YACxG,eAAY;AAAA,UAAA;UAGN,QAAA,yBADRH,IAAAA,mBAKI,KALJI,cAKIC,IAAAA,gBADC,QAAA,IAAI,GAAA,CAAA,uBAETL,IAAAA,mBAAyD,QAAzDM,cAAyDD,IAAAA,gBAAzB,gBAAA,KAAe,GAAA,CAAA;AAAA,QAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACtCrD,UAAM,QAAQ;AAsBd,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA,IACE;AAEJ,UAAM,mBAAmBN,IAAAA,SAAS,MAAM,MAAM,aAAa,KAAK;AAChE,UAAM,iBAAiBA,IAAAA,SAAS,MAAM,MAAM,aAAa,QAAQ,SAAS,MAAM,QAAQ;AAExF,UAAM,OAAO;AAKb,UAAM,EAAE,IAAI,SAAS,QAAA,IAAYQ,MAAAA,MAAM,EAAE,QAAQ,SAAS,IAAI,MAAM,GAAA,CAAI;AACxE,UAAM,UAAUR,IAAAA,SAAS,MAAM,QAAQ,OAAO,CAAC;AAG/C,UAAM,WAAWS,IAAAA,IAAI,IAAI;AACzB,UAAM,EAAE,cAAc,UAAA,IAAcC,0BAAa;AAAA,MAC/C,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,cAAc;AAAA,IAAA,CACf;AAGD,UAAM,WAAWV,IAAAA,SAAS,MAAM,QAAQ,MAAM,KAAK,CAAC;AAEpD,UAAM,cAAyC;AAAA,MAC7C,IAAI;AAAA,MACJ,SAAS;AAAA,MACT,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,MAAM;AAAA,IAAA;AAGR,UAAM,sBAAsB,MAAM;AAChC,UAAI,iBAAiB;AACnB,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAEA,UAAM,eAAe,CAAC,MAAqB;AACzC,UAAI,EAAE,QAAQ,YAAY,eAAe;AACvC,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAEAW,QAAAA,UAAU,MAAM;AACd,eAAS,iBAAiB,WAAW,YAAY;AACjD,eAAS,KAAK,MAAM,WAAW;AAAA,IACjC,CAAC;AAEDC,QAAAA,YAAY,MAAM;AAChB,eAAS,oBAAoB,WAAW,YAAY;AACpD,eAAS,KAAK,MAAM,WAAW;AAAA,IACjC,CAAC;;8BAICC,IAAAA,YA0DWC,cAAA;AAAA,QA1DA,IAAI,eAAA;AAAA,QAAiB,UAAU,iBAAA;AAAA,MAAA;QACxCZ,IAAAA,mBAwDM,OAAA;AAAA,UAvDJ,OAAM;AAAA,UACL,2BAAY,qBAAmB,CAAA,MAAA,CAAA;AAAA,QAAA;UAEhCA,IAAAA,mBAmDM,OAAA;AAAA,qBAlDA;AAAA,YAAJ,KAAI;AAAA,YACH,IAAIa,IAAAA,MAAA,OAAA;AAAA,YACL,MAAK;AAAA,YACL,cAAW;AAAA,YACV,mBAAiB,SAAA,QAAW,QAAA,QAAU;AAAA,YACtC,OAAKX,IAAAA,eAAA,CAAE,YAAYW,IAAAA,MAAA,IAAA,CAAI,GAClB,kFAAkF,CAAA;AAAA,UAAA;YAIhFA,IAAAA,MAAA,KAAA,KAASC,KAAAA,OAAO,UAAUA,KAAAA,OAAO,SADzCC,IAAAA,UAAA,GAAAhB,IAAAA,mBA2BM,OA3BNE,cA2BM;AAAA,cAvBJD,IAAAA,mBASK,MAAA;AAAA,gBARF,IAAI,QAAA;AAAA,gBACL,OAAM;AAAA,cAAA;gBAENgB,IAAAA,WAIO,2BAJP,MAIO;AAAA,kBAHLA,IAAAA,WAEO,0BAFP,MAEO;AAAA,4DADFH,IAAAA,MAAA,KAAA,CAAK,GAAA,CAAA;AAAA,kBAAA;;;cAIdb,IAAAA,mBAYS,UAAA;AAAA,gBAXP,OAAM;AAAA,gBACN,MAAK;AAAA,gBACL,cAAW;AAAA,gBACV,+CAAO,KAAI,OAAA;AAAA,cAAA;gBAEZiB,gBAIEJ,IAAAA,MAAAK,MAAAA,IAAA,GAAA;AAAA,kBAHA,OAAM;AAAA,kBACN,MAAK;AAAA,kBACL,eAAY;AAAA,gBAAA;gBAEdlB,IAAAA,mBAAmD,QAAnDK,cAAmDD,IAAAA,gBAA1BS,IAAAA,MAAA,gBAAA,CAAgB,GAAA,CAAA;AAAA,cAAA;;YAK7Cb,IAAAA,mBAEM,OAFNmB,cAEM;AAAA,cADJH,eAAQ,KAAA,QAAA,SAAA;AAAA,YAAA;YAKFF,KAAAA,OAAO,UADfC,IAAAA,aAAAhB,IAAAA,mBAKM,OALNqB,cAKM;AAAA,cADJJ,eAAsB,KAAA,QAAA,QAAA;AAAA,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC7GhC,UAAM,eAAelB,IAAAA,SAAqB,MAAM;AAC9C,UAAI,QAAA,cAAc,QAAA,iBAAiB;AACjC,eAAO,MAAM,KAAK,EAAE,QAAQ,QAAA,WAAA,GAAc,CAAC,GAAG,MAAM,IAAI,CAAC;AAAA,MAC3D;AAEA,YAAM,QAAoB,CAAA;AAC1B,YAAM,YAAY,KAAK,OAAO,0BAAkB,KAAK,CAAC;AAGtD,YAAM,KAAK,CAAC;AAGZ,UAAI,aAAa,KAAK,IAAI,GAAG,sBAAc,SAAS;AACpD,UAAI,WAAW,KAAK,IAAI,qBAAa,GAAG,QAAA,cAAc,SAAS;AAG/D,UAAI,uBAAe,YAAY,GAAG;AAChC,mBAAW,KAAK,IAAI,QAAA,aAAa,GAAG,QAAA,kBAAkB,CAAC;AAAA,MACzD,WAAW,QAAA,eAAe,QAAA,aAAa,YAAY,GAAG;AACpD,qBAAa,KAAK,IAAI,GAAG,QAAA,aAAa,QAAA,kBAAkB,CAAC;AAAA,MAC3D;AAGA,UAAI,aAAa,GAAG;AAClB,cAAM,KAAK,gBAAgB;AAAA,MAC7B;AAGA,eAAS,IAAI,YAAY,KAAK,UAAU,KAAK;AAC3C,cAAM,KAAK,CAAC;AAAA,MACd;AAGA,UAAI,WAAW,QAAA,aAAa,GAAG;AAC7B,cAAM,KAAK,cAAc;AAAA,MAC3B;AAGA,UAAI,QAAA,aAAa,GAAG;AAClB,cAAM,KAAK,kBAAU;AAAA,MACvB;AAEA,aAAO;AAAA,IACT,CAAC;AAED,UAAM,OAAO;AAKb,UAAM,aAAa,CAAC,SAAiB;AACnC,UAAI,QAAQ,KAAK,QAAQ,QAAA,cAAc,CAAC,QAAA,SAAS;AAC/C,aAAK,eAAe,IAAI;AAAA,MAC1B;AAAA,IACF;AAEA,UAAM,iBAAiB,CAAC,UAAiB;AACvC,YAAM,SAAS,MAAM;AACrB,WAAK,mBAAmB,OAAO,OAAO,KAAK,CAAC;AAAA,IAC9C;;aAKU,QAAA,aAAU,KADlBiB,IAAAA,aAAAhB,IAAAA,mBA+FM,OA/FNsB,cA+FM;AAAA,QA1FJrB,IAAAA,mBA6BM,OA7BNC,cA6BM;AAAA,UA5BJD,uBAEM,OAFNG,cAEMC,oBADD,QAAA,SAAS,IAAG,MAACA,IAAAA,gBAAG,QAAA,WAAW,IAAG,MAACA,IAAAA,gBAAG,QAAA,OAAO,IAAG,0BAAI,QAAA,UAAU,GAAA,CAAA;AAAA,UAGvD,QAAA,gBADRW,IAAAA,UAAA,GAAAhB,IAAAA,mBAwBM,OAxBNM,cAwBM;AAAA,YApBJL,IAAAA,mBAKQ,SALRmB,cAKQf,IAAAA,gBADH,QAAA,iBAAiB,GAAA,CAAA;AAAA,YAEtBJ,IAAAA,mBAaS,UAAA;AAAA,cAZP,IAAG;AAAA,cACF,OAAO,QAAA;AAAA,cACR,OAAM;AAAA,cACL,UAAQ;AAAA,YAAA;oCAETD,IAAAA,mBAMSuB,IAAAA,UAAA,MAAAC,IAAAA,WALQ,QAAA,iBAAe,CAAvB,SAAI;wCADbxB,IAAAA,mBAMS,UAAA;AAAA,kBAJN,KAAK;AAAA,kBACL,OAAO;AAAA,gBAAA,uBAEL,IAAI,GAAA,GAAA,UAAA;AAAA;;;;QAOfC,IAAAA,mBAyDM,OAzDN,YAyDM;AAAA,UAvDJA,IAAAA,mBAUS,UAAA;AAAA,YATN,UAAU,QAAA,gBAAW,KAAU,QAAA;AAAA,YAChC,OAAM;AAAA,YACL,SAAK,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA,CAAA,WAAE,WAAW,QAAA,cAAW,CAAA;AAAA,UAAA;YAE9BiB,gBAGEJ,IAAAA,MAAAK,MAAAA,IAAA,GAAA;AAAA,cAFA,OAAM;AAAA,cACN,MAAK;AAAA,YAAA;YAEPlB,IAAAA,mBAAyD,QAAzD,aAAyDI,IAAAA,gBAAvB,QAAA,aAAa,GAAA,CAAA;AAAA,UAAA;UAIjC,QAAA,wCACdL,IAAAA,mBA0BWuB,IAAAA,UAAA,EAAA,KAAA,KAAAC,IAAAA,WAzBM,aAAA,OAAY,CAApB,SAAI;gFACL,QAAI;AAAA,cAIF,6BAA6B,SAAI,mCADzCxB,IAAAA,mBAKO,QALP,aAGC,KAED,uBAEAA,IAAAA,mBAaS,UAAA;AAAA;gBAXN,UAAU,QAAA;AAAA,gBACV,OAAKG,IAAAA,eAAA;AAAA;kBAAoH,SAAS,QAAA;kBAAuS,QAAA,UAAO,kCAAA;AAAA,gBAAA;gBAOhb,SAAK,CAAA,WAAE,WAAW,IAAI;AAAA,cAAA,uBAEpB,IAAI,GAAA,IAAA,WAAA;AAAA,YAAA;;UAMbF,IAAAA,mBAUS,UAAA;AAAA,YATN,UAAU,QAAA,gBAAgB,QAAA,cAAc,QAAA;AAAA,YACzC,OAAM;AAAA,YACL,SAAK,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA,CAAA,WAAE,WAAW,QAAA,cAAW,CAAA;AAAA,UAAA;YAE9BA,IAAAA,mBAAqD,QAArD,aAAqDI,IAAAA,gBAAnB,QAAA,SAAS,GAAA,CAAA;AAAA,YAC3Ca,gBAGEJ,IAAAA,MAAAK,MAAAA,IAAA,GAAA;AAAA,cAFA,OAAM;AAAA,cACN,MAAK;AAAA,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;;ACzLf,UAAM,QAAQ;AAMd,UAAM,OAAO;AAIb,UAAM,WAAWpB,IAAAA,SAAS,MAAM;AAC9B,cAAQ,MAAM,aAAa,MAAA;AAAA,QACzB,KAAK;AACH,iBAAO;AAAA,QACT,KAAK;AACH,iBAAO;AAAA,QACT,KAAK;AACH,iBAAO;AAAA,QACT,KAAK;AACH,iBAAO;AAAA,QACT;AACE,iBAAO;AAAA,MAAA;AAAA,IAEb,CAAC;AAED,UAAM,YAAYA,IAAAA,SAAS,MAAM;AAC/B,cAAQ,MAAM,aAAa,MAAA;AAAA,QACzB,KAAK;AACH,iBAAO;AAAA,QACT,KAAK;AACH,iBAAO;AAAA,QACT,KAAK;AACH,iBAAO;AAAA,QACT,KAAK;AACH,iBAAO;AAAA,QACT;AACE,iBAAO;AAAA,MAAA;AAAA,IAEb,CAAC;AAED,UAAM,UAAUA,IAAAA,SAAS,MAAM;AAC7B,cAAQ,MAAM,aAAa,MAAA;AAAA,QACzB,KAAK;AACH,iBAAO;AAAA,QACT,KAAK;AACH,iBAAO;AAAA,QACT,KAAK;AACH,iBAAO;AAAA,QACT,KAAK;AACH,iBAAO;AAAA,QACT;AACE,iBAAO;AAAA,MAAA;AAAA,IAEb,CAAC;AAED,UAAM,gBAAgB,MAAM;AAC1B,UAAI,MAAM,aAAa,IAAI;AACzB,aAAK,WAAW,MAAM,aAAa,EAAE;AAAA,MACvC;AAAA,IACF;AAEAW,QAAAA,UAAU,MAAM;AACd,YAAM,WAAW,MAAM,aAAa,YAAY,MAAM,YAAY;AAClE,UAAI,MAAM,gBAAgB,SAAS,WAAW,GAAG;AAC/C,mBAAW,MAAM;AACf,wBAAA;AAAA,QACF,GAAG,QAAQ;AAAA,MACb;AAAA,IACF,CAAC;;AAIC,aAAAM,cAAA,GAAAhB,uBAmCM,OAnCNsB,cAmCM;AAAA,QAhCJrB,IAAAA,mBAMM,OAAA;AAAA,UANA,2BAAQ,QAAA,OAAO,mDAAA,CAAA;AAAA,QAAA;UACnBiB,gBAIEJ,IAAAA,MAAAK,MAAAA,IAAA,GAAA;AAAA,YAHC,OAAKhB,IAAAA,eAAA,CAAE,UAAA,OAEF,QAAQ,CAAA;AAAA,YADb,MAAM,SAAA;AAAA,UAAA;;QAKXF,IAAAA,mBAaM,OAbNC,cAaM;AAAA,UAXI,QAAA,aAAa,SADrBc,IAAAA,UAAA,GAAAhB,IAAAA,mBAKK,MALLI,cAKKC,IAAAA,gBADA,QAAA,aAAa,KAAK,GAAA,CAAA;UAGf,QAAA,aAAa,WADrBW,IAAAA,UAAA,GAAAhB,IAAAA,mBAKI,KALJM,cAKID,IAAAA,gBADC,QAAA,aAAa,OAAO,GAAA,CAAA;;QAI3BJ,IAAAA,mBAQS,UAAA;AAAA,UAPP,OAAM;AAAA,UACL,SAAO;AAAA,QAAA;UAERiB,gBAGEJ,IAAAA,MAAAK,MAAAA,IAAA,GAAA;AAAA,YAFA,OAAM;AAAA,YACN,MAAK;AAAA,UAAA;;;;;;;;;;;;;;;;;ACxGb,UAAM,QAAQ;AAed,UAAM,OAAO;AAIb,UAAM,kBAA0C;AAAA,MAC9C,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,eAAe;AAAA,IAAA;AAGjB,UAAM,gBAAgBpB,IAAAA,SAAS,MAAA;;AAAM,yBAAM,aAAN,mBAAgB,WAAW;AAAA,KAAM;AAEtE,UAAM,WAAWA,IAAAA,SAAS,MAAM;AAC9B,UAAI,CAAC,cAAc,SAAS,CAAC,MAAM,kBAAkB,CAAA;AACrD,aAAO,EAAE,KAAK,MAAM,UAAA;AAAA,IACtB,CAAC;;8BAICa,IAAAA,YAuBWC,IAAAA,UAAA,EAvBD,IAAG,UAAM;AAAA,QACjBZ,IAAAA,mBAqBM,OAAA;AAAA,UApBH,OAAKE,IAAAA,eAAA,CAAA,kDAAqD,gBAAgB,QAAA,QAAQ,CAAA,CAAA;AAAA,UAClF,0BAAO,SAAA,KAAQ;AAAA,QAAA;UAEhBe,IAAAA,YAgBkBO,IAAAA,iBAAA;AAAA,YAfhB,sBAAmB;AAAA,YACnB,oBAAiB;AAAA,YACjB,kBAAe;AAAA,YACf,sBAAmB;AAAA,YACnB,oBAAiB;AAAA,YACjB,kBAAe;AAAA,UAAA;iCAGb,MAAqC;AAAA,oCADvCzB,IAAAA,mBAOEuB,IAAAA,UAAA,MAAAC,IAAAA,WANuB,QAAA,eAAa,CAA7B,iBAAY;wCADrBZ,IAAAA,YAOEc,aAAA;AAAA,kBALC,KAAK,aAAa;AAAA,kBAClB;AAAA,kBACA,gBAAc,QAAA;AAAA,kBACd,UAAU,QAAA;AAAA,kBACV,WAAO,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA,CAAA,WAAE,KAAI,WAAY,MAAM;AAAA,gBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;ACtD1C,UAAM,QAAQ;AAgBd,UAAM,OAAO;AAIb,UAAM,gBAAuG;AAAA,MAC3G,MAAM;AAAA,QACJ,IAAI;AAAA,QACJ,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,WAAW;AAAA,MAAA;AAAA,MAEb,SAAS;AAAA,QACP,IAAI;AAAA,QACJ,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,WAAW;AAAA,MAAA;AAAA,MAEb,SAAS;AAAA,QACP,IAAI;AAAA,QACJ,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,WAAW;AAAA,MAAA;AAAA,MAEb,OAAO;AAAA,QACL,IAAI;AAAA,QACJ,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,WAAW;AAAA,MAAA;AAAA,IACb;AAGF,UAAM,SAAS,cAAc,MAAM,OAAO;;8BAIxC1B,IAAAA,mBAqCM,OAAA;AAAA,QApCH,OAAKG,IAAAA,eAAA;AAAA;UAAoDW,IAAAA,MAAA,MAAA,EAAO;AAAA,UAAUA,IAAAA,MAAA,MAAA,EAAO;AAAA,QAAA;QAKlF,MAAK;AAAA,MAAA;QAELI,gBAIEJ,IAAAA,MAAAK,MAAAA,IAAA,GAAA;AAAA,UAHC,MAAM,QAAA,QAAQL,IAAAA,MAAA,MAAA,EAAO;AAAA,UACrB,OAAKX,IAAAA,eAAA,CAAA,mBAAsBW,IAAAA,MAAA,MAAA,EAAO,SAAS,CAAA;AAAA,UAC5C,eAAY;AAAA,QAAA;QAEdb,IAAAA,mBAUM,OAVNqB,cAUM;AAAA,UARI,QAAA,0BADRtB,IAAAA,mBAKK,MALLE,cAKKG,IAAAA,gBADA,QAAA,KAAK,GAAA,CAAA;UAEVJ,IAAAA,mBAEM,OAFNG,cAEM;AAAA,YADJa,eAAQ,KAAA,QAAA,SAAA;AAAA,UAAA;;QAIJ,QAAA,gCADRjB,IAAAA,mBAYS,UAAA;AAAA;UAVP,MAAK;AAAA,UACL,OAAM;AAAA,UACN,cAAW;AAAA,UACV,+CAAO,KAAI,SAAA;AAAA,QAAA;UAEZkB,gBAIEJ,IAAAA,MAAAK,MAAAA,IAAA,GAAA;AAAA,YAHA,MAAK;AAAA,YACL,OAAM;AAAA,YACN,eAAY;AAAA,UAAA;;;;;;;;;;;;;;;;;;;;;;;;;ACtElB,aAAAH,cAAA,GAAAhB,uBAqBM,OArBNsB,cAqBM;AAAA,QAnBI,QAAA,yBADRV,IAAAA,YAIEE,IAAAA,MAAAK,MAAAA,IAAA,GAAA;AAAA;UAFC,MAAM,QAAA;AAAA,UACP,OAAM;AAAA,QAAA;QAGA,QAAA,0BADRnB,IAAAA,mBAKK,MALLE,cAKKG,IAAAA,gBADA,QAAA,KAAK,GAAA,CAAA;QAEVJ,IAAAA,mBAEI,KAFJG,cAEI;AAAA,UADFa,IAAAA,WAA0B,4BAA1B,MAA0B;AAAA,oDAAjB,QAAA,OAAO,GAAA,CAAA;AAAA,UAAA;;QAGVF,KAAAA,OAAO,UADfC,IAAAA,aAAAhB,IAAAA,mBAKM,OALNM,cAKM;AAAA,UADJW,eAAsB,KAAA,QAAA,QAAA;AAAA,QAAA;;;;;;;;;;;;;;;;;;;;;;AClC5B,UAAM,QAAQ;AAoBd,UAAM,OAAO;AAIb,UAAM,aAAiF;AAAA,MACrF,SAAS;AAAA,QACP,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,WAAW;AAAA,MAAA;AAAA,MAEb,OAAO;AAAA,QACL,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,WAAW;AAAA,MAAA;AAAA,MAEb,SAAS;AAAA,QACP,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,WAAW;AAAA,MAAA;AAAA,MAEb,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,WAAW;AAAA,MAAA;AAAA,IACb;AAGF,UAAM,SAAS,WAAW,MAAM,IAAI;AAGpC,QAAI,MAAM,WAAW,GAAG;AACtB,iBAAW,MAAM;AACf,aAAK,OAAO;AAAA,MACd,GAAG,MAAM,QAAQ;AAAA,IACnB;;8BAIEjB,IAAAA,mBAoCM,OAAA;AAAA,QAnCH,OAAKG,IAAAA,eAAA;AAAA;UAA4EW,IAAAA,MAAA,MAAA,EAAO;AAAA,QAAA;QAIzF,MAAK;AAAA,MAAA;QAELI,gBAIEJ,IAAAA,MAAAK,MAAAA,IAAA,GAAA;AAAA,UAHC,MAAML,IAAAA,MAAA,MAAA,EAAO;AAAA,UACb,OAAKX,IAAAA,eAAA,CAAA,mBAAsBW,IAAAA,MAAA,MAAA,EAAO,SAAS,CAAA;AAAA,UAC5C,eAAY;AAAA,QAAA;QAEdb,IAAAA,mBAUM,OAVNqB,cAUM;AAAA,UARI,QAAA,0BADRtB,IAAAA,mBAKI,KALJE,cAKIG,IAAAA,gBADC,QAAA,KAAK,GAAA,CAAA;UAEVJ,IAAAA,mBAEI,KAFJG,cAEIC,IAAAA,gBADC,QAAA,OAAO,GAAA,CAAA;AAAA,QAAA;QAIN,QAAA,6BADRL,IAAAA,mBAYS,UAAA;AAAA;UAVP,MAAK;AAAA,UACL,OAAM;AAAA,UACN,cAAW;AAAA,UACV,+CAAO,KAAI,OAAA;AAAA,QAAA;UAEZkB,gBAIEJ,IAAAA,MAAAK,MAAAA,IAAA,GAAA;AAAA,YAHA,MAAK;AAAA,YACL,OAAM;AAAA,YACN,eAAY;AAAA,UAAA;;;;;;;;;;;;;;;ACnFpB,UAAM,QAAQ;AAcd,UAAM,OAAO;AAIb,UAAM,kBAA0C;AAAA,MAC9C,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,eAAe;AAAA,MACf,cAAc;AAAA,MACd,iBAAiB;AAAA,IAAA;AAGnB,UAAM,gBAAgBpB,IAAAA,SAAS,MAAA;;AAAM,yBAAM,aAAN,mBAAgB,WAAW;AAAA,KAAM;AAEtE,UAAM,WAAWA,IAAAA,SAAS,MAAM;AAC9B,UAAI,CAAC,cAAc,MAAO,QAAO,CAAA;AACjC,aAAO,EAAE,KAAK,MAAM,aAAa,OAAA;AAAA,IACnC,CAAC;;8BAICa,IAAAA,YA0BWC,IAAAA,UAAA,EA1BD,IAAG,UAAM;AAAA,QACjBZ,IAAAA,mBAwBM,OAAA;AAAA,UAvBH,OAAKE,IAAAA,eAAA,CAAA,oDAAuD,gBAAgB,QAAA,QAAQ,CAAA,CAAA;AAAA,UACpF,0BAAO,SAAA,KAAQ;AAAA,UAChB,aAAU;AAAA,UACV,eAAY;AAAA,QAAA;UAEZe,IAAAA,YAiBkBO,IAAAA,iBAAA;AAAA,YAhBhB,sBAAmB;AAAA,YACnB,oBAAiB;AAAA,YACjB,kBAAe;AAAA,YACf,sBAAmB;AAAA,YACnB,oBAAiB;AAAA,YACjB,kBAAe;AAAA,UAAA;iCAGb,MAAuB;AAAA,oCADzBzB,IAAAA,mBAQEuB,IAAAA,UAAA,MAAAC,IAAAA,WAPgB,QAAA,QAAM,CAAf,UAAK;wCADdZ,IAAAA,YAQEe,aAAA;AAAA,kBANC,KAAK,MAAM;AAAA,kBACX,SAAS,MAAM;AAAA,kBACf,MAAM,MAAM;AAAA,kBACZ,OAAO,MAAM;AAAA,kBACb,UAAU,MAAM;AAAA,kBAChB,SAAK,CAAA,WAAE,KAAI,SAAU,MAAM,EAAE;AAAA,gBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACjExC,UAAM,QAAQ;AA8Bd,UAAM,aAAa5B,IAAAA,SAAS,MAAM;AAChC,UAAI,MAAM,cAAe,QAAO;AAChC,aAAO,KAAK,IAAI,KAAK,IAAK,MAAM,QAAQ,MAAM,MAAO,KAAK,CAAC,GAAG,GAAG;AAAA,IACnE,CAAC;AAED,UAAM,cAA4C;AAAA,MAChD,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IAAA;AAGN,UAAM,iBAAkD;AAAA,MACtD,SAAS;AAAA,MACT,SAAS;AAAA,MACT,SAAS;AAAA,MACT,OAAO;AAAA,IAAA;;AAKP,aAAAiB,cAAA,GAAAhB,uBA6BM,OA7BNsB,cA6BM;AAAA,QA3BI,QAAA,cAAc,QAAA,iBADtBN,IAAAA,aAAAhB,IAAAA,mBAMM,OANNE,cAMM;AAAA,UAFJ,OAAA,CAAA,MAAA,OAAA,CAAA,IAAAD,IAAAA,mBAA8D,QAAA,EAAxD,OAAM,mCAAA,GAAmC,YAAQ,EAAA;AAAA,UACvDA,IAAAA,mBAA4F,QAA5FG,cAA4FC,IAAAA,gBAAjC,KAAK,MAAM,WAAA,KAAU,CAAA,IAAI,KAAC,CAAA;AAAA,QAAA;QAEvFJ,IAAAA,mBAoBM,OAAA;AAAA,UAnBH,OAAKE,IAAAA,eAAA;AAAA;YAA0F,YAAY,QAAA,IAAI;AAAA,UAAA;UAIhH,MAAK;AAAA,UACJ,iBAAe,QAAA,gBAAgB,SAAY,QAAA;AAAA,UAC3C,iBAAe;AAAA,UACf,iBAAe,QAAA;AAAA,QAAA;UAEhBF,IAAAA,mBASE,OAAA;AAAA,YARC,OAAKE,IAAAA,eAAA;AAAA;cAA6E,eAAe,QAAA,OAAO;AAAA,cAAc,QAAA,WAAO;AAAA,cAA6B,QAAA,YAAQ;AAAA,cAAkC,QAAA,iBAAa;AAAA,YAAA;YAOjN,OAAKyB,IAAAA,eAAA,EAAA,OAAW,QAAA,gBAAa,QAAA,GAAc,WAAA,KAAU,IAAA,CAAA;AAAA,UAAA;;;;;;;;;;;;;;;;;;;;;;AC3D9D,UAAM,iBAAkD;AAAA,MACtD,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa;AAAA,MACb,SAAS;AAAA,IAAA;;AAMD,aAAA,QAAA,sBAAsB,QAAA,QAAK,KADnCZ,cAAA,GAAAhB,uBAkBM,OAlBNsB,cAkBM;AAAA,8BAbJtB,IAAAA,mBAYEuB,IAAAA,UAAA,MAAAC,IAAAA,WAXY,QAAA,OAAK,CAAV,MAAC;kCADVxB,IAAAA,mBAYE,OAAA;AAAA,YAVC,KAAK;AAAA,YACL,OAAKG,IAAAA,eAAA;AAAA;cAAsD,eAAe,QAAA,OAAO;AAAA,cAAY,QAAA,WAAO;AAAA,YAAA;YAKpG,OAAKyB,IAAAA,eAAA;AAAA,qBAAoB,MAAM,QAAA,QAAK,QAAW,QAAA,SAAK;AAAA,sBAA6B,QAAA;AAAA,YAAA;;;8BAMtF5B,IAAAA,mBAYE,OAAA;AAAA;QAVC,OAAKG,IAAAA,eAAA;AAAA;UAAkD,eAAe,QAAA,OAAO;AAAA,UAAU,QAAA,WAAO;AAAA,QAAA;QAK9F,OAAKyB,IAAAA,eAAA;AAAA,UAAkB,OAAA,QAAA,UAAU,QAAA,YAAO,aAAA,SAAA;AAAA,kBAAmD,QAAA,WAAW,QAAA,YAAO,aAAA,SAA2B,QAAA,YAAO,SAAA,SAAA;AAAA,QAAA;QAIhJ,eAAY;AAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;ACvDhB,UAAM,QAAQ;AAiCd,UAAM,OAAO;AAKb,UAAM,gBAAoI;AAAA,MACxI,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,WAAW;AAAA,QACX,eAAe;AAAA,MAAA;AAAA,MAEjB,SAAS;AAAA,QACP,MAAM;AAAA,QACN,WAAW;AAAA,QACX,eAAe;AAAA,MAAA;AAAA,MAEjB,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,WAAW;AAAA,QACX,eAAe;AAAA,MAAA;AAAA,MAEjB,SAAS;AAAA,QACP,MAAM;AAAA,QACN,WAAW;AAAA,QACX,eAAe;AAAA,MAAA;AAAA,IACjB;AAGF,UAAM,SAAS,cAAc,MAAM,OAAO;;aAKhC,QAAA,yBADRhB,IAAAA,YA6CQiB,aAAA;AAAA;QA3CN,MAAK;AAAA,QACJ,sBAAoB,QAAA;AAAA,QACpB,oBAAkB,QAAA;AAAA,QAClB,UAAU,QAAA;AAAA,QACV,+CAAO,KAAI,QAAA;AAAA,MAAA;6BAEZ,MAoCM;AAAA,UApCN5B,IAAAA,mBAoCM,OApCN,YAoCM;AAAA,YAlCJA,IAAAA,mBAKM,OALN,YAKM;AAAA,cAJJiB,gBAGEJ,IAAAA,MAAAK,MAAAA,IAAA,GAAA;AAAA,gBAFC,MAAM,QAAA,QAAQL,IAAAA,MAAA,MAAA,EAAO;AAAA,gBACrB,OAAKX,IAAAA,eAAA,CAAGW,IAAAA,MAAA,MAAA,EAAO,WAAS,QAAA,CAAA;AAAA,cAAA;;YAK7Bb,IAAAA,mBAEK,MAFL,YAEKI,IAAAA,gBADA,QAAA,KAAK,GAAA,CAAA;AAAA,YAIVJ,IAAAA,mBAEI,KAFJ,YAEI;AAAA,cADFgB,IAAAA,WAA0B,4BAA1B,MAA0B;AAAA,wDAAjB,QAAA,OAAO,GAAA,CAAA;AAAA,cAAA;;YAIlBhB,IAAAA,mBAeM,OAfN,YAeM;AAAA,cAdJiB,IAAAA,YAMSY,2CAAAA,WAAA;AAAA,gBALP,SAAQ;AAAA,gBACP,UAAU,QAAA;AAAA,gBACV,+CAAO,KAAI,QAAA;AAAA,cAAA;qCAEZ,MAAgB;AAAA,0DAAb,QAAA,UAAU,GAAA,CAAA;AAAA,gBAAA;;;cAEfZ,IAAAA,YAMSY,2CAAAA,WAAA;AAAA,gBALN,SAAShB,IAAAA,MAAA,MAAA,EAAO;AAAA,gBAChB,SAAS,QAAA;AAAA,gBACT,+CAAO,KAAI,SAAA;AAAA,cAAA;qCAEZ,MAAiB;AAAA,0DAAd,QAAA,WAAW,GAAA,CAAA;AAAA,gBAAA;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -188,11 +188,16 @@ const _hoisted_5$1 = {
188
188
  };
189
189
  const _hoisted_6 = ["value"];
190
190
  const _hoisted_7 = ["value"];
191
- const _hoisted_8 = { class: "flex justify-center sm:justify-end gap-2" };
191
+ const _hoisted_8 = { class: "flex justify-center sm:justify-end items-center gap-1" };
192
192
  const _hoisted_9 = ["disabled"];
193
193
  const _hoisted_10 = { class: "hidden sm:inline" };
194
- const _hoisted_11 = ["disabled"];
195
- const _hoisted_12 = { class: "hidden sm:inline" };
194
+ const _hoisted_11 = {
195
+ key: 0,
196
+ class: "px-2 py-2 text-sm text-gray-500 dark:text-gray-400"
197
+ };
198
+ const _hoisted_12 = ["disabled", "onClick"];
199
+ const _hoisted_13 = ["disabled"];
200
+ const _hoisted_14 = { class: "hidden sm:inline" };
196
201
  const _sfc_main$9 = /* @__PURE__ */ defineComponent({
197
202
  __name: "PaginationControls",
198
203
  props: {
@@ -202,6 +207,8 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
202
207
  pageSize: { default: 10 },
203
208
  pageSizeOptions: { default: () => [10, 20, 50, 100] },
204
209
  showPageSize: { type: Boolean, default: true },
210
+ showPageNumbers: { type: Boolean, default: true },
211
+ maxVisiblePages: { default: 7 },
205
212
  pageLabel: { default: "Page" },
206
213
  ofLabel: { default: "of" },
207
214
  itemsPerPageLabel: { default: "Items per page:" },
@@ -210,6 +217,34 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
210
217
  },
211
218
  emits: ["update:page", "update:pageSize"],
212
219
  setup(__props, { emit: __emit }) {
220
+ const visiblePages = computed(() => {
221
+ if (__props.totalPages <= __props.maxVisiblePages) {
222
+ return Array.from({ length: __props.totalPages }, (_, i) => i + 1);
223
+ }
224
+ const pages = [];
225
+ const sidePages = Math.floor((__props.maxVisiblePages - 3) / 2);
226
+ pages.push(1);
227
+ let rangeStart = Math.max(2, __props.currentPage - sidePages);
228
+ let rangeEnd = Math.min(__props.totalPages - 1, __props.currentPage + sidePages);
229
+ if (__props.currentPage <= sidePages + 2) {
230
+ rangeEnd = Math.min(__props.totalPages - 1, __props.maxVisiblePages - 2);
231
+ } else if (__props.currentPage >= __props.totalPages - sidePages - 1) {
232
+ rangeStart = Math.max(2, __props.totalPages - __props.maxVisiblePages + 3);
233
+ }
234
+ if (rangeStart > 2) {
235
+ pages.push("ellipsis-start");
236
+ }
237
+ for (let i = rangeStart; i <= rangeEnd; i++) {
238
+ pages.push(i);
239
+ }
240
+ if (rangeEnd < __props.totalPages - 1) {
241
+ pages.push("ellipsis-end");
242
+ }
243
+ if (__props.totalPages > 1) {
244
+ pages.push(__props.totalPages);
245
+ }
246
+ return pages;
247
+ });
213
248
  const emit = __emit;
214
249
  const changePage = (page) => {
215
250
  if (page >= 1 && page <= __props.totalPages && !__props.loading) {
@@ -244,7 +279,7 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
244
279
  createElementVNode("div", _hoisted_8, [
245
280
  createElementVNode("button", {
246
281
  disabled: __props.currentPage === 1 || __props.loading,
247
- class: "focus:ring-primary inline-flex items-center gap-1 rounded-lg border border-gray-300 bg-white px-3 sm:px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700",
282
+ class: "focus:ring-primary inline-flex items-center gap-1 rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700",
248
283
  onClick: _cache[0] || (_cache[0] = ($event) => changePage(__props.currentPage - 1))
249
284
  }, [
250
285
  createVNode(unref(Icon), {
@@ -253,17 +288,31 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
253
288
  }),
254
289
  createElementVNode("span", _hoisted_10, toDisplayString(__props.previousLabel), 1)
255
290
  ], 8, _hoisted_9),
291
+ __props.showPageNumbers ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(visiblePages.value, (page) => {
292
+ return openBlock(), createElementBlock(Fragment, { key: page }, [
293
+ page === "ellipsis-start" || page === "ellipsis-end" ? (openBlock(), createElementBlock("span", _hoisted_11, " … ")) : (openBlock(), createElementBlock("button", {
294
+ key: 1,
295
+ disabled: __props.loading,
296
+ class: normalizeClass([
297
+ "min-w-[40px] px-3 py-2 text-sm font-medium rounded-lg border transition-colors",
298
+ page === __props.currentPage ? "bg-primary-600 text-white border-primary-600 dark:bg-primary-500 dark:border-primary-500" : "bg-white text-gray-700 border-gray-300 hover:bg-gray-50 dark:bg-gray-800 dark:text-gray-200 dark:border-gray-600 dark:hover:bg-gray-700",
299
+ __props.loading ? "cursor-not-allowed opacity-50" : ""
300
+ ]),
301
+ onClick: ($event) => changePage(page)
302
+ }, toDisplayString(page), 11, _hoisted_12))
303
+ ], 64);
304
+ }), 128)) : createCommentVNode("", true),
256
305
  createElementVNode("button", {
257
306
  disabled: __props.currentPage === __props.totalPages || __props.loading,
258
- class: "focus:ring-primary inline-flex items-center gap-1 rounded-lg border border-gray-300 bg-white px-3 sm:px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700",
307
+ class: "focus:ring-primary inline-flex items-center gap-1 rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700",
259
308
  onClick: _cache[1] || (_cache[1] = ($event) => changePage(__props.currentPage + 1))
260
309
  }, [
261
- createElementVNode("span", _hoisted_12, toDisplayString(__props.nextLabel), 1),
310
+ createElementVNode("span", _hoisted_14, toDisplayString(__props.nextLabel), 1),
262
311
  createVNode(unref(Icon), {
263
312
  class: "size-4",
264
313
  icon: "lucide:chevron-right"
265
314
  })
266
- ], 8, _hoisted_11)
315
+ ], 8, _hoisted_13)
267
316
  ])
268
317
  ])) : createCommentVNode("", true);
269
318
  };
@@ -761,7 +810,7 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
761
810
  };
762
811
  }
763
812
  });
764
- const Progress = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-7ff636cf"]]);
813
+ const Progress = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-546a3ae5"]]);
765
814
  const _hoisted_1$1 = {
766
815
  key: 0,
767
816
  class: "space-y-2",
@@ -926,4 +975,4 @@ export {
926
975
  _sfc_main$1 as i,
927
976
  _sfc_main as j
928
977
  };
929
- //# sourceMappingURL=ConfirmDialog.vue_vue_type_script_setup_true_lang-DqkA1Zr-.js.map
978
+ //# sourceMappingURL=ConfirmDialog.vue_vue_type_script_setup_true_lang-DWs2V7xX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfirmDialog.vue_vue_type_script_setup_true_lang-DWs2V7xX.js","sources":["../src/components/feedback/LoadingSpinner.vue","../src/components/feedback/Modal.vue","../src/components/feedback/PaginationControls.vue","../src/components/feedback/NotificationComponent.vue","../src/components/feedback/NotificationList.vue","../src/components/feedback/Alert.vue","../src/components/feedback/EmptyState.vue","../src/components/feedback/Toast.vue","../src/components/feedback/ToastContainer.vue","../src/components/feedback/Progress.vue","../src/components/feedback/Skeleton.vue","../src/components/feedback/ConfirmDialog.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { computed } from 'vue'\nimport type { SpinnerSize } from '@/types'\n\nconst props = withDefaults(\n defineProps<{\n text?: string\n size?: SpinnerSize\n /** Accessible label for screen readers (defaults to 'Loading' or text prop) */\n ariaLabel?: string\n }>(),\n {\n size: 'md',\n ariaLabel: 'Loading',\n },\n)\n\nconst sizeClasses: Record<SpinnerSize, string> = {\n sm: 'size-8',\n md: 'size-12',\n lg: 'size-16',\n}\n\nconst accessibleLabel = computed(() => props.text || props.ariaLabel)\n</script>\n\n<template>\n <div\n class=\"flex items-center justify-center py-12\"\n role=\"status\"\n aria-live=\"polite\"\n :aria-label=\"accessibleLabel\"\n >\n <div class=\"text-center\">\n <div\n :class=\"sizeClasses[size]\"\n class=\"border-primary inline-block animate-spin rounded-full border-4 border-solid border-r-transparent\"\n aria-hidden=\"true\"\n />\n <p\n v-if=\"text\"\n class=\"mt-4 text-gray-600 dark:text-gray-400\"\n >\n {{ text }}\n </p>\n <span v-else class=\"sr-only\">{{ accessibleLabel }}</span>\n </div>\n </div>\n</template>\n","<script lang=\"ts\" setup>\r\nimport { Icon } from '@iconify/vue'\r\nimport { onMounted, onUnmounted, computed, ref } from 'vue'\r\nimport type { ModalSize } from '@/types'\r\nimport { useId } from '@/composables/useId'\r\nimport { useFocusTrap } from '@/composables/useFocusTrap'\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n title?: string\r\n size?: ModalSize\r\n closeOnBackdrop?: boolean\r\n closeOnEscape?: boolean\r\n closeButtonLabel?: string\r\n /** Teleport target (e.g., 'body', '#app'). Set to false to disable teleport. */\r\n teleport?: string | false\r\n /** Custom ID for the modal (auto-generated if not provided) */\r\n id?: string\r\n }>(),\r\n {\r\n title: '',\r\n size: 'default',\r\n closeOnBackdrop: true,\r\n closeOnEscape: true,\r\n closeButtonLabel: 'Close',\r\n teleport: 'body',\r\n },\r\n)\r\n\r\nconst {\r\n title,\r\n size,\r\n closeOnBackdrop,\r\n closeOnEscape,\r\n closeButtonLabel,\r\n} = props\r\n\r\nconst teleportDisabled = computed(() => props.teleport === false)\r\nconst teleportTarget = computed(() => props.teleport === false ? 'body' : props.teleport)\r\n\r\nconst emit = defineEmits<{\r\n close: []\r\n}>()\r\n\r\n// Generate unique IDs for ARIA relationships\r\nconst { id: modalId, related } = useId({ prefix: 'modal', id: props.id })\r\nconst titleId = computed(() => related('title'))\r\n\r\n// Focus trap\r\nconst isActive = ref(true)\r\nconst { containerRef: dialogRef } = useFocusTrap({\r\n active: isActive,\r\n focusFirst: true,\r\n restoreFocus: true,\r\n})\r\n\r\n// Check if modal has a title (for aria-labelledby)\r\nconst hasTitle = computed(() => Boolean(props.title))\r\n\r\nconst sizeClasses: Record<ModalSize, string> = {\r\n sm: 'max-w-md',\r\n default: 'max-w-3xl',\r\n lg: 'max-w-5xl',\r\n xl: 'max-w-7xl',\r\n full: 'max-w-full mx-4',\r\n}\r\n\r\nconst handleBackdropClick = () => {\r\n if (closeOnBackdrop) {\r\n emit('close')\r\n }\r\n}\r\n\r\nconst handleEscape = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape' && closeOnEscape) {\r\n emit('close')\r\n }\r\n}\r\n\r\nonMounted(() => {\r\n document.addEventListener('keydown', handleEscape)\r\n document.body.style.overflow = 'hidden'\r\n})\r\n\r\nonUnmounted(() => {\r\n document.removeEventListener('keydown', handleEscape)\r\n document.body.style.overflow = ''\r\n})\r\n</script>\r\n\r\n<template>\r\n <Teleport :to=\"teleportTarget\" :disabled=\"teleportDisabled\">\r\n <div\r\n class=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4\"\r\n @click.self=\"handleBackdropClick\"\r\n >\r\n <div\r\n ref=\"dialogRef\"\r\n :id=\"modalId\"\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n :aria-labelledby=\"hasTitle ? titleId : undefined\"\r\n :class=\"sizeClasses[size]\"\r\n class=\"flex max-h-[90vh] w-full flex-col rounded-lg bg-white shadow-xl dark:bg-gray-900\"\r\n >\r\n <!-- Header -->\r\n <div\r\n v-if=\"title || $slots.header || $slots.title\"\r\n class=\"flex items-center justify-between border-b border-gray-200 px-6 py-4 dark:border-gray-700\"\r\n >\r\n <h3\r\n :id=\"titleId\"\r\n class=\"text-xl font-semibold text-gray-900 dark:text-gray-100\"\r\n >\r\n <slot name=\"header\">\r\n <slot name=\"title\">\r\n {{ title }}\r\n </slot>\r\n </slot>\r\n </h3>\r\n <button\r\n class=\"rounded-lg p-1.5 text-gray-400 hover:bg-gray-100 hover:text-gray-900 dark:hover:bg-gray-800 dark:hover:text-gray-100\"\r\n type=\"button\"\r\n aria-label=\"Close dialog\"\r\n @click=\"emit('close')\"\r\n >\r\n <Icon\r\n class=\"size-5\"\r\n icon=\"lucide:x\"\r\n aria-hidden=\"true\"\r\n />\r\n <span class=\"sr-only\">{{ closeButtonLabel }}</span>\r\n </button>\r\n </div>\r\n\r\n <!-- Body -->\r\n <div class=\"flex-1 overflow-y-auto px-6 py-4\">\r\n <slot />\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div\r\n v-if=\"$slots.footer\"\r\n class=\"flex items-center justify-end gap-3 border-t border-gray-200 px-6 py-4 dark:border-gray-700\"\r\n >\r\n <slot name=\"footer\" />\r\n </div>\r\n </div>\r\n </div>\r\n </Teleport>\r\n</template>\r\n","<script lang=\"ts\" setup>\r\nimport { computed } from 'vue'\r\nimport { Icon } from '@iconify/vue'\r\n\r\nconst {\r\n currentPage,\r\n totalPages,\r\n loading = false,\r\n pageSize = 10,\r\n pageSizeOptions = [10, 20, 50, 100],\r\n showPageSize = true,\r\n showPageNumbers = true,\r\n maxVisiblePages = 7,\r\n pageLabel = 'Page',\r\n ofLabel = 'of',\r\n itemsPerPageLabel = 'Items per page:',\r\n previousLabel = 'Previous',\r\n nextLabel = 'Next',\r\n} = defineProps<{\r\n currentPage: number\r\n totalPages: number\r\n loading?: boolean\r\n pageSize?: number\r\n pageSizeOptions?: number[]\r\n showPageSize?: boolean\r\n showPageNumbers?: boolean\r\n maxVisiblePages?: number\r\n pageLabel?: string\r\n ofLabel?: string\r\n itemsPerPageLabel?: string\r\n previousLabel?: string\r\n nextLabel?: string\r\n}>()\r\n\r\ntype PageItem = number | 'ellipsis-start' | 'ellipsis-end'\r\n\r\nconst visiblePages = computed<PageItem[]>(() => {\r\n if (totalPages <= maxVisiblePages) {\r\n return Array.from({ length: totalPages }, (_, i) => i + 1)\r\n }\r\n\r\n const pages: PageItem[] = []\r\n const sidePages = Math.floor((maxVisiblePages - 3) / 2)\r\n\r\n // Always show first page\r\n pages.push(1)\r\n\r\n // Calculate range around current page\r\n let rangeStart = Math.max(2, currentPage - sidePages)\r\n let rangeEnd = Math.min(totalPages - 1, currentPage + sidePages)\r\n\r\n // Adjust range to show more pages on one side if near edges\r\n if (currentPage <= sidePages + 2) {\r\n rangeEnd = Math.min(totalPages - 1, maxVisiblePages - 2)\r\n } else if (currentPage >= totalPages - sidePages - 1) {\r\n rangeStart = Math.max(2, totalPages - maxVisiblePages + 3)\r\n }\r\n\r\n // Add ellipsis or pages after first page\r\n if (rangeStart > 2) {\r\n pages.push('ellipsis-start')\r\n }\r\n\r\n // Add range pages\r\n for (let i = rangeStart; i <= rangeEnd; i++) {\r\n pages.push(i)\r\n }\r\n\r\n // Add ellipsis or pages before last page\r\n if (rangeEnd < totalPages - 1) {\r\n pages.push('ellipsis-end')\r\n }\r\n\r\n // Always show last page\r\n if (totalPages > 1) {\r\n pages.push(totalPages)\r\n }\r\n\r\n return pages\r\n})\r\n\r\nconst emit = defineEmits<{\r\n 'update:page': [page: number]\r\n 'update:pageSize': [size: number]\r\n}>()\r\n\r\nconst changePage = (page: number) => {\r\n if (page >= 1 && page <= totalPages && !loading) {\r\n emit('update:page', page)\r\n }\r\n}\r\n\r\nconst changePageSize = (event: Event) => {\r\n const target = event.target as HTMLSelectElement\r\n emit('update:pageSize', Number(target.value))\r\n}\r\n</script>\r\n\r\n<template>\r\n <div\r\n v-if=\"totalPages > 1\"\r\n class=\"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 border-t border-gray-200 px-4 sm:px-6 py-4 dark:border-gray-700\"\r\n >\r\n <!-- Info and page size -->\r\n <div class=\"flex flex-col sm:flex-row sm:items-center gap-3 sm:gap-4\">\r\n <div class=\"text-sm text-gray-700 dark:text-gray-300 text-center sm:text-left\">\r\n {{ pageLabel }} {{ currentPage }} {{ ofLabel }} {{ totalPages }}\r\n </div>\r\n <div\r\n v-if=\"showPageSize\"\r\n class=\"flex items-center justify-center sm:justify-start gap-2\"\r\n >\r\n <label\r\n class=\"text-sm text-gray-600 dark:text-gray-400 hidden sm:inline\"\r\n for=\"page-size\"\r\n >\r\n {{ itemsPerPageLabel }}\r\n </label>\r\n <select\r\n id=\"page-size\"\r\n :value=\"pageSize\"\r\n class=\"focus:border-primary focus:ring-primary rounded border border-gray-300 bg-white px-2 py-1 text-sm text-gray-900 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100\"\r\n @change=\"changePageSize\"\r\n >\r\n <option\r\n v-for=\"size in pageSizeOptions\"\r\n :key=\"size\"\r\n :value=\"size\"\r\n >\r\n {{ size }}\r\n </option>\r\n </select>\r\n </div>\r\n </div>\r\n\r\n <!-- Navigation buttons -->\r\n <div class=\"flex justify-center sm:justify-end items-center gap-1\">\r\n <!-- Previous button -->\r\n <button\r\n :disabled=\"currentPage === 1 || loading\"\r\n class=\"focus:ring-primary inline-flex items-center gap-1 rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700\"\r\n @click=\"changePage(currentPage - 1)\"\r\n >\r\n <Icon\r\n class=\"size-4\"\r\n icon=\"lucide:chevron-left\"\r\n />\r\n <span class=\"hidden sm:inline\">{{ previousLabel }}</span>\r\n </button>\r\n\r\n <!-- Page numbers -->\r\n <template v-if=\"showPageNumbers\">\r\n <template\r\n v-for=\"page in visiblePages\"\r\n :key=\"page\"\r\n >\r\n <!-- Ellipsis -->\r\n <span\r\n v-if=\"page === 'ellipsis-start' || page === 'ellipsis-end'\"\r\n class=\"px-2 py-2 text-sm text-gray-500 dark:text-gray-400\"\r\n >\r\n …\r\n </span>\r\n <!-- Page number button -->\r\n <button\r\n v-else\r\n :disabled=\"loading\"\r\n :class=\"[\r\n 'min-w-[40px] px-3 py-2 text-sm font-medium rounded-lg border transition-colors',\r\n page === currentPage\r\n ? 'bg-primary-600 text-white border-primary-600 dark:bg-primary-500 dark:border-primary-500'\r\n : 'bg-white text-gray-700 border-gray-300 hover:bg-gray-50 dark:bg-gray-800 dark:text-gray-200 dark:border-gray-600 dark:hover:bg-gray-700',\r\n loading ? 'cursor-not-allowed opacity-50' : ''\r\n ]\"\r\n @click=\"changePage(page)\"\r\n >\r\n {{ page }}\r\n </button>\r\n </template>\r\n </template>\r\n\r\n <!-- Next button -->\r\n <button\r\n :disabled=\"currentPage === totalPages || loading\"\r\n class=\"focus:ring-primary inline-flex items-center gap-1 rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700\"\r\n @click=\"changePage(currentPage + 1)\"\r\n >\r\n <span class=\"hidden sm:inline\">{{ nextLabel }}</span>\r\n <Icon\r\n class=\"size-4\"\r\n icon=\"lucide:chevron-right\"\r\n />\r\n </button>\r\n </div>\r\n </div>\r\n</template>\r\n","<script lang=\"ts\" setup>\nimport type { Notification } from '@/types'\nimport { computed, onMounted } from 'vue'\nimport { Icon } from '@iconify/vue'\n\nconst props = defineProps<{\n notification: Notification\n autoDismiss?: boolean\n duration?: number\n}>()\n\nconst emit = defineEmits<{\n dismiss: [id: string]\n}>()\n\nconst iconName = computed(() => {\n switch (props.notification.type) {\n case 'success':\n return 'lucide:check-circle'\n case 'info':\n return 'lucide:info'\n case 'warning':\n return 'lucide:alert-triangle'\n case 'error':\n return 'lucide:x-circle'\n default:\n return 'lucide:bell'\n }\n})\n\nconst iconColor = computed(() => {\n switch (props.notification.type) {\n case 'success':\n return 'text-green-600 dark:text-green-400'\n case 'info':\n return 'text-blue-600 dark:text-blue-400'\n case 'warning':\n return 'text-yellow-600 dark:text-yellow-400'\n case 'error':\n return 'text-red-600 dark:text-red-400'\n default:\n return 'text-gray-600 dark:text-gray-400'\n }\n})\n\nconst bgColor = computed(() => {\n switch (props.notification.type) {\n case 'success':\n return 'bg-green-50 dark:bg-green-950'\n case 'info':\n return 'bg-blue-50 dark:bg-blue-950'\n case 'warning':\n return 'bg-yellow-50 dark:bg-yellow-950'\n case 'error':\n return 'bg-red-50 dark:bg-red-950'\n default:\n return 'bg-gray-50 dark:bg-gray-950'\n }\n})\n\nconst handleDismiss = () => {\n if (props.notification.id) {\n emit('dismiss', props.notification.id)\n }\n}\n\nonMounted(() => {\n const duration = props.notification.duration ?? props.duration ?? 5000\n if (props.autoDismiss !== false && duration > 0) {\n setTimeout(() => {\n handleDismiss()\n }, duration)\n }\n})\n</script>\n\n<template>\n <div\n class=\"flex max-w-md items-start space-x-3 rounded-lg border border-gray-200 bg-white p-4 shadow-lg dark:border-gray-800 dark:bg-black\"\n >\n <div :class=\"[bgColor, 'flex items-center justify-center rounded-full p-2']\">\n <Icon\n :class=\"iconColor\"\n :icon=\"iconName\"\n class=\"size-5\"\n />\n </div>\n\n <div class=\"flex min-w-0 flex-1 flex-col\">\n <h4\n v-if=\"notification.title\"\n class=\"text-sm font-semibold text-gray-900 dark:text-gray-100\"\n >\n {{ notification.title }}\n </h4>\n <p\n v-if=\"notification.message\"\n class=\"mt-1 text-sm text-gray-600 dark:text-gray-400\"\n >\n {{ notification.message }}\n </p>\n </div>\n\n <button\n class=\"shrink-0 text-gray-400 transition-colors hover:text-gray-600 dark:text-gray-600 dark:hover:text-gray-400\"\n @click=\"handleDismiss\"\n >\n <Icon\n class=\"size-4\"\n icon=\"lucide:x\"\n />\n </button>\n </div>\n</template>\n","<script lang=\"ts\" setup>\r\nimport { computed } from 'vue'\r\nimport type { Notification } from '@/types'\r\nimport NotificationComponent from './NotificationComponent.vue'\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n notifications: Notification[]\r\n autoDismiss?: boolean\r\n duration?: number\r\n /** Position of the container */\r\n position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'\r\n /** Custom top offset (e.g., '80px', '5rem') to account for fixed headers */\r\n topOffset?: string\r\n }>(),\r\n {\r\n position: 'top-right',\r\n },\r\n)\r\n\r\nconst emit = defineEmits<{\r\n dismiss: [id: string]\r\n}>()\r\n\r\nconst positionClasses: Record<string, string> = {\r\n 'top-right': 'top-5 right-5',\r\n 'top-left': 'top-5 left-5',\r\n 'bottom-right': 'bottom-5 right-5',\r\n 'bottom-left': 'bottom-5 left-5',\r\n}\r\n\r\nconst isTopPosition = computed(() => props.position?.startsWith('top'))\r\n\r\nconst topStyle = computed(() => {\r\n if (!isTopPosition.value || !props.topOffset) return {}\r\n return { top: props.topOffset }\r\n})\r\n</script>\r\n\r\n<template>\r\n <Teleport to=\"body\">\r\n <div\r\n :class=\"['fixed z-50 flex flex-col gap-3 w-full max-w-sm', positionClasses[position]]\"\r\n :style=\"topStyle\"\r\n >\r\n <TransitionGroup\r\n enter-active-class=\"transition duration-300 ease-out\"\r\n enter-from-class=\"opacity-0 translate-x-4\"\r\n enter-to-class=\"opacity-100 translate-x-0\"\r\n leave-active-class=\"transition duration-200 ease-in\"\r\n leave-from-class=\"opacity-100 translate-x-0\"\r\n leave-to-class=\"opacity-0 translate-x-4\"\r\n >\r\n <NotificationComponent\r\n v-for=\"notification in notifications\"\r\n :key=\"notification.id\"\r\n :notification=\"notification\"\r\n :auto-dismiss=\"autoDismiss\"\r\n :duration=\"duration\"\r\n @dismiss=\"emit('dismiss', $event)\"\r\n />\r\n </TransitionGroup>\r\n </div>\r\n </Teleport>\r\n</template>\r\n","<script lang=\"ts\" setup>\nimport { Icon } from '@iconify/vue'\n\nexport type AlertVariant = 'info' | 'success' | 'warning' | 'error'\n\nconst props = withDefaults(\n defineProps<{\n /** Alert variant */\n variant?: AlertVariant\n /** Title text */\n title?: string\n /** Show close button */\n dismissible?: boolean\n /** Custom icon */\n icon?: string\n }>(),\n {\n variant: 'info',\n },\n)\n\nconst emit = defineEmits<{\n dismiss: []\n}>()\n\nconst variantStyles: Record<AlertVariant, { bg: string; border: string; icon: string; iconColor: string }> = {\n info: {\n bg: 'bg-blue-50 dark:bg-blue-900/20',\n border: 'border-blue-200 dark:border-blue-800',\n icon: 'lucide:info',\n iconColor: 'text-blue-500',\n },\n success: {\n bg: 'bg-green-50 dark:bg-green-900/20',\n border: 'border-green-200 dark:border-green-800',\n icon: 'lucide:check-circle',\n iconColor: 'text-green-500',\n },\n warning: {\n bg: 'bg-yellow-50 dark:bg-yellow-900/20',\n border: 'border-yellow-200 dark:border-yellow-800',\n icon: 'lucide:alert-triangle',\n iconColor: 'text-yellow-500',\n },\n error: {\n bg: 'bg-red-50 dark:bg-red-900/20',\n border: 'border-red-200 dark:border-red-800',\n icon: 'lucide:alert-circle',\n iconColor: 'text-red-500',\n },\n}\n\nconst styles = variantStyles[props.variant]\n</script>\n\n<template>\n <div\n :class=\"[\n 'flex gap-3 rounded-lg border p-4',\n styles.bg,\n styles.border,\n ]\"\n role=\"alert\"\n >\n <Icon\n :icon=\"icon || styles.icon\"\n :class=\"['size-5 shrink-0', styles.iconColor]\"\n aria-hidden=\"true\"\n />\n <div class=\"flex-1\">\n <h4\n v-if=\"title\"\n class=\"mb-1 font-medium text-gray-900 dark:text-white\"\n >\n {{ title }}\n </h4>\n <div class=\"text-sm text-gray-700 dark:text-gray-300\">\n <slot />\n </div>\n </div>\n <button\n v-if=\"dismissible\"\n type=\"button\"\n class=\"shrink-0 rounded p-1 text-gray-400 hover:bg-gray-200 hover:text-gray-600 dark:hover:bg-gray-700 dark:hover:text-gray-300\"\n aria-label=\"Dismiss alert\"\n @click=\"emit('dismiss')\"\n >\n <Icon\n icon=\"lucide:x\"\n class=\"size-4\"\n aria-hidden=\"true\"\n />\n </button>\n </div>\n</template>\n","<script lang=\"ts\" setup>\nimport { Icon } from '@iconify/vue'\n\nwithDefaults(\n defineProps<{\n /** Message to display */\n message?: string\n /** Icon name (iconify format) */\n icon?: string\n /** Title text */\n title?: string\n }>(),\n {\n message: 'No results found',\n icon: 'lucide:inbox',\n },\n)\n</script>\n\n<template>\n <div class=\"py-12 text-center\">\n <Icon\n v-if=\"icon\"\n :icon=\"icon\"\n class=\"mx-auto mb-4 size-12 text-gray-400 dark:text-gray-500\"\n />\n <h3\n v-if=\"title\"\n class=\"mb-2 text-lg font-medium text-gray-900 dark:text-white\"\n >\n {{ title }}\n </h3>\n <p class=\"text-gray-500 dark:text-gray-400\">\n <slot>{{ message }}</slot>\n </p>\n <div\n v-if=\"$slots.action\"\n class=\"mt-4\"\n >\n <slot name=\"action\" />\n </div>\n </div>\n</template>\n","<script lang=\"ts\" setup>\r\nimport { Icon } from '@iconify/vue'\r\n\r\nexport type ToastType = 'success' | 'error' | 'warning' | 'info'\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n /** Toast message */\r\n message: string\r\n /** Toast type */\r\n type?: ToastType\r\n /** Title (optional) */\r\n title?: string\r\n /** Show close button */\r\n closable?: boolean\r\n /** Duration in ms (0 = no auto-close) */\r\n duration?: number\r\n }>(),\r\n {\r\n type: 'info',\r\n closable: true,\r\n duration: 5000,\r\n },\r\n)\r\n\r\nconst emit = defineEmits<{\r\n close: []\r\n}>()\r\n\r\nconst typeConfig: Record<ToastType, { icon: string; bg: string; iconColor: string }> = {\r\n success: {\r\n icon: 'lucide:check-circle',\r\n bg: 'bg-green-50 border-green-200 dark:bg-green-950 dark:border-green-800',\r\n iconColor: 'text-green-500',\r\n },\r\n error: {\r\n icon: 'lucide:x-circle',\r\n bg: 'bg-red-50 border-red-200 dark:bg-red-950 dark:border-red-800',\r\n iconColor: 'text-red-500',\r\n },\r\n warning: {\r\n icon: 'lucide:alert-triangle',\r\n bg: 'bg-yellow-50 border-yellow-200 dark:bg-yellow-950 dark:border-yellow-800',\r\n iconColor: 'text-yellow-500',\r\n },\r\n info: {\r\n icon: 'lucide:info',\r\n bg: 'bg-blue-50 border-blue-200 dark:bg-blue-950 dark:border-blue-800',\r\n iconColor: 'text-blue-500',\r\n },\r\n}\r\n\r\nconst config = typeConfig[props.type]\r\n\r\n// Auto-close\r\nif (props.duration > 0) {\r\n setTimeout(() => {\r\n emit('close')\r\n }, props.duration)\r\n}\r\n</script>\r\n\r\n<template>\r\n <div\r\n :class=\"[\r\n 'flex items-start gap-3 rounded-lg border p-4 shadow-lg',\r\n config.bg,\r\n ]\"\r\n role=\"alert\"\r\n >\r\n <Icon\r\n :icon=\"config.icon\"\r\n :class=\"['size-5 shrink-0', config.iconColor]\"\r\n aria-hidden=\"true\"\r\n />\r\n <div class=\"flex-1 min-w-0\">\r\n <p\r\n v-if=\"title\"\r\n class=\"font-medium text-gray-900 dark:text-white\"\r\n >\r\n {{ title }}\r\n </p>\r\n <p class=\"text-sm text-gray-700 dark:text-gray-300\">\r\n {{ message }}\r\n </p>\r\n </div>\r\n <button\r\n v-if=\"closable\"\r\n type=\"button\"\r\n class=\"shrink-0 rounded p-1 text-gray-400 hover:bg-gray-200 hover:text-gray-600 dark:hover:bg-gray-700 dark:hover:text-gray-300\"\r\n aria-label=\"Dismiss notification\"\r\n @click=\"emit('close')\"\r\n >\r\n <Icon\r\n icon=\"lucide:x\"\r\n class=\"size-4\"\r\n aria-hidden=\"true\"\r\n />\r\n </button>\r\n </div>\r\n</template>\r\n","<script lang=\"ts\" setup>\r\nimport { computed } from 'vue'\r\nimport Toast from './Toast.vue'\r\nimport type { ToastType } from './Toast.vue'\r\n\r\nexport interface ToastItem {\r\n id: string\r\n message: string\r\n type?: ToastType\r\n title?: string\r\n duration?: number\r\n}\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n /** Array of toast items */\r\n toasts: ToastItem[]\r\n /** Position of the container */\r\n position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'top-center' | 'bottom-center'\r\n /** Custom top offset (e.g., '80px', '5rem') to account for fixed headers */\r\n topOffset?: string\r\n }>(),\r\n {\r\n position: 'top-right',\r\n },\r\n)\r\n\r\nconst emit = defineEmits<{\r\n close: [id: string]\r\n}>()\r\n\r\nconst positionClasses: Record<string, string> = {\r\n 'top-right': 'right-4',\r\n 'top-left': 'left-4',\r\n 'bottom-right': 'bottom-4 right-4',\r\n 'bottom-left': 'bottom-4 left-4',\r\n 'top-center': 'left-1/2 -translate-x-1/2',\r\n 'bottom-center': 'bottom-4 left-1/2 -translate-x-1/2',\r\n}\r\n\r\nconst isTopPosition = computed(() => props.position?.startsWith('top'))\r\n\r\nconst topStyle = computed(() => {\r\n if (!isTopPosition.value) return {}\r\n return { top: props.topOffset || '1rem' }\r\n})\r\n</script>\r\n\r\n<template>\r\n <Teleport to=\"body\">\r\n <div\r\n :class=\"['fixed z-9999 flex flex-col gap-2 w-full max-w-sm', positionClasses[position]]\"\r\n :style=\"topStyle\"\r\n aria-live=\"polite\"\r\n aria-atomic=\"false\"\r\n >\r\n <TransitionGroup\r\n enter-active-class=\"transition duration-300 ease-out\"\r\n enter-from-class=\"opacity-0 translate-x-4\"\r\n enter-to-class=\"opacity-100 translate-x-0\"\r\n leave-active-class=\"transition duration-200 ease-in\"\r\n leave-from-class=\"opacity-100 translate-x-0\"\r\n leave-to-class=\"opacity-0 translate-x-4\"\r\n >\r\n <Toast\r\n v-for=\"toast in toasts\"\r\n :key=\"toast.id\"\r\n :message=\"toast.message\"\r\n :type=\"toast.type\"\r\n :title=\"toast.title\"\r\n :duration=\"toast.duration\"\r\n @close=\"emit('close', toast.id)\"\r\n />\r\n </TransitionGroup>\r\n </div>\r\n </Teleport>\r\n</template>\r\n","<script lang=\"ts\" setup>\r\nimport { computed } from 'vue'\r\n\r\nexport type ProgressSize = 'sm' | 'md' | 'lg'\r\nexport type ProgressVariant = 'default' | 'success' | 'warning' | 'error'\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n /** Current value (0-100) */\r\n value: number\r\n /** Maximum value */\r\n max?: number\r\n /** Size variant */\r\n size?: ProgressSize\r\n /** Color variant */\r\n variant?: ProgressVariant\r\n /** Show percentage label */\r\n showLabel?: boolean\r\n /** Striped animation */\r\n striped?: boolean\r\n /** Animated stripes */\r\n animated?: boolean\r\n /** Indeterminate state (loading) */\r\n indeterminate?: boolean\r\n }>(),\r\n {\r\n max: 100,\r\n size: 'md',\r\n variant: 'default',\r\n showLabel: false,\r\n striped: false,\r\n animated: false,\r\n indeterminate: false,\r\n },\r\n)\r\n\r\nconst percentage = computed(() => {\r\n if (props.indeterminate) return 100\r\n return Math.min(Math.max((props.value / props.max) * 100, 0), 100)\r\n})\r\n\r\nconst sizeClasses: Record<ProgressSize, string> = {\r\n sm: 'h-1',\r\n md: 'h-2',\r\n lg: 'h-4',\r\n}\r\n\r\nconst variantClasses: Record<ProgressVariant, string> = {\r\n default: 'bg-primary',\r\n success: 'bg-green-500',\r\n warning: 'bg-yellow-500',\r\n error: 'bg-red-500',\r\n}\r\n</script>\r\n\r\n<template>\r\n <div class=\"w-full\">\r\n <div\n v-if=\"showLabel && !indeterminate\"\n class=\"mb-1 flex justify-between text-sm\"\n >\r\n <span class=\"text-gray-600 dark:text-gray-400\">Progress</span>\r\n <span class=\"font-medium text-gray-900 dark:text-white\">{{ Math.round(percentage) }}%</span>\r\n </div>\r\n <div\r\n :class=\"[\r\n 'w-full overflow-hidden rounded-full bg-gray-200 dark:bg-gray-700',\r\n sizeClasses[size],\r\n ]\"\r\n role=\"progressbar\"\r\n :aria-valuenow=\"indeterminate ? undefined : value\"\r\n :aria-valuemin=\"0\"\r\n :aria-valuemax=\"max\"\r\n >\r\n <div\r\n :class=\"[\r\n 'h-full rounded-full transition-all duration-300',\r\n variantClasses[variant],\r\n striped && 'bg-stripes',\r\n animated && 'animate-stripes',\r\n indeterminate && 'animate-indeterminate',\r\n ]\"\r\n :style=\"{ width: indeterminate ? '30%' : `${percentage}%` }\"\r\n />\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<style scoped>\r\n.bg-stripes {\r\n background-image: linear-gradient(\r\n 45deg,\r\n rgba(255, 255, 255, 0.15) 25%,\r\n transparent 25%,\r\n transparent 50%,\r\n rgba(255, 255, 255, 0.15) 50%,\r\n rgba(255, 255, 255, 0.15) 75%,\r\n transparent 75%,\r\n transparent\r\n );\r\n background-size: 1rem 1rem;\r\n}\r\n\r\n.animate-stripes {\r\n animation: stripes 1s linear infinite;\r\n}\r\n\r\n@keyframes stripes {\r\n from {\r\n background-position: 1rem 0;\r\n }\r\n to {\r\n background-position: 0 0;\r\n }\r\n}\r\n\r\n.animate-indeterminate {\r\n animation: indeterminate 1.5s ease-in-out infinite;\r\n}\r\n\r\n@keyframes indeterminate {\r\n 0% {\r\n transform: translateX(-100%);\r\n }\r\n 100% {\r\n transform: translateX(400%);\r\n }\r\n}\r\n</style>\r\n","<script lang=\"ts\" setup>\r\nexport type SkeletonVariant = 'text' | 'circular' | 'rectangular' | 'rounded'\r\n\r\nwithDefaults(\r\n defineProps<{\r\n /** Variant style */\r\n variant?: SkeletonVariant\r\n /** Width (CSS value) */\r\n width?: string\r\n /** Height (CSS value) */\r\n height?: string\r\n /** Number of lines (for text variant) */\r\n lines?: number\r\n /** Animate the skeleton */\r\n animate?: boolean\r\n }>(),\r\n {\r\n variant: 'text',\r\n animate: true,\r\n lines: 1,\r\n },\r\n)\r\n\r\nconst variantClasses: Record<SkeletonVariant, string> = {\r\n text: 'h-4 rounded',\r\n circular: 'rounded-full',\r\n rectangular: '',\r\n rounded: 'rounded-lg',\r\n}\r\n</script>\r\n\r\n<template>\r\n <div\r\n v-if=\"variant === 'text' && lines > 1\"\r\n class=\"space-y-2\"\r\n aria-hidden=\"true\"\r\n >\r\n <div\r\n v-for=\"i in lines\"\r\n :key=\"i\"\r\n :class=\"[\r\n 'bg-gray-200 dark:bg-gray-700',\r\n variantClasses[variant],\r\n animate && 'animate-pulse',\r\n ]\"\r\n :style=\"{\r\n width: i === lines ? '75%' : width || '100%',\r\n height: height,\r\n }\"\r\n />\r\n </div>\r\n <div\r\n v-else\r\n :class=\"[\r\n 'bg-gray-200 dark:bg-gray-700',\r\n variantClasses[variant],\r\n animate && 'animate-pulse',\r\n ]\"\r\n :style=\"{\r\n width: width || (variant === 'circular' ? '3rem' : '100%'),\r\n height: height || (variant === 'circular' ? '3rem' : variant === 'text' ? '1rem' : '6rem'),\r\n }\"\r\n aria-hidden=\"true\"\r\n />\r\n</template>\r\n","<script lang=\"ts\" setup>\r\nimport { Icon } from '@iconify/vue'\r\nimport Modal from './Modal.vue'\r\nimport Button from '@/components/core/Button.vue'\r\n\r\nexport type ConfirmDialogVariant = 'info' | 'warning' | 'danger' | 'success'\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n /** Whether the dialog is open */\r\n open?: boolean\r\n /** Dialog title */\r\n title?: string\r\n /** Dialog message */\r\n message?: string\r\n /** Confirm button text */\r\n confirmText?: string\r\n /** Cancel button text */\r\n cancelText?: string\r\n /** Dialog variant (affects icon and confirm button color) */\r\n variant?: ConfirmDialogVariant\r\n /** Show loading state on confirm button */\r\n loading?: boolean\r\n /** Icon to display */\r\n icon?: string\r\n /** Teleport target (e.g., 'body', '#app'). Set to false to disable teleport. */\r\n teleport?: string | false\r\n }>(),\r\n {\r\n open: false,\r\n title: 'Confirm',\r\n message: 'Are you sure you want to proceed?',\r\n confirmText: 'Confirm',\r\n cancelText: 'Cancel',\r\n variant: 'info',\r\n loading: false,\r\n teleport: 'body',\r\n },\r\n)\r\n\r\nconst emit = defineEmits<{\r\n confirm: []\r\n cancel: []\r\n}>()\r\n\r\nconst variantConfig: Record<ConfirmDialogVariant, { icon: string; iconClass: string; buttonVariant: 'primary' | 'danger' | 'success' }> = {\r\n info: {\r\n icon: 'lucide:info',\r\n iconClass: 'text-blue-500',\r\n buttonVariant: 'primary',\r\n },\r\n warning: {\r\n icon: 'lucide:alert-triangle',\r\n iconClass: 'text-yellow-500',\r\n buttonVariant: 'primary',\r\n },\r\n danger: {\r\n icon: 'lucide:alert-circle',\r\n iconClass: 'text-red-500',\r\n buttonVariant: 'danger',\r\n },\r\n success: {\r\n icon: 'lucide:check-circle',\r\n iconClass: 'text-green-500',\r\n buttonVariant: 'success',\r\n },\r\n}\r\n\r\nconst config = variantConfig[props.variant]\r\n</script>\r\n\r\n<template>\r\n <Modal\r\n v-if=\"open\"\r\n size=\"sm\"\r\n :close-on-backdrop=\"!loading\"\r\n :close-on-escape=\"!loading\"\r\n :teleport=\"teleport\"\r\n @close=\"emit('cancel')\"\r\n >\r\n <div class=\"text-center\">\r\n <!-- Icon -->\r\n <div class=\"mx-auto mb-4 flex size-14 items-center justify-center rounded-full bg-gray-100 dark:bg-gray-800\">\r\n <Icon\r\n :icon=\"icon || config.icon\"\r\n :class=\"[config.iconClass, 'size-8']\"\r\n />\r\n </div>\r\n\r\n <!-- Title -->\r\n <h3 class=\"mb-2 text-lg font-semibold text-gray-900 dark:text-gray-100\">\r\n {{ title }}\r\n </h3>\r\n\r\n <!-- Message -->\r\n <p class=\"mb-6 text-gray-600 dark:text-gray-400\">\r\n <slot>{{ message }}</slot>\r\n </p>\r\n\r\n <!-- Actions -->\r\n <div class=\"flex justify-center gap-3\">\r\n <Button\r\n variant=\"outline\"\r\n :disabled=\"loading\"\r\n @click=\"emit('cancel')\"\r\n >\r\n {{ cancelText }}\r\n </Button>\r\n <Button\r\n :variant=\"config.buttonVariant\"\r\n :loading=\"loading\"\r\n @click=\"emit('confirm')\"\r\n >\r\n {{ confirmText }}\r\n </Button>\r\n </div>\r\n </div>\r\n </Modal>\r\n</template>\r\n"],"names":["_createElementBlock","_createElementVNode","_hoisted_2","_normalizeClass","_hoisted_3","_toDisplayString","_hoisted_4","_createBlock","_Teleport","_unref","$slots","_openBlock","_renderSlot","_createVNode","_hoisted_5","_hoisted_6","_hoisted_1","_Fragment","_renderList","_TransitionGroup","NotificationComponent","Toast","_normalizeStyle","Modal","Button"],"mappings":"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"}