@htlkg/components 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/composables/index.js +388 -0
  2. package/dist/composables/index.js.map +1 -0
  3. package/package.json +41 -0
  4. package/src/composables/index.ts +6 -0
  5. package/src/composables/useForm.test.ts +229 -0
  6. package/src/composables/useForm.ts +130 -0
  7. package/src/composables/useFormValidation.test.ts +189 -0
  8. package/src/composables/useFormValidation.ts +83 -0
  9. package/src/composables/useModal.property.test.ts +164 -0
  10. package/src/composables/useModal.ts +43 -0
  11. package/src/composables/useNotifications.test.ts +166 -0
  12. package/src/composables/useNotifications.ts +81 -0
  13. package/src/composables/useTable.property.test.ts +198 -0
  14. package/src/composables/useTable.ts +134 -0
  15. package/src/composables/useTabs.property.test.ts +247 -0
  16. package/src/composables/useTabs.ts +101 -0
  17. package/src/data/Chart.demo.vue +340 -0
  18. package/src/data/Chart.md +525 -0
  19. package/src/data/Chart.vue +133 -0
  20. package/src/data/DataList.md +80 -0
  21. package/src/data/DataList.test.ts +69 -0
  22. package/src/data/DataList.vue +46 -0
  23. package/src/data/SearchableSelect.md +107 -0
  24. package/src/data/SearchableSelect.vue +124 -0
  25. package/src/data/Table.demo.vue +296 -0
  26. package/src/data/Table.md +588 -0
  27. package/src/data/Table.property.test.ts +548 -0
  28. package/src/data/Table.test.ts +562 -0
  29. package/src/data/Table.unit.test.ts +544 -0
  30. package/src/data/Table.vue +321 -0
  31. package/src/data/index.ts +5 -0
  32. package/src/domain/BrandCard.md +81 -0
  33. package/src/domain/BrandCard.vue +63 -0
  34. package/src/domain/BrandSelector.md +84 -0
  35. package/src/domain/BrandSelector.vue +65 -0
  36. package/src/domain/ProductBadge.md +60 -0
  37. package/src/domain/ProductBadge.vue +47 -0
  38. package/src/domain/UserAvatar.md +84 -0
  39. package/src/domain/UserAvatar.vue +60 -0
  40. package/src/domain/domain-components.property.test.ts +449 -0
  41. package/src/domain/index.ts +4 -0
  42. package/src/forms/DateRange.demo.vue +273 -0
  43. package/src/forms/DateRange.md +337 -0
  44. package/src/forms/DateRange.vue +110 -0
  45. package/src/forms/JsonSchemaForm.demo.vue +549 -0
  46. package/src/forms/JsonSchemaForm.md +112 -0
  47. package/src/forms/JsonSchemaForm.property.test.ts +817 -0
  48. package/src/forms/JsonSchemaForm.test.ts +601 -0
  49. package/src/forms/JsonSchemaForm.unit.test.ts +801 -0
  50. package/src/forms/JsonSchemaForm.vue +615 -0
  51. package/src/forms/index.ts +3 -0
  52. package/src/index.ts +17 -0
  53. package/src/navigation/Breadcrumbs.demo.vue +142 -0
  54. package/src/navigation/Breadcrumbs.md +102 -0
  55. package/src/navigation/Breadcrumbs.test.ts +69 -0
  56. package/src/navigation/Breadcrumbs.vue +58 -0
  57. package/src/navigation/Stepper.demo.vue +337 -0
  58. package/src/navigation/Stepper.md +174 -0
  59. package/src/navigation/Stepper.vue +146 -0
  60. package/src/navigation/Tabs.demo.vue +293 -0
  61. package/src/navigation/Tabs.md +163 -0
  62. package/src/navigation/Tabs.test.ts +176 -0
  63. package/src/navigation/Tabs.vue +104 -0
  64. package/src/navigation/index.ts +5 -0
  65. package/src/overlays/Alert.demo.vue +377 -0
  66. package/src/overlays/Alert.md +248 -0
  67. package/src/overlays/Alert.test.ts +166 -0
  68. package/src/overlays/Alert.vue +70 -0
  69. package/src/overlays/Drawer.md +140 -0
  70. package/src/overlays/Drawer.test.ts +92 -0
  71. package/src/overlays/Drawer.vue +76 -0
  72. package/src/overlays/Modal.demo.vue +149 -0
  73. package/src/overlays/Modal.md +385 -0
  74. package/src/overlays/Modal.test.ts +128 -0
  75. package/src/overlays/Modal.vue +86 -0
  76. package/src/overlays/Notification.md +150 -0
  77. package/src/overlays/Notification.test.ts +96 -0
  78. package/src/overlays/Notification.vue +58 -0
  79. package/src/overlays/index.ts +4 -0
