@htlkg/components 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -0
- package/dist/AdminWrapper.vue_vue_type_script_setup_true_lang-B32IylcT.js +367 -0
- package/dist/AdminWrapper.vue_vue_type_script_setup_true_lang-B32IylcT.js.map +1 -0
- package/dist/Alert.vue_vue_type_script_setup_true_lang-DxPCS-Hx.js +263 -0
- package/dist/Alert.vue_vue_type_script_setup_true_lang-DxPCS-Hx.js.map +1 -0
- package/dist/DateRange.vue_vue_type_script_setup_true_lang-BLVg1Hah.js +580 -0
- package/dist/DateRange.vue_vue_type_script_setup_true_lang-BLVg1Hah.js.map +1 -0
- package/dist/ProductBadge.vue_vue_type_script_setup_true_lang-Cmr2f4Cy.js +187 -0
- package/dist/ProductBadge.vue_vue_type_script_setup_true_lang-Cmr2f4Cy.js.map +1 -0
- package/dist/_plugin-vue_export-helper-1tPrXgE0.js +11 -0
- package/dist/_plugin-vue_export-helper-1tPrXgE0.js.map +1 -0
- package/dist/components.css +15 -0
- package/dist/composables/index.js +32 -573
- package/dist/composables/index.js.map +1 -1
- package/dist/data/index.js +18 -0
- package/dist/data/index.js.map +1 -0
- package/dist/domain/index.js +8 -0
- package/dist/domain/index.js.map +1 -0
- package/dist/filterHelpers-DgRyoYSa.js +1386 -0
- package/dist/filterHelpers-DgRyoYSa.js.map +1 -0
- package/dist/forms/index.js +6 -0
- package/dist/forms/index.js.map +1 -0
- package/dist/index-DGO_pNgG.js +79 -0
- package/dist/index-DGO_pNgG.js.map +1 -0
- package/dist/index-QK97OdqQ.js +25 -0
- package/dist/index-QK97OdqQ.js.map +1 -0
- package/dist/index.js +67 -0
- package/dist/index.js.map +1 -0
- package/dist/navigation/index.js +8 -0
- package/dist/navigation/index.js.map +1 -0
- package/dist/overlays/index.js +8 -0
- package/dist/overlays/index.js.map +1 -0
- package/dist/stores/index.js +14 -0
- package/dist/stores/index.js.map +1 -0
- package/dist/useAdminPage-GhgXp0x8.js +1070 -0
- package/dist/useAdminPage-GhgXp0x8.js.map +1 -0
- package/dist/useTable-DutR1gkg.js +293 -0
- package/dist/useTable-DutR1gkg.js.map +1 -0
- package/package.json +43 -14
- package/src/composables/composables.md +109 -0
- package/src/composables/index.ts +69 -0
- package/src/composables/useAdminPage.ts +462 -0
- package/src/composables/useConfirmation.ts +358 -0
- package/src/composables/usePageContext.ts +171 -0
- package/src/composables/useStats.ts +361 -0
- package/src/composables/useTable.ts +26 -5
- package/src/composables/useWizard.ts +448 -0
- package/src/data/DataTable.vue +553 -0
- package/src/data/Table/Table.vue +295 -0
- package/src/data/columnHelpers.ts +503 -0
- package/src/data/data.md +106 -0
- package/src/data/filterHelpers.ts +358 -0
- package/src/data/index.ts +31 -0
- package/src/domain/domain.md +102 -0
- package/src/forms/JsonSchemaForm.vue +4 -1
- package/src/forms/forms.md +89 -0
- package/src/index.ts +4 -3
- package/src/navigation/navigation.md +80 -0
- package/src/overlays/overlays.md +86 -0
- package/src/stores/stores.md +82 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAdminPage-GhgXp0x8.js","sources":["../src/composables/useModal.ts","../src/composables/useTabs.ts","../src/composables/useForm.ts","../src/composables/useFormValidation.ts","../src/composables/useNotifications.ts","../src/composables/usePageContext.ts","../src/composables/useWizard.ts","../src/composables/useStats.ts","../src/composables/useConfirmation.ts","../src/composables/useAdminPage.ts"],"sourcesContent":["import { ref, type Ref } from 'vue';\n\nexport interface UseModalOptions {\n initialOpen?: boolean;\n onOpen?: () => void;\n onClose?: () => void;\n}\n\nexport interface UseModalReturn {\n isOpen: Ref<boolean>;\n open: () => void;\n close: () => void;\n toggle: () => void;\n}\n\nexport function useModal(options: UseModalOptions = {}): UseModalReturn {\n const isOpen = ref(options.initialOpen ?? false);\n\n function open() {\n isOpen.value = true;\n options.onOpen?.();\n }\n\n function close() {\n isOpen.value = false;\n options.onClose?.();\n }\n\n function toggle() {\n if (isOpen.value) {\n close();\n } else {\n open();\n }\n }\n\n return {\n isOpen,\n open,\n close,\n toggle\n };\n}\n","import { ref, computed, type Ref, type ComputedRef } from 'vue';\n\nexport interface Tab {\n id: string;\n label: string;\n disabled?: boolean;\n}\n\nexport interface UseTabsOptions {\n tabs: Tab[];\n initialTab?: string;\n onChange?: (tabId: string) => void;\n}\n\nexport interface UseTabsReturn {\n activeTab: Ref<string>;\n tabs: Ref<Tab[]>;\n currentTabIndex: ComputedRef<number>;\n isFirstTab: ComputedRef<boolean>;\n isLastTab: ComputedRef<boolean>;\n setActiveTab: (tabId: string) => void;\n nextTab: () => void;\n previousTab: () => void;\n isTabActive: (tabId: string) => boolean;\n isTabDisabled: (tabId: string) => boolean;\n}\n\nexport function useTabs(options: UseTabsOptions): UseTabsReturn {\n const tabs = ref(options.tabs);\n const activeTab = ref(\n options.initialTab || (tabs.value.length > 0 ? tabs.value[0].id : '')\n );\n\n const currentTabIndex = computed(() =>\n tabs.value.findIndex(tab => tab.id === activeTab.value)\n );\n\n const isFirstTab = computed(() => currentTabIndex.value === 0);\n\n const isLastTab = computed(() =>\n currentTabIndex.value === tabs.value.length - 1\n );\n\n function setActiveTab(tabId: string) {\n const tab = tabs.value.find(t => t.id === tabId);\n if (tab && !tab.disabled) {\n activeTab.value = tabId;\n options.onChange?.(tabId);\n }\n }\n\n function nextTab() {\n if (!isLastTab.value) {\n const nextIndex = currentTabIndex.value + 1;\n const nextTab = tabs.value[nextIndex];\n if (nextTab && !nextTab.disabled) {\n setActiveTab(nextTab.id);\n } else if (nextIndex < tabs.value.length - 1) {\n // Skip disabled tab and try next\n activeTab.value = nextTab.id;\n nextTab();\n }\n }\n }\n\n function previousTab() {\n if (!isFirstTab.value) {\n const prevIndex = currentTabIndex.value - 1;\n const prevTab = tabs.value[prevIndex];\n if (prevTab && !prevTab.disabled) {\n setActiveTab(prevTab.id);\n } else if (prevIndex > 0) {\n // Skip disabled tab and try previous\n activeTab.value = prevTab.id;\n previousTab();\n }\n }\n }\n\n function isTabActive(tabId: string): boolean {\n return activeTab.value === tabId;\n }\n\n function isTabDisabled(tabId: string): boolean {\n const tab = tabs.value.find(t => t.id === tabId);\n return tab?.disabled ?? false;\n }\n\n return {\n activeTab,\n tabs,\n currentTabIndex,\n isFirstTab,\n isLastTab,\n setActiveTab,\n nextTab,\n previousTab,\n isTabActive,\n isTabDisabled\n };\n}\n","import { ref, computed, type Ref, type ComputedRef } from 'vue';\n\nexport interface ValidationRule<T = any> {\n validate: (value: T) => boolean | Promise<boolean>;\n message: string;\n}\n\nexport interface FieldConfig {\n rules?: ValidationRule[];\n initialValue?: any;\n}\n\nexport interface UseFormOptions<T extends Record<string, any>> {\n initialValues: T;\n validationRules?: Partial<Record<keyof T, ValidationRule[]>>;\n onSubmit?: (values: T) => void | Promise<void>;\n}\n\nexport interface UseFormReturn<T extends Record<string, any>> {\n values: Ref<T>;\n errors: Ref<Partial<Record<keyof T, string>>>;\n touched: Ref<Partial<Record<keyof T, boolean>>>;\n isSubmitting: Ref<boolean>;\n isValid: ComputedRef<boolean>;\n setFieldValue: (field: keyof T, value: any) => void;\n setFieldError: (field: keyof T, error: string) => void;\n setFieldTouched: (field: keyof T, touched: boolean) => void;\n validateField: (field: keyof T) => Promise<boolean>;\n validateForm: () => Promise<boolean>;\n handleSubmit: (event?: Event) => Promise<void>;\n resetForm: () => void;\n}\n\nexport function useForm<T extends Record<string, any>>(\n options: UseFormOptions<T>\n): UseFormReturn<T> {\n const values = ref<T>({ ...options.initialValues }) as Ref<T>;\n const errors = ref<Partial<Record<keyof T, string>>>({});\n const touched = ref<Partial<Record<keyof T, boolean>>>({});\n const isSubmitting = ref(false);\n\n const isValid = computed(() => Object.keys(errors.value).length === 0);\n\n function setFieldValue(field: keyof T, value: any) {\n values.value[field] = value;\n }\n\n function setFieldError(field: keyof T, error: string) {\n errors.value[field] = error;\n }\n\n function setFieldTouched(field: keyof T, isTouched: boolean) {\n touched.value[field] = isTouched;\n }\n\n async function validateField(field: keyof T): Promise<boolean> {\n const rules = options.validationRules?.[field];\n if (!rules || rules.length === 0) return true;\n\n const value = values.value[field];\n\n for (const rule of rules) {\n const isValid = await rule.validate(value);\n if (!isValid) {\n setFieldError(field, rule.message);\n return false;\n }\n }\n\n // Clear error if validation passed\n delete errors.value[field];\n return true;\n }\n\n async function validateForm(): Promise<boolean> {\n const fields = Object.keys(values.value) as Array<keyof T>;\n const validationResults = await Promise.all(\n fields.map(field => validateField(field))\n );\n\n return validationResults.every(result => result);\n }\n\n async function handleSubmit(event?: Event) {\n if (event) {\n event.preventDefault();\n }\n\n if (isSubmitting.value) return;\n\n // Mark all fields as touched\n for (const field of Object.keys(values.value) as Array<keyof T>) {\n setFieldTouched(field, true);\n }\n\n // Validate form\n const isFormValid = await validateForm();\n if (!isFormValid) return;\n\n // Submit form\n isSubmitting.value = true;\n try {\n await options.onSubmit?.(values.value);\n } finally {\n isSubmitting.value = false;\n }\n }\n\n function resetForm() {\n values.value = { ...options.initialValues };\n errors.value = {};\n touched.value = {};\n isSubmitting.value = false;\n }\n\n return {\n values,\n errors,\n touched,\n isSubmitting,\n isValid,\n setFieldValue,\n setFieldError,\n setFieldTouched,\n validateField,\n validateForm,\n handleSubmit,\n resetForm\n };\n}\n","import type { ValidationRule } from './useForm';\n\n// Common validation rules\nexport const required = (message = 'This field is required'): ValidationRule => ({\n validate: (value: any) => {\n if (value === null || value === undefined) return false;\n if (typeof value === 'string') return value.trim().length > 0;\n if (Array.isArray(value)) return value.length > 0;\n return true;\n },\n message\n});\n\nexport const minLength = (min: number, message?: string): ValidationRule => ({\n validate: (value: string) => {\n if (!value) return true; // Let required handle empty values\n return value.length >= min;\n },\n message: message || `Must be at least ${min} characters`\n});\n\nexport const maxLength = (max: number, message?: string): ValidationRule => ({\n validate: (value: string) => {\n if (!value) return true;\n return value.length <= max;\n },\n message: message || `Must be at most ${max} characters`\n});\n\nexport const email = (message = 'Invalid email address'): ValidationRule => ({\n validate: (value: string) => {\n if (!value) return true;\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return emailRegex.test(value);\n },\n message\n});\n\nexport const pattern = (regex: RegExp, message = 'Invalid format'): ValidationRule => ({\n validate: (value: string) => {\n if (!value) return true;\n return regex.test(value);\n },\n message\n});\n\nexport const min = (minValue: number, message?: string): ValidationRule => ({\n validate: (value: number) => {\n if (value === null || value === undefined) return true;\n return value >= minValue;\n },\n message: message || `Must be at least ${minValue}`\n});\n\nexport const max = (maxValue: number, message?: string): ValidationRule => ({\n validate: (value: number) => {\n if (value === null || value === undefined) return true;\n return value <= maxValue;\n },\n message: message || `Must be at most ${maxValue}`\n});\n\nexport const custom = (\n validator: (value: any) => boolean | Promise<boolean>,\n message: string\n): ValidationRule => ({\n validate: validator,\n message\n});\n\n// Composable for form validation\nexport function useFormValidation() {\n return {\n required,\n minLength,\n maxLength,\n email,\n pattern,\n min,\n max,\n custom\n };\n}\n","import { ref, type Ref } from 'vue';\n\nexport interface Notification {\n id: string;\n message: string;\n type: 'info' | 'success' | 'warning' | 'error';\n duration?: number;\n}\n\nexport interface UseNotificationsReturn {\n notifications: Ref<Notification[]>;\n addNotification: (notification: Omit<Notification, 'id'>) => string;\n removeNotification: (id: string) => void;\n clearAll: () => void;\n info: (message: string, duration?: number) => string;\n success: (message: string, duration?: number) => string;\n warning: (message: string, duration?: number) => string;\n error: (message: string, duration?: number) => string;\n}\n\n// Global notifications state\nconst notifications = ref<Notification[]>([]);\n\nexport function useNotifications(): UseNotificationsReturn {\n function addNotification(notification: Omit<Notification, 'id'>): string {\n const id = `notification-${Date.now()}-${Math.random()}`;\n const newNotification: Notification = {\n ...notification,\n id\n };\n\n notifications.value.push(newNotification);\n\n // Auto-remove after duration\n if (notification.duration) {\n setTimeout(() => {\n removeNotification(id);\n }, notification.duration);\n }\n\n return id;\n }\n\n function removeNotification(id: string) {\n const index = notifications.value.findIndex(n => n.id === id);\n if (index !== -1) {\n notifications.value.splice(index, 1);\n }\n }\n\n function clearAll() {\n notifications.value = [];\n }\n\n function info(message: string, duration = 3000): string {\n return addNotification({ message, type: 'info', duration });\n }\n\n function success(message: string, duration = 3000): string {\n return addNotification({ message, type: 'success', duration });\n }\n\n function warning(message: string, duration = 3000): string {\n return addNotification({ message, type: 'warning', duration });\n }\n\n function error(message: string, duration = 5000): string {\n return addNotification({ message, type: 'error', duration });\n }\n\n return {\n notifications,\n addNotification,\n removeNotification,\n clearAll,\n info,\n success,\n warning,\n error\n };\n}\n","/**\n * Page Context Composable\n *\n * Provides access to common page context data (user, brand, routes)\n * within Vue components, without prop drilling.\n */\n\nimport { computed, inject, type InjectionKey, type ComputedRef } from \"vue\";\nimport { useStore } from \"@nanostores/vue\";\nimport { atom } from \"nanostores\";\nimport { routes, type Routes } from \"@htlkg/core\";\n\n/**\n * User information from authentication\n */\nexport interface PageUser {\n\tusername: string;\n\temail?: string;\n\tisAdmin: boolean;\n\tisSuperAdmin: boolean;\n\tbrandIds?: number[];\n\taccountIds?: number[];\n\troles?: string[];\n}\n\n/**\n * Brand context for brand-scoped pages\n */\nexport interface PageBrand {\n\tid: number;\n\tname: string;\n\tlogo?: string;\n}\n\n/**\n * Full page context\n */\nexport interface PageContext {\n\tuser: PageUser | null;\n\tbrand?: PageBrand;\n\tbrandId?: number;\n\tisAdmin: boolean;\n\tisSuperAdmin: boolean;\n\troutes: Routes;\n}\n\n/**\n * Injection key for providing page context\n */\nexport const PAGE_CONTEXT_KEY: InjectionKey<PageContext> = Symbol(\"pageContext\");\n\n/**\n * Nanostore for user state (set by AdminLayout)\n */\nexport const $user = atom<PageUser | null>(null);\n\n/**\n * Nanostore for current brand (set by BrandLayout)\n */\nexport const $currentBrand = atom<PageBrand | null>(null);\n\n/**\n * Set user in the store (called from layout)\n */\nexport function setUser(user: PageUser | null): void {\n\t$user.set(user);\n}\n\n/**\n * Set current brand in the store (called from layout)\n */\nexport function setCurrentBrand(brand: PageBrand | null): void {\n\t$currentBrand.set(brand);\n}\n\n/**\n * Get page context within a Vue component\n *\n * This composable provides access to:\n * - Current user information\n * - Current brand (if in brand context)\n * - Admin/superadmin status\n * - Type-safe routes\n *\n * @example\n * ```vue\n * <script setup>\n * import { usePageContext } from '@htlkg/components';\n *\n * const { user, isAdmin, routes } = usePageContext();\n *\n * function goToAccounts() {\n * window.location.href = routes.admin.accounts();\n * }\n * </script>\n * ```\n *\n * @example With provider pattern\n * ```vue\n * // In parent component\n * import { provide, PAGE_CONTEXT_KEY } from '@htlkg/components';\n * provide(PAGE_CONTEXT_KEY, { user, brand, isAdmin: true, routes });\n *\n * // In child component\n * const context = usePageContext();\n * ```\n */\nexport function usePageContext(): ComputedRef<PageContext> {\n\t// Try injection first (from provider)\n\tconst injected = inject(PAGE_CONTEXT_KEY, null);\n\tif (injected) {\n\t\treturn computed(() => injected);\n\t}\n\n\t// Fallback to nanostores\n\tconst user = useStore($user);\n\tconst brand = useStore($currentBrand);\n\n\treturn computed(() => ({\n\t\tuser: user.value,\n\t\tbrand: brand.value ?? undefined,\n\t\tbrandId: brand.value?.id,\n\t\tisAdmin: user.value?.isAdmin ?? false,\n\t\tisSuperAdmin: user.value?.isSuperAdmin ?? false,\n\t\troutes,\n\t}));\n}\n\n/**\n * Check if user has access to a specific brand\n */\nexport function useHasAccessToBrand(brandId: number): ComputedRef<boolean> {\n\tconst context = usePageContext();\n\n\treturn computed(() => {\n\t\tconst user = context.value.user;\n\t\tif (!user) return false;\n\t\tif (user.isAdmin || user.isSuperAdmin) return true;\n\t\treturn user.brandIds?.includes(brandId) ?? false;\n\t});\n}\n\n/**\n * Check if user has access to a specific account\n */\nexport function useHasAccessToAccount(accountId: number): ComputedRef<boolean> {\n\tconst context = usePageContext();\n\n\treturn computed(() => {\n\t\tconst user = context.value.user;\n\t\tif (!user) return false;\n\t\tif (user.isAdmin || user.isSuperAdmin) return true;\n\t\treturn user.accountIds?.includes(accountId) ?? false;\n\t});\n}\n\n/**\n * Get user roles\n */\nexport function useUserRoles(): ComputedRef<string[]> {\n\tconst context = usePageContext();\n\treturn computed(() => context.value.user?.roles ?? []);\n}\n\n/**\n * Check if user has a specific role\n */\nexport function useHasRole(role: string): ComputedRef<boolean> {\n\tconst roles = useUserRoles();\n\treturn computed(() => roles.value.includes(role));\n}\n","/**\n * Wizard Composable\n *\n * Manages multi-step form/wizard state with validation support.\n * Integrates with Stepper component and JsonSchemaForm.\n */\n\nimport { ref, computed, type Ref, type ComputedRef, type Component } from 'vue';\n\n/**\n * JSON Schema type for form validation\n */\nexport interface JsonSchema {\n\ttype: string;\n\tproperties?: Record<string, any>;\n\trequired?: string[];\n\ttitle?: string;\n\tdescription?: string;\n}\n\n/**\n * Step definition for the wizard\n */\nexport interface WizardStep<T = any> {\n\t/** Unique step identifier */\n\tid: string;\n\t/** Display label for the step */\n\tlabel: string;\n\t/** Optional description */\n\tdescription?: string;\n\t/** JSON Schema for JsonSchemaForm (optional) */\n\tschema?: JsonSchema;\n\t/** Custom validation function (optional) */\n\tvalidate?: (data: T) => boolean | Promise<boolean>;\n\t/** Icon component for the step (optional) */\n\ticon?: Component;\n\t/** Whether step can be skipped */\n\toptional?: boolean;\n}\n\n/**\n * Step status for Stepper component\n */\nexport type StepStatus = 'complete' | 'current' | 'upcoming' | 'error';\n\n/**\n * Stepper-compatible step format\n */\nexport interface StepperStep {\n\tid: string;\n\tlabel: string;\n\tstatus: StepStatus;\n\tvalid?: boolean;\n}\n\n/**\n * Options for useWizard\n */\nexport interface UseWizardOptions<T extends Record<string, any>> {\n\t/** Step definitions */\n\tsteps: WizardStep<T>[];\n\t/** Initial form data */\n\tinitialData?: Partial<T>;\n\t/** Callback when wizard completes */\n\tonComplete?: (data: T) => void | Promise<void>;\n\t/** Callback when step changes */\n\tonStepChange?: (fromIndex: number, toIndex: number, data: T) => void;\n\t/** Whether to validate before advancing */\n\tvalidateOnNext?: boolean;\n\t/** Whether to allow going back without validation */\n\tallowBackWithoutValidation?: boolean;\n}\n\n/**\n * Return type for useWizard\n */\nexport interface UseWizardReturn<T extends Record<string, any>> {\n\t// State\n\tcurrentStepIndex: Ref<number>;\n\tcurrentStep: ComputedRef<WizardStep<T>>;\n\tdata: Ref<Partial<T>>;\n\tisFirstStep: ComputedRef<boolean>;\n\tisLastStep: ComputedRef<boolean>;\n\tisCompleting: Ref<boolean>;\n\tstepErrors: Ref<Record<string, string>>;\n\n\t// For Stepper component\n\tstepperSteps: ComputedRef<StepperStep[]>;\n\n\t// Validation state\n\tstepValidation: Ref<Record<string, boolean>>;\n\tcurrentStepValid: ComputedRef<boolean>;\n\tallStepsValid: ComputedRef<boolean>;\n\n\t// Navigation\n\tgoToNext: () => Promise<boolean>;\n\tgoToPrevious: () => boolean;\n\tgoToStep: (index: number) => Promise<boolean>;\n\tcanGoToStep: (index: number) => boolean;\n\n\t// Data management\n\tupdateData: (newData: Partial<T>) => void;\n\tupdateStepData: (stepId: string, stepData: Partial<T>) => void;\n\tsetStepValid: (stepId: string, valid: boolean) => void;\n\tsetStepError: (stepId: string, error: string | null) => void;\n\tresetStep: (stepId: string) => void;\n\treset: () => void;\n\n\t// Completion\n\tcomplete: () => Promise<boolean>;\n\n\t// Utilities\n\tgetStepIndex: (stepId: string) => number;\n\tgetStep: (stepId: string) => WizardStep<T> | undefined;\n\tprogress: ComputedRef<number>;\n}\n\n/**\n * Creates a wizard composable for managing multi-step forms\n *\n * @example\n * ```typescript\n * const wizard = useWizard({\n * steps: [\n * { id: 'details', label: 'Details', schema: detailsSchema },\n * { id: 'audience', label: 'Audience', schema: audienceSchema },\n * { id: 'review', label: 'Review' },\n * ],\n * initialData: { name: '', audience: [] },\n * onComplete: async (data) => {\n * await createCampaign(data);\n * },\n * });\n *\n * // In template\n * <Stepper :steps=\"wizard.stepperSteps\" v-model:currentStep=\"wizard.currentStepIndex\" />\n * <JsonSchemaForm\n * v-if=\"wizard.currentStep.schema\"\n * :schema=\"wizard.currentStep.schema\"\n * v-model=\"wizard.data\"\n * />\n * <button @click=\"wizard.goToPrevious\" :disabled=\"wizard.isFirstStep\">Back</button>\n * <button @click=\"wizard.goToNext\" v-if=\"!wizard.isLastStep\">Next</button>\n * <button @click=\"wizard.complete\" v-else :disabled=\"wizard.isCompleting\">Complete</button>\n * ```\n */\nexport function useWizard<T extends Record<string, any>>(\n\toptions: UseWizardOptions<T>\n): UseWizardReturn<T> {\n\tconst {\n\t\tsteps,\n\t\tinitialData = {} as Partial<T>,\n\t\tonComplete,\n\t\tonStepChange,\n\t\tvalidateOnNext = true,\n\t\tallowBackWithoutValidation = true,\n\t} = options;\n\n\t// Core state\n\tconst currentStepIndex = ref(0);\n\tconst data = ref<Partial<T>>({ ...initialData }) as Ref<Partial<T>>;\n\tconst isCompleting = ref(false);\n\tconst stepValidation = ref<Record<string, boolean>>({});\n\tconst stepErrors = ref<Record<string, string>>({});\n\n\t// Computed: Current step\n\tconst currentStep = computed(() => steps[currentStepIndex.value]);\n\n\t// Computed: Navigation flags\n\tconst isFirstStep = computed(() => currentStepIndex.value === 0);\n\tconst isLastStep = computed(() => currentStepIndex.value === steps.length - 1);\n\n\t// Computed: Progress percentage\n\tconst progress = computed(() =>\n\t\tMath.round(((currentStepIndex.value + 1) / steps.length) * 100)\n\t);\n\n\t// Computed: Current step validation status\n\tconst currentStepValid = computed(() => {\n\t\tconst step = currentStep.value;\n\t\tif (!step) return false;\n\t\tif (step.optional) return true;\n\t\treturn stepValidation.value[step.id] !== false;\n\t});\n\n\t// Computed: All required steps valid\n\tconst allStepsValid = computed(() => {\n\t\treturn steps.every(step => {\n\t\t\tif (step.optional) return true;\n\t\t\treturn stepValidation.value[step.id] === true;\n\t\t});\n\t});\n\n\t// Computed: Steps formatted for Stepper component\n\tconst stepperSteps = computed<StepperStep[]>(() =>\n\t\tsteps.map((step, index) => {\n\t\t\tlet status: StepStatus;\n\n\t\t\tif (index < currentStepIndex.value) {\n\t\t\t\tstatus = stepValidation.value[step.id] === false ? 'error' : 'complete';\n\t\t\t} else if (index === currentStepIndex.value) {\n\t\t\t\tstatus = 'current';\n\t\t\t} else {\n\t\t\t\tstatus = 'upcoming';\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tid: step.id,\n\t\t\t\tlabel: step.label,\n\t\t\t\tstatus,\n\t\t\t\tvalid: stepValidation.value[step.id] ?? true,\n\t\t\t};\n\t\t})\n\t);\n\n\t// Utility: Get step index by ID\n\tfunction getStepIndex(stepId: string): number {\n\t\treturn steps.findIndex(s => s.id === stepId);\n\t}\n\n\t// Utility: Get step by ID\n\tfunction getStep(stepId: string): WizardStep<T> | undefined {\n\t\treturn steps.find(s => s.id === stepId);\n\t}\n\n\t// Validate a specific step\n\tasync function validateStep(stepIndex: number): Promise<boolean> {\n\t\tconst step = steps[stepIndex];\n\t\tif (!step) return false;\n\n\t\t// Optional steps are always valid\n\t\tif (step.optional) {\n\t\t\tstepValidation.value[step.id] = true;\n\t\t\treturn true;\n\t\t}\n\n\t\t// Custom validation function\n\t\tif (step.validate) {\n\t\t\ttry {\n\t\t\t\tconst result = await step.validate(data.value as T);\n\t\t\t\tstepValidation.value[step.id] = result;\n\t\t\t\tif (!result) {\n\t\t\t\t\tstepErrors.value[step.id] = 'Validation failed';\n\t\t\t\t} else {\n\t\t\t\t\tdelete stepErrors.value[step.id];\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t} catch (error) {\n\t\t\t\tstepValidation.value[step.id] = false;\n\t\t\t\tstepErrors.value[step.id] = error instanceof Error ? error.message : 'Validation error';\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// If no custom validation, check if step was marked valid\n\t\t// Default to true if not explicitly set\n\t\tif (stepValidation.value[step.id] === undefined) {\n\t\t\tstepValidation.value[step.id] = true;\n\t\t}\n\n\t\treturn stepValidation.value[step.id] !== false;\n\t}\n\n\t// Check if navigation to step is allowed\n\tfunction canGoToStep(targetIndex: number): boolean {\n\t\tif (targetIndex < 0 || targetIndex >= steps.length) return false;\n\n\t\t// Can always go back if allowed\n\t\tif (targetIndex < currentStepIndex.value && allowBackWithoutValidation) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// For forward navigation, all previous steps must be valid\n\t\tif (targetIndex > currentStepIndex.value && validateOnNext) {\n\t\t\tfor (let i = 0; i < targetIndex; i++) {\n\t\t\t\tconst step = steps[i];\n\t\t\t\tif (!step.optional && stepValidation.value[step.id] === false) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t// Navigation: Go to next step\n\tasync function goToNext(): Promise<boolean> {\n\t\tif (isLastStep.value) return false;\n\n\t\t// Validate current step before advancing\n\t\tif (validateOnNext) {\n\t\t\tconst isValid = await validateStep(currentStepIndex.value);\n\t\t\tif (!isValid) return false;\n\t\t}\n\n\t\tconst fromIndex = currentStepIndex.value;\n\t\tcurrentStepIndex.value++;\n\n\t\tonStepChange?.(fromIndex, currentStepIndex.value, data.value as T);\n\t\treturn true;\n\t}\n\n\t// Navigation: Go to previous step\n\tfunction goToPrevious(): boolean {\n\t\tif (isFirstStep.value) return false;\n\n\t\tconst fromIndex = currentStepIndex.value;\n\t\tcurrentStepIndex.value--;\n\n\t\tonStepChange?.(fromIndex, currentStepIndex.value, data.value as T);\n\t\treturn true;\n\t}\n\n\t// Navigation: Go to specific step\n\tasync function goToStep(targetIndex: number): Promise<boolean> {\n\t\tif (!canGoToStep(targetIndex)) return false;\n\n\t\t// If going forward, validate current step\n\t\tif (targetIndex > currentStepIndex.value && validateOnNext) {\n\t\t\tconst isValid = await validateStep(currentStepIndex.value);\n\t\t\tif (!isValid) return false;\n\t\t}\n\n\t\tconst fromIndex = currentStepIndex.value;\n\t\tcurrentStepIndex.value = targetIndex;\n\n\t\tonStepChange?.(fromIndex, currentStepIndex.value, data.value as T);\n\t\treturn true;\n\t}\n\n\t// Data: Update wizard data\n\tfunction updateData(newData: Partial<T>): void {\n\t\tdata.value = { ...data.value, ...newData };\n\t}\n\n\t// Data: Update data for a specific step\n\tfunction updateStepData(stepId: string, stepData: Partial<T>): void {\n\t\tupdateData(stepData);\n\t\t// Clear error when data is updated\n\t\tdelete stepErrors.value[stepId];\n\t}\n\n\t// Validation: Set step validation status\n\tfunction setStepValid(stepId: string, valid: boolean): void {\n\t\tstepValidation.value[stepId] = valid;\n\t\tif (valid) {\n\t\t\tdelete stepErrors.value[stepId];\n\t\t}\n\t}\n\n\t// Validation: Set step error\n\tfunction setStepError(stepId: string, error: string | null): void {\n\t\tif (error) {\n\t\t\tstepErrors.value[stepId] = error;\n\t\t\tstepValidation.value[stepId] = false;\n\t\t} else {\n\t\t\tdelete stepErrors.value[stepId];\n\t\t}\n\t}\n\n\t// Reset: Reset a specific step\n\tfunction resetStep(stepId: string): void {\n\t\tdelete stepValidation.value[stepId];\n\t\tdelete stepErrors.value[stepId];\n\t}\n\n\t// Reset: Reset entire wizard\n\tfunction reset(): void {\n\t\tcurrentStepIndex.value = 0;\n\t\tdata.value = { ...initialData };\n\t\tstepValidation.value = {};\n\t\tstepErrors.value = {};\n\t\tisCompleting.value = false;\n\t}\n\n\t// Complete: Validate all and trigger completion\n\tasync function complete(): Promise<boolean> {\n\t\tif (isCompleting.value) return false;\n\n\t\tisCompleting.value = true;\n\n\t\ttry {\n\t\t\t// Validate all steps\n\t\t\tfor (let i = 0; i < steps.length; i++) {\n\t\t\t\tconst isValid = await validateStep(i);\n\t\t\t\tif (!isValid && !steps[i].optional) {\n\t\t\t\t\t// Navigate to failed step\n\t\t\t\t\tcurrentStepIndex.value = i;\n\t\t\t\t\tisCompleting.value = false;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Call completion handler\n\t\t\tif (onComplete) {\n\t\t\t\tawait onComplete(data.value as T);\n\t\t\t}\n\n\t\t\treturn true;\n\t\t} catch (error) {\n\t\t\tconsole.error('[useWizard] Completion error:', error);\n\t\t\treturn false;\n\t\t} finally {\n\t\t\tisCompleting.value = false;\n\t\t}\n\t}\n\n\treturn {\n\t\t// State\n\t\tcurrentStepIndex,\n\t\tcurrentStep,\n\t\tdata,\n\t\tisFirstStep,\n\t\tisLastStep,\n\t\tisCompleting,\n\t\tstepErrors,\n\n\t\t// Stepper integration\n\t\tstepperSteps,\n\n\t\t// Validation\n\t\tstepValidation,\n\t\tcurrentStepValid,\n\t\tallStepsValid,\n\n\t\t// Navigation\n\t\tgoToNext,\n\t\tgoToPrevious,\n\t\tgoToStep,\n\t\tcanGoToStep,\n\n\t\t// Data management\n\t\tupdateData,\n\t\tupdateStepData,\n\t\tsetStepValid,\n\t\tsetStepError,\n\t\tresetStep,\n\t\treset,\n\n\t\t// Completion\n\t\tcomplete,\n\n\t\t// Utilities\n\t\tgetStepIndex,\n\t\tgetStep,\n\t\tprogress,\n\t};\n}\n","/**\n * Stats Composable\n *\n * Derives statistics from reactive data with staggered loading animation.\n * Integrates with uiStats component from @hotelinking/ui.\n */\n\nimport { ref, computed, watch, type Ref, type ComputedRef, type Component } from 'vue';\n\n/**\n * Color options matching @hotelinking/ui\n */\nexport type StatColor = 'green' | 'red' | 'yellow' | 'blue' | 'gray' | 'purple' | 'orange' | 'pink';\n\n/**\n * Change type for stat trends\n */\nexport type ChangeType = 'increase' | 'decrease' | 'neutral';\n\n/**\n * Definition for a single stat\n */\nexport interface StatDefinition<T> {\n\t/** Unique identifier */\n\tid: string;\n\t/** Display name */\n\tname: string;\n\t/** Icon component (Heroicons) */\n\ticon: Component;\n\t/** Color theme */\n\tcolor?: StatColor;\n\t/** Function to compute stat value from data */\n\tcompute: (items: T[]) => string | number;\n\t/** Optional: Compute change percentage/value */\n\tcomputeChange?: (items: T[], previousItems?: T[]) => string;\n\t/** Optional: Compute change type (increase/decrease/neutral) */\n\tcomputeChangeType?: (items: T[], previousItems?: T[]) => ChangeType;\n\t/** Show footer with action text */\n\tshowFooter?: boolean;\n\t/** Action text for footer */\n\tactionText?: string;\n}\n\n/**\n * Stat item formatted for uiStats component\n */\nexport interface StatItem {\n\tid: string;\n\tname: string;\n\tstat: string | number;\n\ticon: Component;\n\tcolor: StatColor;\n\tchange?: string;\n\tchangeType?: ChangeType;\n\tshowFooter?: boolean;\n\tactionText?: string;\n}\n\n/**\n * Options for useStats\n */\nexport interface UseStatsOptions<T> {\n\t/** Reactive data source */\n\tdata: Ref<T[]> | ComputedRef<T[]>;\n\t/** Loading state of the data source */\n\tloading: Ref<boolean> | ComputedRef<boolean>;\n\t/** Stat definitions */\n\tdefinitions: StatDefinition<T>[];\n\t/** Delay between each stat reveal (ms) */\n\tstaggerDelay?: number;\n\t/** Initial delay before first stat reveals (ms) */\n\tinitialDelay?: number;\n\t/** Previous data for computing changes (optional) */\n\tpreviousData?: Ref<T[]> | ComputedRef<T[]>;\n}\n\n/**\n * Return type for useStats\n */\nexport interface UseStatsReturn<T> {\n\t/** Computed stats array for uiStats */\n\tstats: ComputedRef<StatItem[]>;\n\t/** Individual loading states for each stat */\n\tloadingStates: Ref<boolean[]>;\n\t/** Combined stats with loading property */\n\tstatsWithLoading: ComputedRef<Array<StatItem & { loading: boolean }>>;\n\t/** Whether all stats are loaded */\n\tallLoaded: ComputedRef<boolean>;\n\t/** Force refresh loading animation */\n\trefreshAnimation: () => void;\n\t/** Get a single stat by ID */\n\tgetStat: (id: string) => StatItem | undefined;\n}\n\n/**\n * Creates a stats composable for deriving statistics from reactive data\n *\n * @example\n * ```typescript\n * import { CheckCircleIcon, ClockIcon, XCircleIcon } from '@heroicons/vue/24/outline';\n *\n * const { statsWithLoading } = useStats({\n * data: campaigns,\n * loading: campaignsLoading,\n * definitions: [\n * {\n * id: 'active',\n * name: 'Active Campaigns',\n * icon: CheckCircleIcon,\n * color: 'green',\n * compute: (items) => items.filter(c => c.status === 'active').length,\n * },\n * {\n * id: 'pending',\n * name: 'Pending',\n * icon: ClockIcon,\n * color: 'yellow',\n * compute: (items) => items.filter(c => c.status === 'pending').length,\n * },\n * {\n * id: 'total-sent',\n * name: 'Total Sent',\n * icon: PaperAirplaneIcon,\n * color: 'blue',\n * compute: (items) => items.reduce((sum, c) => sum + c.sentCount, 0).toLocaleString(),\n * computeChange: (items) => '+12%',\n * computeChangeType: () => 'increase',\n * },\n * ],\n * staggerDelay: 100,\n * });\n *\n * // In template\n * <div class=\"grid grid-cols-4 gap-4\">\n * <uiStats\n * v-for=\"stat in statsWithLoading\"\n * :key=\"stat.id\"\n * :item=\"stat\"\n * :loading=\"stat.loading\"\n * @statClick=\"handleStatClick\"\n * />\n * </div>\n * ```\n */\nexport function useStats<T>(options: UseStatsOptions<T>): UseStatsReturn<T> {\n\tconst {\n\t\tdata,\n\t\tloading,\n\t\tdefinitions,\n\t\tstaggerDelay = 100,\n\t\tinitialDelay = 0,\n\t\tpreviousData,\n\t} = options;\n\n\t// Individual loading states for staggered animation\n\tconst loadingStates = ref<boolean[]>(definitions.map(() => true));\n\n\t// Timers for cleanup\n\tlet timers: ReturnType<typeof setTimeout>[] = [];\n\n\t// Clear all pending timers\n\tfunction clearTimers(): void {\n\t\ttimers.forEach(timer => clearTimeout(timer));\n\t\ttimers = [];\n\t}\n\n\t// Trigger staggered loading animation\n\tfunction triggerStaggeredReveal(): void {\n\t\tclearTimers();\n\n\t\t// Reset all to loading\n\t\tloadingStates.value = definitions.map(() => true);\n\n\t\t// Staggered reveal\n\t\tdefinitions.forEach((_, index) => {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tloadingStates.value[index] = false;\n\t\t\t}, initialDelay + staggerDelay * (index + 1));\n\t\t\ttimers.push(timer);\n\t\t});\n\t}\n\n\t// Watch for loading state changes\n\twatch(\n\t\t() => loading.value,\n\t\t(isLoading, wasLoading) => {\n\t\t\tif (wasLoading && !isLoading) {\n\t\t\t\t// Data just finished loading, trigger reveal\n\t\t\t\ttriggerStaggeredReveal();\n\t\t\t} else if (isLoading && !wasLoading) {\n\t\t\t\t// Started loading, reset states\n\t\t\t\tclearTimers();\n\t\t\t\tloadingStates.value = definitions.map(() => true);\n\t\t\t}\n\t\t},\n\t\t{ immediate: true }\n\t);\n\n\t// If data is already loaded on mount, trigger reveal\n\tif (!loading.value) {\n\t\ttriggerStaggeredReveal();\n\t}\n\n\t// Computed: Stats derived from data\n\tconst stats = computed<StatItem[]>(() => {\n\t\tconst items = data.value;\n\t\tconst prevItems = previousData?.value;\n\n\t\treturn definitions.map(def => {\n\t\t\tconst stat: StatItem = {\n\t\t\t\tid: def.id,\n\t\t\t\tname: def.name,\n\t\t\t\tstat: def.compute(items),\n\t\t\t\ticon: def.icon,\n\t\t\t\tcolor: def.color ?? 'gray',\n\t\t\t};\n\n\t\t\t// Add change information if provided\n\t\t\tif (def.computeChange) {\n\t\t\t\tstat.change = def.computeChange(items, prevItems);\n\t\t\t}\n\n\t\t\tif (def.computeChangeType) {\n\t\t\t\tstat.changeType = def.computeChangeType(items, prevItems);\n\t\t\t}\n\n\t\t\t// Footer options\n\t\t\tif (def.showFooter !== undefined) {\n\t\t\t\tstat.showFooter = def.showFooter;\n\t\t\t}\n\n\t\t\tif (def.actionText) {\n\t\t\t\tstat.actionText = def.actionText;\n\t\t\t}\n\n\t\t\treturn stat;\n\t\t});\n\t});\n\n\t// Computed: Stats with loading property included\n\tconst statsWithLoading = computed(() =>\n\t\tstats.value.map((stat, index) => ({\n\t\t\t...stat,\n\t\t\tloading: loading.value || loadingStates.value[index],\n\t\t}))\n\t);\n\n\t// Computed: All stats loaded\n\tconst allLoaded = computed(() =>\n\t\t!loading.value && loadingStates.value.every(s => !s)\n\t);\n\n\t// Get a single stat by ID\n\tfunction getStat(id: string): StatItem | undefined {\n\t\treturn stats.value.find(s => s.id === id);\n\t}\n\n\t// Manually refresh animation\n\tfunction refreshAnimation(): void {\n\t\ttriggerStaggeredReveal();\n\t}\n\n\treturn {\n\t\tstats,\n\t\tloadingStates,\n\t\tstatsWithLoading,\n\t\tallLoaded,\n\t\trefreshAnimation,\n\t\tgetStat,\n\t};\n}\n\n/**\n * Helper: Create a simple count stat definition\n */\nexport function countStat<T>(\n\tid: string,\n\tname: string,\n\ticon: Component,\n\tfilter: (item: T) => boolean,\n\toptions?: { color?: StatColor }\n): StatDefinition<T> {\n\treturn {\n\t\tid,\n\t\tname,\n\t\ticon,\n\t\tcolor: options?.color ?? 'gray',\n\t\tcompute: (items) => items.filter(filter).length,\n\t};\n}\n\n/**\n * Helper: Create a sum stat definition\n */\nexport function sumStat<T>(\n\tid: string,\n\tname: string,\n\ticon: Component,\n\tgetValue: (item: T) => number,\n\toptions?: { color?: StatColor; format?: (value: number) => string }\n): StatDefinition<T> {\n\treturn {\n\t\tid,\n\t\tname,\n\t\ticon,\n\t\tcolor: options?.color ?? 'gray',\n\t\tcompute: (items) => {\n\t\t\tconst sum = items.reduce((total, item) => total + getValue(item), 0);\n\t\t\treturn options?.format ? options.format(sum) : sum.toLocaleString();\n\t\t},\n\t};\n}\n\n/**\n * Helper: Create an average stat definition\n */\nexport function averageStat<T>(\n\tid: string,\n\tname: string,\n\ticon: Component,\n\tgetValue: (item: T) => number,\n\toptions?: { color?: StatColor; decimals?: number; suffix?: string }\n): StatDefinition<T> {\n\treturn {\n\t\tid,\n\t\tname,\n\t\ticon,\n\t\tcolor: options?.color ?? 'gray',\n\t\tcompute: (items) => {\n\t\t\tif (items.length === 0) return '0';\n\t\t\tconst sum = items.reduce((total, item) => total + getValue(item), 0);\n\t\t\tconst avg = sum / items.length;\n\t\t\tconst formatted = avg.toFixed(options?.decimals ?? 1);\n\t\t\treturn options?.suffix ? `${formatted}${options.suffix}` : formatted;\n\t\t},\n\t};\n}\n\n/**\n * Helper: Create a percentage stat definition\n */\nexport function percentageStat<T>(\n\tid: string,\n\tname: string,\n\ticon: Component,\n\tfilter: (item: T) => boolean,\n\toptions?: { color?: StatColor; decimals?: number }\n): StatDefinition<T> {\n\treturn {\n\t\tid,\n\t\tname,\n\t\ticon,\n\t\tcolor: options?.color ?? 'gray',\n\t\tcompute: (items) => {\n\t\t\tif (items.length === 0) return '0%';\n\t\t\tconst count = items.filter(filter).length;\n\t\t\tconst percentage = (count / items.length) * 100;\n\t\t\treturn `${percentage.toFixed(options?.decimals ?? 1)}%`;\n\t\t},\n\t};\n}\n","/**\n * Confirmation Composable\n *\n * Manages confirmation dialog state for destructive actions.\n * Works with uiModal from @hotelinking/ui.\n */\n\nimport { ref, computed, type Ref, type ComputedRef, type Component } from 'vue';\n\n/**\n * Confirmation dialog variant\n */\nexport type ConfirmationVariant = 'danger' | 'warning' | 'info' | 'default';\n\n/**\n * Configuration for a confirmation dialog\n */\nexport interface ConfirmationConfig {\n\t/** Dialog title */\n\ttitle: string;\n\t/** Dialog message/description */\n\tmessage: string;\n\t/** Text for confirm button */\n\tconfirmText?: string;\n\t/** Text for cancel button */\n\tcancelText?: string;\n\t/** Visual variant */\n\tvariant?: ConfirmationVariant;\n\t/** Icon component to display */\n\ticon?: Component;\n\t/** Whether action is in progress */\n\tloading?: boolean;\n}\n\n/**\n * Internal state for pending confirmation\n */\ninterface PendingConfirmation {\n\tresolve: (value: boolean) => void;\n\treject: (reason?: unknown) => void;\n}\n\n/**\n * Options for useConfirmation\n */\nexport interface UseConfirmationOptions {\n\t/** Default confirm button text */\n\tdefaultConfirmText?: string;\n\t/** Default cancel button text */\n\tdefaultCancelText?: string;\n\t/** Default variant */\n\tdefaultVariant?: ConfirmationVariant;\n}\n\n/**\n * Return type for useConfirmation\n */\nexport interface UseConfirmationReturn {\n\t/** Whether dialog is open */\n\tisOpen: Ref<boolean>;\n\t/** Current dialog configuration */\n\tconfig: Ref<ConfirmationConfig>;\n\t/** Whether action is in progress */\n\tisLoading: Ref<boolean>;\n\n\t/** Open confirmation dialog and wait for response */\n\tconfirm: (options: ConfirmationConfig) => Promise<boolean>;\n\t/** Handle confirm button click */\n\thandleConfirm: () => void;\n\t/** Handle cancel button click */\n\thandleCancel: () => void;\n\t/** Close dialog without triggering callbacks */\n\tclose: () => void;\n\n\t/** Convenience: Confirm delete action */\n\tconfirmDelete: (itemName: string, options?: Partial<ConfirmationConfig>) => Promise<boolean>;\n\t/** Convenience: Confirm bulk delete action */\n\tconfirmBulkDelete: (count: number, itemType?: string, options?: Partial<ConfirmationConfig>) => Promise<boolean>;\n\t/** Convenience: Confirm destructive action */\n\tconfirmDestructive: (actionName: string, options?: Partial<ConfirmationConfig>) => Promise<boolean>;\n\t/** Convenience: Confirm with custom async action */\n\tconfirmWithAction: <T>(\n\t\toptions: ConfirmationConfig,\n\t\taction: () => Promise<T>\n\t) => Promise<{ confirmed: boolean; result?: T; error?: Error }>;\n\n\t/** Props for uiModal component */\n\tmodalProps: ComputedRef<{\n\t\ttitle: string;\n\t\topen: boolean;\n\t\tmodalName: string;\n\t\tactions: Array<{ name: string; value: string }>;\n\t}>;\n}\n\n/**\n * Creates a confirmation dialog composable\n *\n * @example\n * ```typescript\n * const confirmation = useConfirmation();\n *\n * async function handleDelete(item: Item) {\n * const confirmed = await confirmation.confirmDelete(item.name);\n * if (confirmed) {\n * await deleteItem(item.id);\n * }\n * }\n *\n * // Or with async action\n * async function handleDeleteWithAction(item: Item) {\n * const { confirmed, error } = await confirmation.confirmWithAction(\n * { title: 'Delete Item', message: `Delete \"${item.name}\"?` },\n * () => deleteItem(item.id)\n * );\n * if (confirmed && !error) {\n * showSuccess('Item deleted');\n * }\n * }\n *\n * // In template\n * <Modal\n * v-bind=\"confirmation.modalProps\"\n * @modal-action=\"(e) => e.action === 'confirm' ? confirmation.handleConfirm() : confirmation.handleCancel()\"\n * >\n * <p>{{ confirmation.config.message }}</p>\n * </Modal>\n * ```\n */\nexport function useConfirmation(options: UseConfirmationOptions = {}): UseConfirmationReturn {\n\tconst {\n\t\tdefaultConfirmText = 'Confirm',\n\t\tdefaultCancelText = 'Cancel',\n\t\tdefaultVariant = 'default',\n\t} = options;\n\n\t// State\n\tconst isOpen = ref(false);\n\tconst isLoading = ref(false);\n\tconst config = ref<ConfirmationConfig>({\n\t\ttitle: '',\n\t\tmessage: '',\n\t\tconfirmText: defaultConfirmText,\n\t\tcancelText: defaultCancelText,\n\t\tvariant: defaultVariant,\n\t});\n\n\t// Pending promise resolution\n\tlet pending: PendingConfirmation | null = null;\n\n\t/**\n\t * Open confirmation dialog and wait for user response\n\t */\n\tfunction confirm(confirmConfig: ConfirmationConfig): Promise<boolean> {\n\t\t// Set configuration with defaults\n\t\tconfig.value = {\n\t\t\t...confirmConfig,\n\t\t\tconfirmText: confirmConfig.confirmText ?? defaultConfirmText,\n\t\t\tcancelText: confirmConfig.cancelText ?? defaultCancelText,\n\t\t\tvariant: confirmConfig.variant ?? defaultVariant,\n\t\t};\n\n\t\tisOpen.value = true;\n\t\tisLoading.value = false;\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tpending = { resolve, reject };\n\t\t});\n\t}\n\n\t/**\n\t * Handle confirm button click\n\t */\n\tfunction handleConfirm(): void {\n\t\tif (pending) {\n\t\t\tpending.resolve(true);\n\t\t\tpending = null;\n\t\t}\n\t\tisOpen.value = false;\n\t\tisLoading.value = false;\n\t}\n\n\t/**\n\t * Handle cancel button click\n\t */\n\tfunction handleCancel(): void {\n\t\tif (pending) {\n\t\t\tpending.resolve(false);\n\t\t\tpending = null;\n\t\t}\n\t\tisOpen.value = false;\n\t\tisLoading.value = false;\n\t}\n\n\t/**\n\t * Close dialog without resolving\n\t */\n\tfunction close(): void {\n\t\tif (pending) {\n\t\t\tpending.resolve(false);\n\t\t\tpending = null;\n\t\t}\n\t\tisOpen.value = false;\n\t\tisLoading.value = false;\n\t}\n\n\t/**\n\t * Convenience: Confirm delete action\n\t */\n\tfunction confirmDelete(\n\t\titemName: string,\n\t\tconfirmConfig?: Partial<ConfirmationConfig>\n\t): Promise<boolean> {\n\t\treturn confirm({\n\t\t\ttitle: 'Delete Item',\n\t\t\tmessage: `Are you sure you want to delete \"${itemName}\"? This action cannot be undone.`,\n\t\t\tconfirmText: 'Delete',\n\t\t\tcancelText: 'Cancel',\n\t\t\tvariant: 'danger',\n\t\t\t...confirmConfig,\n\t\t});\n\t}\n\n\t/**\n\t * Convenience: Confirm bulk delete action\n\t */\n\tfunction confirmBulkDelete(\n\t\tcount: number,\n\t\titemType: string = 'items',\n\t\tconfirmConfig?: Partial<ConfirmationConfig>\n\t): Promise<boolean> {\n\t\treturn confirm({\n\t\t\ttitle: `Delete ${count} ${itemType}`,\n\t\t\tmessage: `Are you sure you want to delete ${count} ${itemType}? This action cannot be undone.`,\n\t\t\tconfirmText: 'Delete All',\n\t\t\tcancelText: 'Cancel',\n\t\t\tvariant: 'danger',\n\t\t\t...confirmConfig,\n\t\t});\n\t}\n\n\t/**\n\t * Convenience: Confirm destructive action\n\t */\n\tfunction confirmDestructive(\n\t\tactionName: string,\n\t\tconfirmConfig?: Partial<ConfirmationConfig>\n\t): Promise<boolean> {\n\t\treturn confirm({\n\t\t\ttitle: `Confirm ${actionName}`,\n\t\t\tmessage: `Are you sure you want to ${actionName.toLowerCase()}? This action cannot be undone.`,\n\t\t\tconfirmText: actionName,\n\t\t\tcancelText: 'Cancel',\n\t\t\tvariant: 'danger',\n\t\t\t...confirmConfig,\n\t\t});\n\t}\n\n\t/**\n\t * Convenience: Confirm with async action execution\n\t */\n\tasync function confirmWithAction<T>(\n\t\tconfirmConfig: ConfirmationConfig,\n\t\taction: () => Promise<T>\n\t): Promise<{ confirmed: boolean; result?: T; error?: Error }> {\n\t\tconst confirmed = await confirm(confirmConfig);\n\n\t\tif (!confirmed) {\n\t\t\treturn { confirmed: false };\n\t\t}\n\n\t\t// Show loading state\n\t\tisLoading.value = true;\n\n\t\ttry {\n\t\t\tconst result = await action();\n\t\t\tisOpen.value = false;\n\t\t\tisLoading.value = false;\n\t\t\treturn { confirmed: true, result };\n\t\t} catch (error) {\n\t\t\tisLoading.value = false;\n\t\t\treturn {\n\t\t\t\tconfirmed: true,\n\t\t\t\terror: error instanceof Error ? error : new Error(String(error)),\n\t\t\t};\n\t\t}\n\t}\n\n\t/**\n\t * Props for uiModal component\n\t */\n\tconst modalProps = computed(() => ({\n\t\ttitle: config.value.title,\n\t\topen: isOpen.value,\n\t\tmodalName: 'confirmation-dialog',\n\t\tactions: [\n\t\t\t{\n\t\t\t\tname: config.value.cancelText ?? defaultCancelText,\n\t\t\t\tvalue: 'cancel',\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: config.value.confirmText ?? defaultConfirmText,\n\t\t\t\tvalue: 'confirm',\n\t\t\t},\n\t\t],\n\t}));\n\n\treturn {\n\t\t// State\n\t\tisOpen,\n\t\tconfig,\n\t\tisLoading,\n\n\t\t// Core methods\n\t\tconfirm,\n\t\thandleConfirm,\n\t\thandleCancel,\n\t\tclose,\n\n\t\t// Convenience methods\n\t\tconfirmDelete,\n\t\tconfirmBulkDelete,\n\t\tconfirmDestructive,\n\t\tconfirmWithAction,\n\n\t\t// Modal props\n\t\tmodalProps,\n\t};\n}\n\n/**\n * Global confirmation instance for use across components\n */\nlet globalConfirmation: UseConfirmationReturn | null = null;\n\n/**\n * Get or create global confirmation instance\n *\n * @example\n * ```typescript\n * // In any component\n * const confirmation = useGlobalConfirmation();\n * await confirmation.confirmDelete('Item Name');\n * ```\n */\nexport function useGlobalConfirmation(): UseConfirmationReturn {\n\tif (!globalConfirmation) {\n\t\tglobalConfirmation = useConfirmation();\n\t}\n\treturn globalConfirmation;\n}\n\n/**\n * Reset global confirmation instance (useful for testing)\n */\nexport function resetGlobalConfirmation(): void {\n\tglobalConfirmation = null;\n}\n","/**\n * Admin Page Composable\n *\n * Provides common page-level state and configuration for admin pages.\n * Integrates with AdminWrapper, Breadcrumbs, and page context.\n */\n\nimport { ref, computed, onMounted, type Ref, type ComputedRef, type Component } from 'vue';\nimport { usePageContext, type PageUser, type PageBrand } from './usePageContext';\n\n/**\n * Breadcrumb item\n */\nexport interface BreadcrumbItem {\n\t/** Display name */\n\tname: string;\n\t/** Route path or name */\n\thref?: string;\n\t/** Whether this is the current page */\n\tcurrent?: boolean;\n\t/** Icon component */\n\ticon?: Component;\n}\n\n/**\n * Page action button\n */\nexport interface PageAction {\n\t/** Unique identifier */\n\tid: string;\n\t/** Button text */\n\ttext: string;\n\t/** Button icon */\n\ticon?: Component;\n\t/** Button color variant */\n\tcolor?: 'primary' | 'secondary' | 'danger' | 'warning';\n\t/** Whether button is disabled */\n\tdisabled?: boolean;\n\t/** Whether button shows loading state */\n\tloading?: boolean;\n\t/** Click handler */\n\tonClick?: () => void | Promise<void>;\n}\n\n/**\n * Options for useAdminPage\n */\nexport interface UseAdminPageOptions {\n\t/** Page title */\n\ttitle: string;\n\t/** Page subtitle (optional) */\n\tsubtitle?: string;\n\t/** Page description (optional) */\n\tdescription?: string;\n\t/** Breadcrumb items (without current page) */\n\tbreadcrumbs?: BreadcrumbItem[];\n\t/** Active sidebar item ID */\n\tsidebarActive?: string;\n\t/** Page action buttons */\n\tactions?: PageAction[];\n\t/** Initial loading state */\n\tloading?: boolean;\n\t/** Loading reveal delay (ms) */\n\tloadingDelay?: number;\n}\n\n/**\n * Return type for useAdminPage\n */\nexport interface UseAdminPageReturn {\n\t// Page info\n\ttitle: string;\n\tsubtitle: string | undefined;\n\tdescription: string | undefined;\n\n\t// Breadcrumbs\n\tbreadcrumbs: ComputedRef<BreadcrumbItem[]>;\n\n\t// Loading state (with staggered reveal)\n\tloadingHeader: Ref<boolean>;\n\tloadingContent: Ref<boolean>;\n\tsetLoading: (loading: boolean) => void;\n\n\t// Page context\n\tuser: ComputedRef<PageUser | null>;\n\tbrand: ComputedRef<PageBrand | null>;\n\tisAdmin: ComputedRef<boolean>;\n\tisSuperAdmin: ComputedRef<boolean>;\n\n\t// Actions\n\tactions: Ref<PageAction[]>;\n\tupdateAction: (id: string, updates: Partial<PageAction>) => void;\n\tsetActionLoading: (id: string, loading: boolean) => void;\n\n\t// Wrapper props\n\twrapperProps: ComputedRef<{\n\t\tcurrentPage: string | undefined;\n\t}>;\n\n\t// Header props (for uiViewHeader)\n\theaderProps: ComputedRef<{\n\t\ttitle: string;\n\t\tsubtitle?: string;\n\t\tdescription?: string;\n\t\tpages: BreadcrumbItem[];\n\t\tloading: boolean;\n\t}>;\n}\n\n/**\n * Creates an admin page composable for common page setup\n *\n * @example\n * ```typescript\n * const page = useAdminPage({\n * title: 'Campaigns',\n * subtitle: 'Manage your email campaigns',\n * breadcrumbs: [\n * { name: 'Dashboard', href: '/dashboard' },\n * { name: 'Marketing', href: '/marketing' },\n * ],\n * sidebarActive: 'campaigns',\n * actions: [\n * {\n * id: 'create',\n * text: 'Create Campaign',\n * icon: PlusIcon,\n * color: 'primary',\n * onClick: () => navigateTo('/campaigns/create'),\n * },\n * ],\n * });\n *\n * // In template\n * <AdminWrapper v-bind=\"page.wrapperProps\">\n * <uiViewHeader v-bind=\"page.headerProps\" />\n * <!-- Content -->\n * </AdminWrapper>\n * ```\n */\nexport function useAdminPage(options: UseAdminPageOptions): UseAdminPageReturn {\n\tconst {\n\t\ttitle,\n\t\tsubtitle,\n\t\tdescription,\n\t\tbreadcrumbs: initialBreadcrumbs = [],\n\t\tsidebarActive,\n\t\tactions: initialActions = [],\n\t\tloading: initialLoading = true,\n\t\tloadingDelay = 200,\n\t} = options;\n\n\t// Get page context\n\tconst context = usePageContext();\n\n\t// Loading states\n\tconst loadingHeader = ref(initialLoading);\n\tconst loadingContent = ref(initialLoading);\n\n\t// Actions state\n\tconst actions = ref<PageAction[]>([...initialActions]);\n\n\t// Staggered loading reveal on mount\n\tonMounted(() => {\n\t\tif (initialLoading) {\n\t\t\tsetTimeout(() => {\n\t\t\t\tloadingHeader.value = false;\n\t\t\t}, loadingDelay);\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tloadingContent.value = false;\n\t\t\t}, loadingDelay * 2);\n\t\t}\n\t});\n\n\t// Computed: User from context\n\tconst user = computed(() => context.value.user);\n\n\t// Computed: Brand from context\n\tconst brand = computed(() => context.value.brand);\n\n\t// Computed: Admin status\n\tconst isAdmin = computed(() => user.value?.isAdmin ?? false);\n\n\t// Computed: Super admin status\n\tconst isSuperAdmin = computed(() => user.value?.isSuperAdmin ?? false);\n\n\t// Computed: Breadcrumbs with current page\n\tconst breadcrumbs = computed<BreadcrumbItem[]>(() => [\n\t\t...initialBreadcrumbs.map(b => ({ ...b, current: false })),\n\t\t{ name: title, current: true },\n\t]);\n\n\t// Computed: Props for AdminWrapper\n\tconst wrapperProps = computed(() => ({\n\t\tcurrentPage: sidebarActive,\n\t}));\n\n\t// Computed: Props for uiViewHeader\n\tconst headerProps = computed(() => ({\n\t\ttitle,\n\t\tsubtitle,\n\t\tdescription,\n\t\tpages: breadcrumbs.value,\n\t\tloading: loadingHeader.value,\n\t}));\n\n\t// Set loading state\n\tfunction setLoading(loading: boolean): void {\n\t\tif (loading) {\n\t\t\tloadingHeader.value = true;\n\t\t\tloadingContent.value = true;\n\t\t} else {\n\t\t\tsetTimeout(() => {\n\t\t\t\tloadingHeader.value = false;\n\t\t\t}, loadingDelay);\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tloadingContent.value = false;\n\t\t\t}, loadingDelay * 2);\n\t\t}\n\t}\n\n\t// Update action by ID\n\tfunction updateAction(id: string, updates: Partial<PageAction>): void {\n\t\tconst index = actions.value.findIndex(a => a.id === id);\n\t\tif (index !== -1) {\n\t\t\tactions.value[index] = { ...actions.value[index], ...updates };\n\t\t}\n\t}\n\n\t// Set action loading state\n\tfunction setActionLoading(id: string, loading: boolean): void {\n\t\tupdateAction(id, { loading });\n\t}\n\n\treturn {\n\t\t// Page info\n\t\ttitle,\n\t\tsubtitle,\n\t\tdescription,\n\n\t\t// Breadcrumbs\n\t\tbreadcrumbs,\n\n\t\t// Loading\n\t\tloadingHeader,\n\t\tloadingContent,\n\t\tsetLoading,\n\n\t\t// Context\n\t\tuser,\n\t\tbrand,\n\t\tisAdmin,\n\t\tisSuperAdmin,\n\n\t\t// Actions\n\t\tactions,\n\t\tupdateAction,\n\t\tsetActionLoading,\n\n\t\t// Props\n\t\twrapperProps,\n\t\theaderProps,\n\t};\n}\n\n/**\n * Helper: Create a list page configuration\n *\n * @example\n * const page = useListPage({\n * title: 'Users',\n * entityName: 'user',\n * breadcrumbs: [{ name: 'Settings', href: '/settings' }],\n * sidebarActive: 'users',\n * onCreateClick: () => navigateTo('/users/create'),\n * });\n */\nexport interface UseListPageOptions extends Omit<UseAdminPageOptions, 'actions'> {\n\t/** Entity name for create button (e.g., 'user' -> 'Create User') */\n\tentityName?: string;\n\t/** Create button click handler */\n\tonCreateClick?: () => void;\n\t/** Create button icon */\n\tcreateIcon?: Component;\n\t/** Hide create button */\n\thideCreate?: boolean;\n}\n\nexport function useListPage(options: UseListPageOptions): UseAdminPageReturn {\n\tconst {\n\t\tentityName,\n\t\tonCreateClick,\n\t\tcreateIcon,\n\t\thideCreate = false,\n\t\t...pageOptions\n\t} = options;\n\n\tconst actions: PageAction[] = [];\n\n\tif (!hideCreate && entityName) {\n\t\tactions.push({\n\t\t\tid: 'create',\n\t\t\ttext: `Create ${entityName.charAt(0).toUpperCase() + entityName.slice(1)}`,\n\t\t\ticon: createIcon,\n\t\t\tcolor: 'primary',\n\t\t\tonClick: onCreateClick,\n\t\t});\n\t}\n\n\treturn useAdminPage({\n\t\t...pageOptions,\n\t\tactions,\n\t});\n}\n\n/**\n * Helper: Create a detail page configuration\n *\n * @example\n * const page = useDetailPage({\n * title: 'User Details',\n * entityName: 'user',\n * breadcrumbs: [\n * { name: 'Settings', href: '/settings' },\n * { name: 'Users', href: '/users' },\n * ],\n * onEditClick: () => navigateTo(`/users/${id}/edit`),\n * onDeleteClick: () => confirmDelete(),\n * });\n */\nexport interface UseDetailPageOptions extends Omit<UseAdminPageOptions, 'actions'> {\n\t/** Entity name for action buttons */\n\tentityName?: string;\n\t/** Edit button click handler */\n\tonEditClick?: () => void;\n\t/** Delete button click handler */\n\tonDeleteClick?: () => void;\n\t/** Edit button icon */\n\teditIcon?: Component;\n\t/** Delete button icon */\n\tdeleteIcon?: Component;\n\t/** Hide edit button */\n\thideEdit?: boolean;\n\t/** Hide delete button */\n\thideDelete?: boolean;\n}\n\nexport function useDetailPage(options: UseDetailPageOptions): UseAdminPageReturn {\n\tconst {\n\t\tentityName,\n\t\tonEditClick,\n\t\tonDeleteClick,\n\t\teditIcon,\n\t\tdeleteIcon,\n\t\thideEdit = false,\n\t\thideDelete = false,\n\t\t...pageOptions\n\t} = options;\n\n\tconst actions: PageAction[] = [];\n\n\tif (!hideEdit && onEditClick) {\n\t\tactions.push({\n\t\t\tid: 'edit',\n\t\t\ttext: 'Edit',\n\t\t\ticon: editIcon,\n\t\t\tcolor: 'secondary',\n\t\t\tonClick: onEditClick,\n\t\t});\n\t}\n\n\tif (!hideDelete && onDeleteClick) {\n\t\tactions.push({\n\t\t\tid: 'delete',\n\t\t\ttext: 'Delete',\n\t\t\ticon: deleteIcon,\n\t\t\tcolor: 'danger',\n\t\t\tonClick: onDeleteClick,\n\t\t});\n\t}\n\n\treturn useAdminPage({\n\t\t...pageOptions,\n\t\tactions,\n\t});\n}\n\n/**\n * Helper: Create a form page configuration\n *\n * @example\n * const page = useFormPage({\n * title: 'Create User',\n * breadcrumbs: [\n * { name: 'Settings', href: '/settings' },\n * { name: 'Users', href: '/users' },\n * ],\n * onSaveClick: () => saveUser(),\n * onCancelClick: () => navigateTo('/users'),\n * });\n */\nexport interface UseFormPageOptions extends Omit<UseAdminPageOptions, 'actions'> {\n\t/** Save button click handler */\n\tonSaveClick?: () => void | Promise<void>;\n\t/** Cancel button click handler */\n\tonCancelClick?: () => void;\n\t/** Save button text */\n\tsaveText?: string;\n\t/** Cancel button text */\n\tcancelText?: string;\n\t/** Save button icon */\n\tsaveIcon?: Component;\n\t/** Cancel button icon */\n\tcancelIcon?: Component;\n\t/** Hide save button */\n\thideSave?: boolean;\n\t/** Hide cancel button */\n\thideCancel?: boolean;\n}\n\nexport function useFormPage(options: UseFormPageOptions): UseAdminPageReturn {\n\tconst {\n\t\tonSaveClick,\n\t\tonCancelClick,\n\t\tsaveText = 'Save',\n\t\tcancelText = 'Cancel',\n\t\tsaveIcon,\n\t\tcancelIcon,\n\t\thideSave = false,\n\t\thideCancel = false,\n\t\t...pageOptions\n\t} = options;\n\n\tconst actions: PageAction[] = [];\n\n\tif (!hideCancel && onCancelClick) {\n\t\tactions.push({\n\t\t\tid: 'cancel',\n\t\t\ttext: cancelText,\n\t\t\ticon: cancelIcon,\n\t\t\tcolor: 'secondary',\n\t\t\tonClick: onCancelClick,\n\t\t});\n\t}\n\n\tif (!hideSave && onSaveClick) {\n\t\tactions.push({\n\t\t\tid: 'save',\n\t\t\ttext: saveText,\n\t\t\ticon: saveIcon,\n\t\t\tcolor: 'primary',\n\t\t\tonClick: onSaveClick,\n\t\t});\n\t}\n\n\treturn useAdminPage({\n\t\t...pageOptions,\n\t\tactions,\n\t});\n}\n"],"names":["nextTab","isValid","min","max"],"mappings":"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"}
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { computed, unref, ref } from "vue";
|
|
2
|
+
function useTable(options) {
|
|
3
|
+
const idKey = options.idKey ?? "id";
|
|
4
|
+
const items = computed(() => {
|
|
5
|
+
try {
|
|
6
|
+
const unwrapped = unref(options.items);
|
|
7
|
+
if (!unwrapped) return [];
|
|
8
|
+
if (!Array.isArray(unwrapped)) {
|
|
9
|
+
console.warn("useTable: items is not an array", unwrapped);
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
12
|
+
return unwrapped;
|
|
13
|
+
} catch (error) {
|
|
14
|
+
console.error("useTable: Error unwrapping items", error);
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
const currentPage = ref(1);
|
|
19
|
+
const pageSize = ref(options.pageSize ?? 10);
|
|
20
|
+
const sortKey = ref(options.sortKey ?? "");
|
|
21
|
+
const sortOrder = ref(options.sortOrder ?? "asc");
|
|
22
|
+
const selectedItems = ref([]);
|
|
23
|
+
const selectedItemIds = ref(/* @__PURE__ */ new Set());
|
|
24
|
+
const resetSelected = ref(false);
|
|
25
|
+
const activeFilters = ref([]);
|
|
26
|
+
const hiddenColumns = ref([]);
|
|
27
|
+
const filteredItems = computed(() => {
|
|
28
|
+
const filters = Array.isArray(activeFilters.value) ? activeFilters.value : [];
|
|
29
|
+
if (filters.length === 0) return items.value;
|
|
30
|
+
return items.value.filter((item) => {
|
|
31
|
+
return filters.every((filter) => {
|
|
32
|
+
const { category, operator, value } = filter;
|
|
33
|
+
if (value === void 0 || value === null || value === "") return true;
|
|
34
|
+
const itemValue = item[category];
|
|
35
|
+
switch (operator) {
|
|
36
|
+
case "contains":
|
|
37
|
+
return String(itemValue).toLowerCase().includes(String(value).toLowerCase());
|
|
38
|
+
case "is":
|
|
39
|
+
case "=":
|
|
40
|
+
return itemValue === value;
|
|
41
|
+
case ">":
|
|
42
|
+
case "greater":
|
|
43
|
+
return Number(itemValue) > Number(value);
|
|
44
|
+
case "<":
|
|
45
|
+
case "less":
|
|
46
|
+
return Number(itemValue) < Number(value);
|
|
47
|
+
case ">=":
|
|
48
|
+
case "greaterOrEqual":
|
|
49
|
+
return Number(itemValue) >= Number(value);
|
|
50
|
+
case "<=":
|
|
51
|
+
case "lessOrEqual":
|
|
52
|
+
return Number(itemValue) <= Number(value);
|
|
53
|
+
default:
|
|
54
|
+
return String(itemValue).toLowerCase().includes(String(value).toLowerCase());
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
const sortedItems = computed(() => {
|
|
60
|
+
if (!sortKey.value) return filteredItems.value;
|
|
61
|
+
return [...filteredItems.value].sort((a, b) => {
|
|
62
|
+
const aVal = a[sortKey.value];
|
|
63
|
+
const bVal = b[sortKey.value];
|
|
64
|
+
const order = sortOrder.value === "asc" ? 1 : -1;
|
|
65
|
+
if (aVal === bVal) return 0;
|
|
66
|
+
if (aVal == null) return 1;
|
|
67
|
+
if (bVal == null) return -1;
|
|
68
|
+
if (typeof aVal === "string" && typeof bVal === "string") {
|
|
69
|
+
return aVal.localeCompare(bVal) * order;
|
|
70
|
+
}
|
|
71
|
+
return aVal > bVal ? order : -order;
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
const paginatedItems = computed(() => {
|
|
75
|
+
const start = (currentPage.value - 1) * pageSize.value;
|
|
76
|
+
const end = start + pageSize.value;
|
|
77
|
+
return sortedItems.value.slice(start, end);
|
|
78
|
+
});
|
|
79
|
+
const totalPages = computed(
|
|
80
|
+
() => Math.ceil(sortedItems.value.length / pageSize.value)
|
|
81
|
+
);
|
|
82
|
+
const totalItems = computed(() => sortedItems.value.length);
|
|
83
|
+
const allSelected = computed(() => {
|
|
84
|
+
if (items.value.length === 0) return false;
|
|
85
|
+
return selectedItemIds.value.size === items.value.length;
|
|
86
|
+
});
|
|
87
|
+
const someSelected = computed(() => {
|
|
88
|
+
return selectedItemIds.value.size > 0 && !allSelected.value;
|
|
89
|
+
});
|
|
90
|
+
function setPage(page) {
|
|
91
|
+
if (page >= 1 && page <= totalPages.value) {
|
|
92
|
+
currentPage.value = page;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function setPageSize(size) {
|
|
96
|
+
pageSize.value = size;
|
|
97
|
+
currentPage.value = 1;
|
|
98
|
+
}
|
|
99
|
+
function handlePageChange(page) {
|
|
100
|
+
setPage(page);
|
|
101
|
+
}
|
|
102
|
+
function handlePageSizeChange(size) {
|
|
103
|
+
const numSize = typeof size === "string" ? parseInt(size) : size;
|
|
104
|
+
setPageSize(numSize);
|
|
105
|
+
}
|
|
106
|
+
function setSorting(key, order = "asc") {
|
|
107
|
+
if (sortKey.value === key) {
|
|
108
|
+
sortOrder.value = sortOrder.value === "asc" ? "desc" : "asc";
|
|
109
|
+
} else {
|
|
110
|
+
sortKey.value = key;
|
|
111
|
+
sortOrder.value = order;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function handleOrderBy(event) {
|
|
115
|
+
sortKey.value = event.value;
|
|
116
|
+
sortOrder.value = event.orderDirection;
|
|
117
|
+
}
|
|
118
|
+
function getItemId(item) {
|
|
119
|
+
return item[idKey];
|
|
120
|
+
}
|
|
121
|
+
function selectItem(item) {
|
|
122
|
+
const id = getItemId(item);
|
|
123
|
+
if (!selectedItemIds.value.has(id)) {
|
|
124
|
+
selectedItemIds.value.add(id);
|
|
125
|
+
selectedItems.value.push(item);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function deselectItem(item) {
|
|
129
|
+
const id = getItemId(item);
|
|
130
|
+
if (selectedItemIds.value.has(id)) {
|
|
131
|
+
selectedItemIds.value.delete(id);
|
|
132
|
+
const index = selectedItems.value.findIndex((i) => getItemId(i) === id);
|
|
133
|
+
if (index !== -1) {
|
|
134
|
+
selectedItems.value.splice(index, 1);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function selectAll() {
|
|
139
|
+
selectedItemIds.value.clear();
|
|
140
|
+
selectedItems.value.length = 0;
|
|
141
|
+
items.value.forEach((item) => {
|
|
142
|
+
const id = getItemId(item);
|
|
143
|
+
selectedItemIds.value.add(id);
|
|
144
|
+
selectedItems.value.push(item);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
function selectAllOnPage() {
|
|
148
|
+
paginatedItems.value.forEach((item) => {
|
|
149
|
+
selectItem(item);
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
function clearSelection() {
|
|
153
|
+
selectedItemIds.value.clear();
|
|
154
|
+
selectedItems.value.length = 0;
|
|
155
|
+
resetSelected.value = true;
|
|
156
|
+
setTimeout(() => {
|
|
157
|
+
resetSelected.value = false;
|
|
158
|
+
}, 100);
|
|
159
|
+
}
|
|
160
|
+
function isSelected(item) {
|
|
161
|
+
const id = getItemId(item);
|
|
162
|
+
return selectedItemIds.value.has(id);
|
|
163
|
+
}
|
|
164
|
+
function applyFilters(filters) {
|
|
165
|
+
if (Array.isArray(filters)) {
|
|
166
|
+
activeFilters.value = filters;
|
|
167
|
+
} else if (filters && typeof filters === "object") {
|
|
168
|
+
if ("filters" in filters && Array.isArray(filters.filters)) {
|
|
169
|
+
activeFilters.value = filters.filters;
|
|
170
|
+
} else {
|
|
171
|
+
activeFilters.value = Object.entries(filters).filter(([_, value]) => value !== void 0 && value !== null && value !== "").map(([key, value]) => ({
|
|
172
|
+
category: key,
|
|
173
|
+
operator: "contains",
|
|
174
|
+
value
|
|
175
|
+
}));
|
|
176
|
+
}
|
|
177
|
+
} else {
|
|
178
|
+
activeFilters.value = [];
|
|
179
|
+
}
|
|
180
|
+
currentPage.value = 1;
|
|
181
|
+
}
|
|
182
|
+
function clearFilters() {
|
|
183
|
+
activeFilters.value = [];
|
|
184
|
+
currentPage.value = 1;
|
|
185
|
+
}
|
|
186
|
+
function removeFilter(index) {
|
|
187
|
+
if (index >= 0 && index < activeFilters.value.length) {
|
|
188
|
+
activeFilters.value.splice(index, 1);
|
|
189
|
+
currentPage.value = 1;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function handleSmartFiltersApplied(filters) {
|
|
193
|
+
applyFilters(filters);
|
|
194
|
+
}
|
|
195
|
+
function handleSmartFiltersCleared() {
|
|
196
|
+
clearFilters();
|
|
197
|
+
}
|
|
198
|
+
function handleSmartFilterDeleted(index) {
|
|
199
|
+
removeFilter(index);
|
|
200
|
+
}
|
|
201
|
+
function toggleColumn(index) {
|
|
202
|
+
const hiddenIndex = hiddenColumns.value.indexOf(index);
|
|
203
|
+
if (hiddenIndex > -1) {
|
|
204
|
+
hiddenColumns.value.splice(hiddenIndex, 1);
|
|
205
|
+
} else {
|
|
206
|
+
hiddenColumns.value.push(index);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
function showColumn(index) {
|
|
210
|
+
const hiddenIndex = hiddenColumns.value.indexOf(index);
|
|
211
|
+
if (hiddenIndex > -1) {
|
|
212
|
+
hiddenColumns.value.splice(hiddenIndex, 1);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
function hideColumn(index) {
|
|
216
|
+
if (!hiddenColumns.value.includes(index)) {
|
|
217
|
+
hiddenColumns.value.push(index);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
function handleColumnsVisibilityChanged(event) {
|
|
221
|
+
if (event.hidden) {
|
|
222
|
+
hideColumn(event.index);
|
|
223
|
+
} else {
|
|
224
|
+
showColumn(event.index);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
function handleModalAction(event) {
|
|
228
|
+
if (event.modal === "selectAllItemsModal" || event.modal.includes("selectAll")) {
|
|
229
|
+
if (event.action === "selectAll") {
|
|
230
|
+
selectAll();
|
|
231
|
+
} else if (event.action === "close") {
|
|
232
|
+
selectAllOnPage();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return {
|
|
237
|
+
// Pagination
|
|
238
|
+
currentPage,
|
|
239
|
+
pageSize,
|
|
240
|
+
totalPages,
|
|
241
|
+
totalItems,
|
|
242
|
+
paginatedItems,
|
|
243
|
+
// Sorting
|
|
244
|
+
sortKey,
|
|
245
|
+
sortOrder,
|
|
246
|
+
sortedItems,
|
|
247
|
+
// Selection
|
|
248
|
+
selectedItems,
|
|
249
|
+
selectedItemIds,
|
|
250
|
+
allSelected,
|
|
251
|
+
someSelected,
|
|
252
|
+
// Filtering
|
|
253
|
+
activeFilters,
|
|
254
|
+
filteredItems,
|
|
255
|
+
// Column visibility
|
|
256
|
+
hiddenColumns,
|
|
257
|
+
// Reset state
|
|
258
|
+
resetSelected,
|
|
259
|
+
// Methods - Pagination
|
|
260
|
+
setPage,
|
|
261
|
+
setPageSize,
|
|
262
|
+
handlePageChange,
|
|
263
|
+
handlePageSizeChange,
|
|
264
|
+
// Methods - Sorting
|
|
265
|
+
setSorting,
|
|
266
|
+
handleOrderBy,
|
|
267
|
+
// Methods - Selection
|
|
268
|
+
selectItem,
|
|
269
|
+
deselectItem,
|
|
270
|
+
selectAll,
|
|
271
|
+
selectAllOnPage,
|
|
272
|
+
clearSelection,
|
|
273
|
+
isSelected,
|
|
274
|
+
// Methods - Filtering
|
|
275
|
+
applyFilters,
|
|
276
|
+
clearFilters,
|
|
277
|
+
removeFilter,
|
|
278
|
+
handleSmartFiltersApplied,
|
|
279
|
+
handleSmartFiltersCleared,
|
|
280
|
+
handleSmartFilterDeleted,
|
|
281
|
+
// Methods - Column visibility
|
|
282
|
+
toggleColumn,
|
|
283
|
+
showColumn,
|
|
284
|
+
hideColumn,
|
|
285
|
+
handleColumnsVisibilityChanged,
|
|
286
|
+
// Methods - Modal actions
|
|
287
|
+
handleModalAction
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
export {
|
|
291
|
+
useTable as u
|
|
292
|
+
};
|
|
293
|
+
//# sourceMappingURL=useTable-DutR1gkg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTable-DutR1gkg.js","sources":["../src/composables/useTable.ts"],"sourcesContent":["import { ref, computed, unref, type Ref, type ComputedRef, type MaybeRef } from 'vue';\n\nexport interface SmartFilter {\n category: string;\n operator: string;\n value: any;\n}\n\nexport interface UseTableOptions<T> {\n items: MaybeRef<T[]>; // Accept both arrays and refs/computed\n pageSize?: number;\n sortKey?: string;\n sortOrder?: 'asc' | 'desc';\n idKey?: string; // Key to use for item identification (default: 'id')\n}\n\nexport interface UseTableReturn<T> {\n // Pagination\n currentPage: Ref<number>;\n pageSize: Ref<number>;\n totalPages: ComputedRef<number>;\n totalItems: ComputedRef<number>;\n paginatedItems: ComputedRef<T[]>;\n \n // Sorting\n sortKey: Ref<string>;\n sortOrder: Ref<'asc' | 'desc'>;\n sortedItems: ComputedRef<T[]>;\n \n // Selection\n selectedItems: Ref<T[]>;\n selectedItemIds: Ref<Set<string | number>>;\n allSelected: ComputedRef<boolean>;\n someSelected: ComputedRef<boolean>;\n \n // Filtering\n activeFilters: Ref<SmartFilter[]>;\n filteredItems: ComputedRef<T[]>;\n \n // Column visibility\n hiddenColumns: Ref<number[]>;\n \n // Reset state\n resetSelected: Ref<boolean>;\n \n // Methods - Pagination\n setPage: (page: number) => void;\n setPageSize: (size: number) => void;\n \n // Methods - Sorting\n setSorting: (key: string, order?: 'asc' | 'desc') => void;\n handleOrderBy: (event: { value: string; orderDirection: 'asc' | 'desc' }) => void;\n \n // Methods - Selection\n selectItem: (item: T) => void;\n deselectItem: (item: T) => void;\n selectAll: () => void;\n selectAllOnPage: () => void;\n clearSelection: () => void;\n isSelected: (item: T) => boolean;\n \n // Methods - Filtering\n applyFilters: (filters: SmartFilter[]) => void;\n clearFilters: () => void;\n removeFilter: (index: number) => void;\n \n // Methods - Column visibility\n toggleColumn: (index: number) => void;\n showColumn: (index: number) => void;\n hideColumn: (index: number) => void;\n \n // Event handlers for uiTable\n handlePageChange: (page: number) => void;\n handlePageSizeChange: (size: number | string) => void;\n handleSmartFiltersApplied: (filters: SmartFilter[]) => void;\n handleSmartFiltersCleared: () => void;\n handleSmartFilterDeleted: (index: number) => void;\n handleColumnsVisibilityChanged: (event: { index: number; hidden: boolean }) => void;\n handleModalAction: (event: { modal: string; action: string }) => void;\n}\n\nexport function useTable<T extends Record<string, any>>(\n options: UseTableOptions<T>\n): UseTableReturn<T> {\n const idKey = options.idKey ?? 'id';\n \n // Create a reactive reference to items with safety check\n const items = computed(() => {\n try {\n const unwrapped = unref(options.items);\n // Ensure we always return an array\n if (!unwrapped) return [];\n if (!Array.isArray(unwrapped)) {\n console.warn('useTable: items is not an array', unwrapped);\n return [];\n }\n return unwrapped;\n } catch (error) {\n console.error('useTable: Error unwrapping items', error);\n return [];\n }\n });\n \n // State - Pagination\n const currentPage = ref(1);\n const pageSize = ref(options.pageSize ?? 10);\n \n // State - Sorting\n const sortKey = ref(options.sortKey ?? '');\n const sortOrder = ref<'asc' | 'desc'>(options.sortOrder ?? 'asc');\n \n // State - Selection\n const selectedItems = ref<T[]>([]) as Ref<T[]>;\n const selectedItemIds = ref<Set<string | number>>(new Set());\n const resetSelected = ref(false);\n \n // State - Filtering\n const activeFilters = ref<SmartFilter[]>([]);\n \n // State - Column visibility\n const hiddenColumns = ref<number[]>([]);\n\n // Computed - Filtering\n const filteredItems = computed(() => {\n // Ensure activeFilters is always an array\n const filters = Array.isArray(activeFilters.value) ? activeFilters.value : [];\n if (filters.length === 0) return items.value;\n\n return items.value.filter(item => {\n // All filters must pass (AND logic by default)\n return filters.every(filter => {\n const { category, operator, value } = filter;\n \n if (value === undefined || value === null || value === '') return true;\n \n const itemValue = item[category];\n \n // Handle different operators\n switch (operator) {\n case 'contains':\n return String(itemValue).toLowerCase().includes(String(value).toLowerCase());\n case 'is':\n case '=':\n return itemValue === value;\n case '>':\n case 'greater':\n return Number(itemValue) > Number(value);\n case '<':\n case 'less':\n return Number(itemValue) < Number(value);\n case '>=':\n case 'greaterOrEqual':\n return Number(itemValue) >= Number(value);\n case '<=':\n case 'lessOrEqual':\n return Number(itemValue) <= Number(value);\n default:\n return String(itemValue).toLowerCase().includes(String(value).toLowerCase());\n }\n });\n });\n });\n\n // Computed - Sorting\n const sortedItems = computed(() => {\n if (!sortKey.value) return filteredItems.value;\n\n return [...filteredItems.value].sort((a, b) => {\n const aVal = a[sortKey.value];\n const bVal = b[sortKey.value];\n const order = sortOrder.value === 'asc' ? 1 : -1;\n\n if (aVal === bVal) return 0;\n if (aVal == null) return 1;\n if (bVal == null) return -1;\n\n // Handle different types\n if (typeof aVal === 'string' && typeof bVal === 'string') {\n return aVal.localeCompare(bVal) * order;\n }\n\n return aVal > bVal ? order : -order;\n });\n });\n\n // Computed - Pagination\n const paginatedItems = computed(() => {\n const start = (currentPage.value - 1) * pageSize.value;\n const end = start + pageSize.value;\n return sortedItems.value.slice(start, end);\n });\n\n const totalPages = computed(() =>\n Math.ceil(sortedItems.value.length / pageSize.value)\n );\n\n const totalItems = computed(() => sortedItems.value.length);\n\n // Computed - Selection\n const allSelected = computed(() => {\n if (items.value.length === 0) return false;\n return selectedItemIds.value.size === items.value.length;\n });\n\n const someSelected = computed(() => {\n return selectedItemIds.value.size > 0 && !allSelected.value;\n });\n\n // Methods - Pagination\n function setPage(page: number) {\n if (page >= 1 && page <= totalPages.value) {\n currentPage.value = page;\n }\n }\n\n function setPageSize(size: number) {\n pageSize.value = size;\n currentPage.value = 1; // Reset to first page\n }\n\n function handlePageChange(page: number) {\n setPage(page);\n }\n\n function handlePageSizeChange(size: number | string) {\n const numSize = typeof size === 'string' ? parseInt(size) : size;\n setPageSize(numSize);\n }\n\n // Methods - Sorting\n function setSorting(key: string, order: 'asc' | 'desc' = 'asc') {\n if (sortKey.value === key) {\n // Toggle order if same key\n sortOrder.value = sortOrder.value === 'asc' ? 'desc' : 'asc';\n } else {\n sortKey.value = key;\n sortOrder.value = order;\n }\n }\n\n function handleOrderBy(event: { value: string; orderDirection: 'asc' | 'desc' }) {\n sortKey.value = event.value;\n sortOrder.value = event.orderDirection;\n }\n\n // Methods - Selection\n function getItemId(item: T): string | number {\n return item[idKey];\n }\n\n function selectItem(item: T) {\n const id = getItemId(item);\n if (!selectedItemIds.value.has(id)) {\n selectedItemIds.value.add(id);\n (selectedItems.value as T[]).push(item);\n }\n }\n\n function deselectItem(item: T) {\n const id = getItemId(item);\n if (selectedItemIds.value.has(id)) {\n selectedItemIds.value.delete(id);\n const index = (selectedItems.value as T[]).findIndex(i => getItemId(i) === id);\n if (index !== -1) {\n (selectedItems.value as T[]).splice(index, 1);\n }\n }\n }\n\n function selectAll() {\n selectedItemIds.value.clear();\n (selectedItems.value as T[]).length = 0;\n \n items.value.forEach(item => {\n const id = getItemId(item);\n selectedItemIds.value.add(id);\n (selectedItems.value as T[]).push(item);\n });\n }\n\n function selectAllOnPage() {\n paginatedItems.value.forEach(item => {\n selectItem(item);\n });\n }\n\n function clearSelection() {\n selectedItemIds.value.clear();\n (selectedItems.value as T[]).length = 0;\n resetSelected.value = true;\n setTimeout(() => {\n resetSelected.value = false;\n }, 100);\n }\n\n function isSelected(item: T): boolean {\n const id = getItemId(item);\n return selectedItemIds.value.has(id);\n }\n\n // Methods - Filtering\n function applyFilters(filters: SmartFilter[] | Record<string, any>) {\n // Handle various filter formats from UI components\n if (Array.isArray(filters)) {\n activeFilters.value = filters;\n } else if (filters && typeof filters === 'object') {\n // Handle object format like { filters: [...] } or extract values\n if ('filters' in filters && Array.isArray(filters.filters)) {\n activeFilters.value = filters.filters;\n } else {\n // Convert object to SmartFilter array\n activeFilters.value = Object.entries(filters)\n .filter(([_, value]) => value !== undefined && value !== null && value !== '')\n .map(([key, value]) => ({\n category: key,\n operator: 'contains',\n value,\n }));\n }\n } else {\n activeFilters.value = [];\n }\n currentPage.value = 1; // Reset to first page when filters change\n }\n\n function clearFilters() {\n activeFilters.value = [];\n currentPage.value = 1;\n }\n\n function removeFilter(index: number) {\n if (index >= 0 && index < activeFilters.value.length) {\n activeFilters.value.splice(index, 1);\n currentPage.value = 1;\n }\n }\n\n function handleSmartFiltersApplied(filters: SmartFilter[] | Record<string, any>) {\n applyFilters(filters);\n }\n\n function handleSmartFiltersCleared() {\n clearFilters();\n }\n\n function handleSmartFilterDeleted(index: number) {\n removeFilter(index);\n }\n\n // Methods - Column visibility\n function toggleColumn(index: number) {\n const hiddenIndex = hiddenColumns.value.indexOf(index);\n if (hiddenIndex > -1) {\n hiddenColumns.value.splice(hiddenIndex, 1);\n } else {\n hiddenColumns.value.push(index);\n }\n }\n\n function showColumn(index: number) {\n const hiddenIndex = hiddenColumns.value.indexOf(index);\n if (hiddenIndex > -1) {\n hiddenColumns.value.splice(hiddenIndex, 1);\n }\n }\n\n function hideColumn(index: number) {\n if (!hiddenColumns.value.includes(index)) {\n hiddenColumns.value.push(index);\n }\n }\n\n function handleColumnsVisibilityChanged(event: { index: number; hidden: boolean }) {\n if (event.hidden) {\n hideColumn(event.index);\n } else {\n showColumn(event.index);\n }\n }\n\n // Methods - Modal actions\n function handleModalAction(event: { modal: string; action: string }) {\n if (event.modal === 'selectAllItemsModal' || event.modal.includes('selectAll')) {\n if (event.action === 'selectAll') {\n selectAll();\n } else if (event.action === 'close') {\n selectAllOnPage();\n }\n }\n }\n\n return {\n // Pagination\n currentPage,\n pageSize,\n totalPages,\n totalItems,\n paginatedItems,\n \n // Sorting\n sortKey,\n sortOrder,\n sortedItems,\n \n // Selection\n selectedItems,\n selectedItemIds,\n allSelected,\n someSelected,\n \n // Filtering\n activeFilters,\n filteredItems,\n \n // Column visibility\n hiddenColumns,\n \n // Reset state\n resetSelected,\n \n // Methods - Pagination\n setPage,\n setPageSize,\n handlePageChange,\n handlePageSizeChange,\n \n // Methods - Sorting\n setSorting,\n handleOrderBy,\n \n // Methods - Selection\n selectItem,\n deselectItem,\n selectAll,\n selectAllOnPage,\n clearSelection,\n isSelected,\n \n // Methods - Filtering\n applyFilters,\n clearFilters,\n removeFilter,\n handleSmartFiltersApplied,\n handleSmartFiltersCleared,\n handleSmartFilterDeleted,\n \n // Methods - Column visibility\n toggleColumn,\n showColumn,\n hideColumn,\n handleColumnsVisibilityChanged,\n \n // Methods - Modal actions\n handleModalAction,\n };\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,15 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@htlkg/components",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
|
-
".":
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"./
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
".": {
|
|
7
|
+
"import": "./dist/index.js",
|
|
8
|
+
"types": "./src/index.ts"
|
|
9
|
+
},
|
|
10
|
+
"./data": {
|
|
11
|
+
"import": "./dist/data/index.js",
|
|
12
|
+
"types": "./src/data/index.ts"
|
|
13
|
+
},
|
|
14
|
+
"./forms": {
|
|
15
|
+
"import": "./dist/forms/index.js",
|
|
16
|
+
"types": "./src/forms/index.ts"
|
|
17
|
+
},
|
|
18
|
+
"./navigation": {
|
|
19
|
+
"import": "./dist/navigation/index.js",
|
|
20
|
+
"types": "./src/navigation/index.ts"
|
|
21
|
+
},
|
|
22
|
+
"./overlays": {
|
|
23
|
+
"import": "./dist/overlays/index.js",
|
|
24
|
+
"types": "./src/overlays/index.ts"
|
|
25
|
+
},
|
|
26
|
+
"./domain": {
|
|
27
|
+
"import": "./dist/domain/index.js",
|
|
28
|
+
"types": "./src/domain/index.ts"
|
|
29
|
+
},
|
|
30
|
+
"./composables": {
|
|
31
|
+
"import": "./dist/composables/index.js",
|
|
32
|
+
"types": "./src/composables/index.ts"
|
|
33
|
+
},
|
|
34
|
+
"./stores": {
|
|
35
|
+
"import": "./dist/stores/index.js",
|
|
36
|
+
"types": "./src/stores/index.ts"
|
|
37
|
+
}
|
|
13
38
|
},
|
|
14
39
|
"files": [
|
|
15
40
|
"src",
|
|
@@ -20,22 +45,26 @@
|
|
|
20
45
|
"ajv": "^8.17.1",
|
|
21
46
|
"ajv-formats": "^3.0.1",
|
|
22
47
|
"vue": "^3.5.22",
|
|
23
|
-
"@htlkg/core": "0.0.
|
|
24
|
-
"@htlkg/data": "0.0.
|
|
48
|
+
"@htlkg/core": "0.0.3",
|
|
49
|
+
"@htlkg/data": "0.0.3"
|
|
25
50
|
},
|
|
26
51
|
"publishConfig": {
|
|
27
52
|
"access": "restricted"
|
|
28
53
|
},
|
|
29
54
|
"devDependencies": {
|
|
55
|
+
"@vitejs/plugin-vue": "^5.2.4",
|
|
30
56
|
"@vue/test-utils": "^2.4.6",
|
|
31
|
-
"tsup": "^8.0.0",
|
|
32
57
|
"typescript": "^5.9.2",
|
|
58
|
+
"vite": "^6.3.5",
|
|
33
59
|
"vitest": "^3.2.4"
|
|
34
60
|
},
|
|
35
61
|
"scripts": {
|
|
36
|
-
"build": "
|
|
37
|
-
"dev": "
|
|
62
|
+
"build": "vite build",
|
|
63
|
+
"dev": "vite build --watch",
|
|
38
64
|
"test": "vitest run",
|
|
39
|
-
"test:watch": "vitest"
|
|
65
|
+
"test:watch": "vitest",
|
|
66
|
+
"version:patch": "pnpm version patch --no-git-tag-version",
|
|
67
|
+
"version:minor": "pnpm version minor --no-git-tag-version",
|
|
68
|
+
"version:major": "pnpm version major --no-git-tag-version"
|
|
40
69
|
}
|
|
41
70
|
}
|