@htlkg/components 0.0.1 → 0.0.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.
@@ -1,20 +1,73 @@
1
1
  // src/composables/useTable.ts
2
- import { ref, computed } from "vue";
2
+ import { ref, computed, unref } from "vue";
3
3
  function useTable(options) {
4
+ const idKey = options.idKey ?? "id";
5
+ const items = computed(() => {
6
+ try {
7
+ const unwrapped = unref(options.items);
8
+ if (!unwrapped) return [];
9
+ if (!Array.isArray(unwrapped)) {
10
+ console.warn("useTable: items is not an array", unwrapped);
11
+ return [];
12
+ }
13
+ return unwrapped;
14
+ } catch (error) {
15
+ console.error("useTable: Error unwrapping items", error);
16
+ return [];
17
+ }
18
+ });
4
19
  const currentPage = ref(1);
5
20
  const pageSize = ref(options.pageSize ?? 10);
6
21
  const sortKey = ref(options.sortKey ?? "");
7
22
  const sortOrder = ref(options.sortOrder ?? "asc");
8
23
  const selectedItems = ref([]);
24
+ const selectedItemIds = ref(/* @__PURE__ */ new Set());
25
+ const resetSelected = ref(false);
26
+ const activeFilters = ref([]);
27
+ const hiddenColumns = ref([]);
28
+ const filteredItems = computed(() => {
29
+ if (activeFilters.value.length === 0) return items.value;
30
+ return items.value.filter((item) => {
31
+ return activeFilters.value.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
+ });
9
59
  const sortedItems = computed(() => {
10
- if (!sortKey.value) return options.items;
11
- return [...options.items].sort((a, b) => {
60
+ if (!sortKey.value) return filteredItems.value;
61
+ return [...filteredItems.value].sort((a, b) => {
12
62
  const aVal = a[sortKey.value];
13
63
  const bVal = b[sortKey.value];
14
64
  const order = sortOrder.value === "asc" ? 1 : -1;
15
65
  if (aVal === bVal) return 0;
16
66
  if (aVal == null) return 1;
17
67
  if (bVal == null) return -1;
68
+ if (typeof aVal === "string" && typeof bVal === "string") {
69
+ return aVal.localeCompare(bVal) * order;
70
+ }
18
71
  return aVal > bVal ? order : -order;
19
72
  });
20
73
  });
@@ -24,8 +77,16 @@ function useTable(options) {
24
77
  return sortedItems.value.slice(start, end);
25
78
  });
26
79
  const totalPages = computed(
27
- () => Math.ceil(options.items.length / pageSize.value)
80
+ () => Math.ceil(sortedItems.value.length / pageSize.value)
28
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
+ });
29
90
  function setPage(page) {
30
91
  if (page >= 1 && page <= totalPages.value) {
31
92
  currentPage.value = page;
@@ -35,6 +96,13 @@ function useTable(options) {
35
96
  pageSize.value = size;
36
97
  currentPage.value = 1;
37
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
+ }
38
106
  function setSorting(key, order = "asc") {
39
107
  if (sortKey.value === key) {
40
108
  sortOrder.value = sortOrder.value === "asc" ? "desc" : "asc";
@@ -43,47 +111,166 @@ function useTable(options) {
43
111
  sortOrder.value = order;
44
112
  }
45
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
+ }
46
121
  function selectItem(item) {
47
- if (!isSelected(item)) {
122
+ const id = getItemId(item);
123
+ if (!selectedItemIds.value.has(id)) {
124
+ selectedItemIds.value.add(id);
48
125
  selectedItems.value.push(item);
49
126
  }
50
127
  }
51
128
  function deselectItem(item) {
52
- const index = selectedItems.value.findIndex(
53
- (i) => JSON.stringify(i) === JSON.stringify(item)
54
- );
55
- if (index !== -1) {
56
- selectedItems.value.splice(index, 1);
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
+ }
57
136
  }
58
137
  }
59
138
  function selectAll() {
60
- selectedItems.value = [...options.items];
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
+ });
61
151
  }
62
152
  function clearSelection() {
63
- selectedItems.value = [];
153
+ selectedItemIds.value.clear();
154
+ selectedItems.value.length = 0;
155
+ resetSelected.value = true;
156
+ setTimeout(() => {
157
+ resetSelected.value = false;
158
+ }, 100);
64
159
  }
65
160
  function isSelected(item) {
66
- return selectedItems.value.some(
67
- (i) => JSON.stringify(i) === JSON.stringify(item)
68
- );
161
+ const id = getItemId(item);
162
+ return selectedItemIds.value.has(id);
163
+ }
164
+ function applyFilters(filters) {
165
+ activeFilters.value = filters;
166
+ currentPage.value = 1;
167
+ }
168
+ function clearFilters() {
169
+ activeFilters.value = [];
170
+ currentPage.value = 1;
171
+ }
172
+ function removeFilter(index) {
173
+ if (index >= 0 && index < activeFilters.value.length) {
174
+ activeFilters.value.splice(index, 1);
175
+ currentPage.value = 1;
176
+ }
177
+ }
178
+ function handleSmartFiltersApplied(filters) {
179
+ applyFilters(filters);
180
+ }
181
+ function handleSmartFiltersCleared() {
182
+ clearFilters();
183
+ }
184
+ function handleSmartFilterDeleted(index) {
185
+ removeFilter(index);
186
+ }
187
+ function toggleColumn(index) {
188
+ const hiddenIndex = hiddenColumns.value.indexOf(index);
189
+ if (hiddenIndex > -1) {
190
+ hiddenColumns.value.splice(hiddenIndex, 1);
191
+ } else {
192
+ hiddenColumns.value.push(index);
193
+ }
194
+ }
195
+ function showColumn(index) {
196
+ const hiddenIndex = hiddenColumns.value.indexOf(index);
197
+ if (hiddenIndex > -1) {
198
+ hiddenColumns.value.splice(hiddenIndex, 1);
199
+ }
200
+ }
201
+ function hideColumn(index) {
202
+ if (!hiddenColumns.value.includes(index)) {
203
+ hiddenColumns.value.push(index);
204
+ }
205
+ }
206
+ function handleColumnsVisibilityChanged(event) {
207
+ if (event.hidden) {
208
+ hideColumn(event.index);
209
+ } else {
210
+ showColumn(event.index);
211
+ }
212
+ }
213
+ function handleModalAction(event) {
214
+ if (event.modal === "selectAllItemsModal" || event.modal.includes("selectAll")) {
215
+ if (event.action === "selectAll") {
216
+ selectAll();
217
+ } else if (event.action === "close") {
218
+ selectAllOnPage();
219
+ }
220
+ }
69
221
  }
70
222
  return {
223
+ // Pagination
71
224
  currentPage,
72
225
  pageSize,
226
+ totalPages,
227
+ totalItems,
228
+ paginatedItems,
229
+ // Sorting
73
230
  sortKey,
74
231
  sortOrder,
75
- selectedItems,
76
- paginatedItems,
77
- totalPages,
78
232
  sortedItems,
233
+ // Selection
234
+ selectedItems,
235
+ selectedItemIds,
236
+ allSelected,
237
+ someSelected,
238
+ // Filtering
239
+ activeFilters,
240
+ filteredItems,
241
+ // Column visibility
242
+ hiddenColumns,
243
+ // Reset state
244
+ resetSelected,
245
+ // Methods - Pagination
79
246
  setPage,
80
247
  setPageSize,
248
+ handlePageChange,
249
+ handlePageSizeChange,
250
+ // Methods - Sorting
81
251
  setSorting,
252
+ handleOrderBy,
253
+ // Methods - Selection
82
254
  selectItem,
83
255
  deselectItem,
84
256
  selectAll,
257
+ selectAllOnPage,
85
258
  clearSelection,
86
- isSelected
259
+ isSelected,
260
+ // Methods - Filtering
261
+ applyFilters,
262
+ clearFilters,
263
+ removeFilter,
264
+ handleSmartFiltersApplied,
265
+ handleSmartFiltersCleared,
266
+ handleSmartFilterDeleted,
267
+ // Methods - Column visibility
268
+ toggleColumn,
269
+ showColumn,
270
+ hideColumn,
271
+ handleColumnsVisibilityChanged,
272
+ // Methods - Modal actions
273
+ handleModalAction
87
274
  };
88
275
  }
89
276
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/composables/useTable.ts","../../src/composables/useModal.ts","../../src/composables/useTabs.ts","../../src/composables/useForm.ts","../../src/composables/useFormValidation.ts","../../src/composables/useNotifications.ts"],"sourcesContent":["import { ref, computed, type Ref, type ComputedRef } from 'vue';\n\nexport interface UseTableOptions<T> {\n items: T[];\n pageSize?: number;\n sortKey?: string;\n sortOrder?: 'asc' | 'desc';\n}\n\nexport interface UseTableReturn<T> {\n currentPage: Ref<number>;\n pageSize: Ref<number>;\n sortKey: Ref<string>;\n sortOrder: Ref<'asc' | 'desc'>;\n selectedItems: Ref<T[]>;\n paginatedItems: ComputedRef<T[]>;\n totalPages: ComputedRef<number>;\n sortedItems: ComputedRef<T[]>;\n setPage: (page: number) => void;\n setPageSize: (size: number) => void;\n setSorting: (key: string, order?: 'asc' | 'desc') => void;\n selectItem: (item: T) => void;\n deselectItem: (item: T) => void;\n selectAll: () => void;\n clearSelection: () => void;\n isSelected: (item: T) => boolean;\n}\n\nexport function useTable<T extends Record<string, any>>(\n options: UseTableOptions<T>\n): UseTableReturn<T> {\n const currentPage = ref(1);\n const pageSize = ref(options.pageSize ?? 10);\n const sortKey = ref(options.sortKey ?? '');\n const sortOrder = ref<'asc' | 'desc'>(options.sortOrder ?? 'asc');\n const selectedItems = ref<T[]>([]);\n\n const sortedItems = computed(() => {\n if (!sortKey.value) return options.items;\n\n return [...options.items].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 return aVal > bVal ? order : -order;\n });\n });\n\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(options.items.length / pageSize.value)\n );\n\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 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 selectItem(item: T) {\n if (!isSelected(item)) {\n selectedItems.value.push(item);\n }\n }\n\n function deselectItem(item: T) {\n // Use deep comparison for objects\n const index = selectedItems.value.findIndex(i => \n JSON.stringify(i) === JSON.stringify(item)\n );\n if (index !== -1) {\n selectedItems.value.splice(index, 1);\n }\n }\n\n function selectAll() {\n selectedItems.value = [...options.items];\n }\n\n function clearSelection() {\n selectedItems.value = [];\n }\n\n function isSelected(item: T): boolean {\n // Use deep comparison for objects\n return selectedItems.value.some(i => \n JSON.stringify(i) === JSON.stringify(item)\n );\n }\n\n return {\n currentPage,\n pageSize,\n sortKey,\n sortOrder,\n selectedItems,\n paginatedItems,\n totalPages,\n sortedItems,\n setPage,\n setPageSize,\n setSorting,\n selectItem,\n deselectItem,\n selectAll,\n clearSelection,\n isSelected\n };\n}\n","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"],"mappings":"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","names":["ref","ref","computed","nextTab","ref","computed","isValid","min","max","ref"]}
1
+ {"version":3,"sources":["../../src/composables/useTable.ts","../../src/composables/useModal.ts","../../src/composables/useTabs.ts","../../src/composables/useForm.ts","../../src/composables/useFormValidation.ts","../../src/composables/useNotifications.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 if (activeFilters.value.length === 0) return items.value;\n\n return items.value.filter(item => {\n // All filters must pass (AND logic by default)\n return activeFilters.value.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[]) {\n activeFilters.value = filters;\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[]) {\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","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"],"mappings":"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","names":["ref","ref","computed","nextTab","ref","computed","isValid","min","max","ref"]}
package/package.json CHANGED
@@ -1,41 +1,41 @@
1
1
  {
2
- "name": "@htlkg/components",
3
- "version": "0.0.1",
4
- "type": "module",
5
- "exports": {
6
- ".": "./src/index.ts",
7
- "./data": "./src/data/index.ts",
8
- "./forms": "./src/forms/index.ts",
9
- "./navigation": "./src/navigation/index.ts",
10
- "./overlays": "./src/overlays/index.ts",
11
- "./domain": "./src/domain/index.ts",
12
- "./composables": "./dist/composables/index.js"
13
- },
14
- "files": [
15
- "src",
16
- "dist"
17
- ],
18
- "scripts": {
19
- "build": "tsup",
20
- "dev": "tsup --watch",
21
- "test": "vitest run",
22
- "test:watch": "vitest"
23
- },
24
- "dependencies": {
25
- "@hotelinking/ui": "^15.49.1",
26
- "@htlkg/core": "^0.0.1",
27
- "@htlkg/data": "^0.0.1",
28
- "ajv": "^8.17.1",
29
- "ajv-formats": "^3.0.1",
30
- "vue": "^3.5.22"
31
- },
32
- "publishConfig": {
33
- "access": "restricted"
34
- },
35
- "devDependencies": {
36
- "@vue/test-utils": "^2.4.6",
37
- "tsup": "^8.0.0",
38
- "typescript": "^5.9.2",
39
- "vitest": "^3.2.4"
40
- }
41
- }
2
+ "name": "@htlkg/components",
3
+ "version": "0.0.2",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": "./src/index.ts",
7
+ "./data": "./src/data/index.ts",
8
+ "./forms": "./src/forms/index.ts",
9
+ "./navigation": "./src/navigation/index.ts",
10
+ "./overlays": "./src/overlays/index.ts",
11
+ "./domain": "./src/domain/index.ts",
12
+ "./composables": "./dist/composables/index.js"
13
+ },
14
+ "files": [
15
+ "src",
16
+ "dist"
17
+ ],
18
+ "dependencies": {
19
+ "@hotelinking/ui": "^16.49.16",
20
+ "ajv": "^8.17.1",
21
+ "ajv-formats": "^3.0.1",
22
+ "vue": "^3.5.22",
23
+ "@htlkg/core": "0.0.2",
24
+ "@htlkg/data": "0.0.2"
25
+ },
26
+ "publishConfig": {
27
+ "access": "restricted"
28
+ },
29
+ "devDependencies": {
30
+ "@vue/test-utils": "^2.4.6",
31
+ "tsup": "^8.0.0",
32
+ "typescript": "^5.9.2",
33
+ "vitest": "^3.2.4"
34
+ },
35
+ "scripts": {
36
+ "build": "tsup",
37
+ "dev": "tsup --watch",
38
+ "test": "vitest run",
39
+ "test:watch": "vitest"
40
+ }
41
+ }
@@ -0,0 +1,34 @@
1
+ // Quick test to verify useTable works with computed refs
2
+ import { computed } from 'vue';
3
+ import { useTable } from './useTable';
4
+
5
+ // Test 1: Plain array
6
+ const test1 = useTable({
7
+ items: [{ id: 1, name: 'Test' }],
8
+ pageSize: 10,
9
+ });
10
+
11
+ console.log('Test 1 (plain array):', test1.paginatedItems.value);
12
+
13
+ // Test 2: Computed ref
14
+ const data = computed(() => [
15
+ { id: 1, name: 'Item 1' },
16
+ { id: 2, name: 'Item 2' },
17
+ ]);
18
+
19
+ const test2 = useTable({
20
+ items: data,
21
+ pageSize: 10,
22
+ });
23
+
24
+ console.log('Test 2 (computed ref):', test2.paginatedItems.value);
25
+
26
+ // Test 3: Empty array
27
+ const test3 = useTable({
28
+ items: [],
29
+ pageSize: 10,
30
+ });
31
+
32
+ console.log('Test 3 (empty array):', test3.paginatedItems.value);
33
+
34
+ export { test1, test2, test3 };
@@ -1,4 +1,4 @@
1
- export { useTable, type UseTableOptions, type UseTableReturn } from './useTable';
1
+ export { useTable, type UseTableOptions, type UseTableReturn, type SmartFilter } from './useTable';
2
2
  export { useModal, type UseModalOptions, type UseModalReturn } from './useModal';
3
3
  export { useTabs, type UseTabsOptions, type UseTabsReturn, type Tab } from './useTabs';
4
4
  export { useForm, type UseFormOptions, type UseFormReturn, type ValidationRule, type FieldConfig } from './useForm';