@@ -0,0 +1,388 @@
1
+ // src/composables/useTable.ts
2
+ import { ref, computed } from "vue";
3
+ function useTable(options) {
4
+ const currentPage = ref(1);
5
+ const pageSize = ref(options.pageSize ?? 10);
6
+ const sortKey = ref(options.sortKey ?? "");
7
+ const sortOrder = ref(options.sortOrder ?? "asc");
8
+ const selectedItems = ref([]);
9
+ const sortedItems = computed(() => {
10
+ if (!sortKey.value) return options.items;
11
+ return [...options.items].sort((a, b) => {
12
+ const aVal = a[sortKey.value];
13
+ const bVal = b[sortKey.value];
14
+ const order = sortOrder.value === "asc" ? 1 : -1;
15
+ if (aVal === bVal) return 0;
16
+ if (aVal == null) return 1;
17
+ if (bVal == null) return -1;
18
+ return aVal > bVal ? order : -order;
19
+ });
20
+ });
21
+ const paginatedItems = computed(() => {
22
+ const start = (currentPage.value - 1) * pageSize.value;
23
+ const end = start + pageSize.value;
24
+ return sortedItems.value.slice(start, end);
25
+ });
26
+ const totalPages = computed(
27
+ () => Math.ceil(options.items.length / pageSize.value)
28
+ );
29
+ function setPage(page) {
30
+ if (page >= 1 && page <= totalPages.value) {
31
+ currentPage.value = page;
32
+ }
33
+ }
34
+ function setPageSize(size) {
35
+ pageSize.value = size;
36
+ currentPage.value = 1;
37
+ }
38
+ function setSorting(key, order = "asc") {
39
+ if (sortKey.value === key) {
40
+ sortOrder.value = sortOrder.value === "asc" ? "desc" : "asc";
41
+ } else {
42
+ sortKey.value = key;
43
+ sortOrder.value = order;
44
+ }
45
+ }
46
+ function selectItem(item) {
47
+ if (!isSelected(item)) {
48
+ selectedItems.value.push(item);
49
+ }
50
+ }
51
+ 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);
57
+ }
58
+ }
59
+ function selectAll() {
60
+ selectedItems.value = [...options.items];
61
+ }
62
+ function clearSelection() {
63
+ selectedItems.value = [];
64
+ }
65
+ function isSelected(item) {
66
+ return selectedItems.value.some(
67
+ (i) => JSON.stringify(i) === JSON.stringify(item)
68
+ );
69
+ }
70
+ return {
71
+ currentPage,
72
+ pageSize,
73
+ sortKey,
74
+ sortOrder,
75
+ selectedItems,
76
+ paginatedItems,
77
+ totalPages,
78
+ sortedItems,
79
+ setPage,
80
+ setPageSize,
81
+ setSorting,
82
+ selectItem,
83
+ deselectItem,
84
+ selectAll,
85
+ clearSelection,
86
+ isSelected
87
+ };
88
+ }
89
+
90
+ // src/composables/useModal.ts
91
+ import { ref as ref2 } from "vue";
92
+ function useModal(options = {}) {
93
+ const isOpen = ref2(options.initialOpen ?? false);
94
+ function open() {
95
+ isOpen.value = true;
96
+ options.onOpen?.();
97
+ }
98
+ function close() {
99
+ isOpen.value = false;
100
+ options.onClose?.();
101
+ }
102
+ function toggle() {
103
+ if (isOpen.value) {
104
+ close();
105
+ } else {
106
+ open();
107
+ }
108
+ }
109
+ return {
110
+ isOpen,
111
+ open,
112
+ close,
113
+ toggle
114
+ };
115
+ }
116
+
117
+ // src/composables/useTabs.ts
118
+ import { ref as ref3, computed as computed2 } from "vue";
119
+ function useTabs(options) {
120
+ const tabs = ref3(options.tabs);
121
+ const activeTab = ref3(
122
+ options.initialTab || (tabs.value.length > 0 ? tabs.value[0].id : "")
123
+ );
124
+ const currentTabIndex = computed2(
125
+ () => tabs.value.findIndex((tab) => tab.id === activeTab.value)
126
+ );
127
+ const isFirstTab = computed2(() => currentTabIndex.value === 0);
128
+ const isLastTab = computed2(
129
+ () => currentTabIndex.value === tabs.value.length - 1
130
+ );
131
+ function setActiveTab(tabId) {
132
+ const tab = tabs.value.find((t) => t.id === tabId);
133
+ if (tab && !tab.disabled) {
134
+ activeTab.value = tabId;
135
+ options.onChange?.(tabId);
136
+ }
137
+ }
138
+ function nextTab() {
139
+ if (!isLastTab.value) {
140
+ const nextIndex = currentTabIndex.value + 1;
141
+ const nextTab2 = tabs.value[nextIndex];
142
+ if (nextTab2 && !nextTab2.disabled) {
143
+ setActiveTab(nextTab2.id);
144
+ } else if (nextIndex < tabs.value.length - 1) {
145
+ activeTab.value = nextTab2.id;
146
+ nextTab2();
147
+ }
148
+ }
149
+ }
150
+ function previousTab() {
151
+ if (!isFirstTab.value) {
152
+ const prevIndex = currentTabIndex.value - 1;
153
+ const prevTab = tabs.value[prevIndex];
154
+ if (prevTab && !prevTab.disabled) {
155
+ setActiveTab(prevTab.id);
156
+ } else if (prevIndex > 0) {
157
+ activeTab.value = prevTab.id;
158
+ previousTab();
159
+ }
160
+ }
161
+ }
162
+ function isTabActive(tabId) {
163
+ return activeTab.value === tabId;
164
+ }
165
+ function isTabDisabled(tabId) {
166
+ const tab = tabs.value.find((t) => t.id === tabId);
167
+ return tab?.disabled ?? false;
168
+ }
169
+ return {
170
+ activeTab,
171
+ tabs,
172
+ currentTabIndex,
173
+ isFirstTab,
174
+ isLastTab,
175
+ setActiveTab,
176
+ nextTab,
177
+ previousTab,
178
+ isTabActive,
179
+ isTabDisabled
180
+ };
181
+ }
182
+
183
+ // src/composables/useForm.ts
184
+ import { ref as ref4, computed as computed3 } from "vue";
185
+ function useForm(options) {
186
+ const values = ref4({ ...options.initialValues });
187
+ const errors = ref4({});
188
+ const touched = ref4({});
189
+ const isSubmitting = ref4(false);
190
+ const isValid = computed3(() => Object.keys(errors.value).length === 0);
191
+ function setFieldValue(field, value) {
192
+ values.value[field] = value;
193
+ }
194
+ function setFieldError(field, error) {
195
+ errors.value[field] = error;
196
+ }
197
+ function setFieldTouched(field, isTouched) {
198
+ touched.value[field] = isTouched;
199
+ }
200
+ async function validateField(field) {
201
+ const rules = options.validationRules?.[field];
202
+ if (!rules || rules.length === 0) return true;
203
+ const value = values.value[field];
204
+ for (const rule of rules) {
205
+ const isValid2 = await rule.validate(value);
206
+ if (!isValid2) {
207
+ setFieldError(field, rule.message);
208
+ return false;
209
+ }
210
+ }
211
+ delete errors.value[field];
212
+ return true;
213
+ }
214
+ async function validateForm() {
215
+ const fields = Object.keys(values.value);
216
+ const validationResults = await Promise.all(
217
+ fields.map((field) => validateField(field))
218
+ );
219
+ return validationResults.every((result) => result);
220
+ }
221
+ async function handleSubmit(event) {
222
+ if (event) {
223
+ event.preventDefault();
224
+ }
225
+ if (isSubmitting.value) return;
226
+ for (const field of Object.keys(values.value)) {
227
+ setFieldTouched(field, true);
228
+ }
229
+ const isFormValid = await validateForm();
230
+ if (!isFormValid) return;
231
+ isSubmitting.value = true;
232
+ try {
233
+ await options.onSubmit?.(values.value);
234
+ } finally {
235
+ isSubmitting.value = false;
236
+ }
237
+ }
238
+ function resetForm() {
239
+ values.value = { ...options.initialValues };
240
+ errors.value = {};
241
+ touched.value = {};
242
+ isSubmitting.value = false;
243
+ }
244
+ return {
245
+ values,
246
+ errors,
247
+ touched,
248
+ isSubmitting,
249
+ isValid,
250
+ setFieldValue,
251
+ setFieldError,
252
+ setFieldTouched,
253
+ validateField,
254
+ validateForm,
255
+ handleSubmit,
256
+ resetForm
257
+ };
258
+ }
259
+
260
+ // src/composables/useFormValidation.ts
261
+ var required = (message = "This field is required") => ({
262
+ validate: (value) => {
263
+ if (value === null || value === void 0) return false;
264
+ if (typeof value === "string") return value.trim().length > 0;
265
+ if (Array.isArray(value)) return value.length > 0;
266
+ return true;
267
+ },
268
+ message
269
+ });
270
+ var minLength = (min2, message) => ({
271
+ validate: (value) => {
272
+ if (!value) return true;
273
+ return value.length >= min2;
274
+ },
275
+ message: message || `Must be at least ${min2} characters`
276
+ });
277
+ var maxLength = (max2, message) => ({
278
+ validate: (value) => {
279
+ if (!value) return true;
280
+ return value.length <= max2;
281
+ },
282
+ message: message || `Must be at most ${max2} characters`
283
+ });
284
+ var email = (message = "Invalid email address") => ({
285
+ validate: (value) => {
286
+ if (!value) return true;
287
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
288
+ return emailRegex.test(value);
289
+ },
290
+ message
291
+ });
292
+ var pattern = (regex, message = "Invalid format") => ({
293
+ validate: (value) => {
294
+ if (!value) return true;
295
+ return regex.test(value);
296
+ },
297
+ message
298
+ });
299
+ var min = (minValue, message) => ({
300
+ validate: (value) => {
301
+ if (value === null || value === void 0) return true;
302
+ return value >= minValue;
303
+ },
304
+ message: message || `Must be at least ${minValue}`
305
+ });
306
+ var max = (maxValue, message) => ({
307
+ validate: (value) => {
308
+ if (value === null || value === void 0) return true;
309
+ return value <= maxValue;
310
+ },
311
+ message: message || `Must be at most ${maxValue}`
312
+ });
313
+ var custom = (validator, message) => ({
314
+ validate: validator,
315
+ message
316
+ });
317
+ function useFormValidation() {
318
+ return {
319
+ required,
320
+ minLength,
321
+ maxLength,
322
+ email,
323
+ pattern,
324
+ min,
325
+ max,
326
+ custom
327
+ };
328
+ }
329
+
330
+ // src/composables/useNotifications.ts
331
+ import { ref as ref5 } from "vue";
332
+ var notifications = ref5([]);
333
+ function useNotifications() {
334
+ function addNotification(notification) {
335
+ const id = `notification-${Date.now()}-${Math.random()}`;
336
+ const newNotification = {
337
+ ...notification,
338
+ id
339
+ };
340
+ notifications.value.push(newNotification);
341
+ if (notification.duration) {
342
+ setTimeout(() => {
343
+ removeNotification(id);
344
+ }, notification.duration);
345
+ }
346
+ return id;
347
+ }
348
+ function removeNotification(id) {
349
+ const index = notifications.value.findIndex((n) => n.id === id);
350
+ if (index !== -1) {
351
+ notifications.value.splice(index, 1);
352
+ }
353
+ }
354
+ function clearAll() {
355
+ notifications.value = [];
356
+ }
357
+ function info(message, duration = 3e3) {
358
+ return addNotification({ message, type: "info", duration });
359
+ }
360
+ function success(message, duration = 3e3) {
361
+ return addNotification({ message, type: "success", duration });
362
+ }
363
+ function warning(message, duration = 3e3) {
364
+ return addNotification({ message, type: "warning", duration });
365
+ }
366
+ function error(message, duration = 5e3) {
367
+ return addNotification({ message, type: "error", duration });
368
+ }
369
+ return {
370
+ notifications,
371
+ addNotification,
372
+ removeNotification,
373
+ clearAll,
374
+ info,
375
+ success,
376
+ warning,
377
+ error
378
+ };
379
+ }
380
+ export {
381
+ useForm,
382
+ useFormValidation,
383
+ useModal,
384
+ useNotifications,
385
+ useTable,
386
+ useTabs
387
+ };
388
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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"]}
package/package.json ADDED
@@ -0,0 +1,41 @@
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
+ }
@@ -0,0 +1,6 @@
1
+ export { useTable, type UseTableOptions, type UseTableReturn } from './useTable';
2
+ export { useModal, type UseModalOptions, type UseModalReturn } from './useModal';
3
+ export { useTabs, type UseTabsOptions, type UseTabsReturn, type Tab } from './useTabs';
4
+ export { useForm, type UseFormOptions, type UseFormReturn, type ValidationRule, type FieldConfig } from './useForm';
5
+ export { useFormValidation } from './useFormValidation';
6
+ export { useNotifications, type Notification, type UseNotificationsReturn } from './useNotifications';