@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.
Files changed (60) hide show
  1. package/README.md +52 -0
  2. package/dist/AdminWrapper.vue_vue_type_script_setup_true_lang-B32IylcT.js +367 -0
  3. package/dist/AdminWrapper.vue_vue_type_script_setup_true_lang-B32IylcT.js.map +1 -0
  4. package/dist/Alert.vue_vue_type_script_setup_true_lang-DxPCS-Hx.js +263 -0
  5. package/dist/Alert.vue_vue_type_script_setup_true_lang-DxPCS-Hx.js.map +1 -0
  6. package/dist/DateRange.vue_vue_type_script_setup_true_lang-BLVg1Hah.js +580 -0
  7. package/dist/DateRange.vue_vue_type_script_setup_true_lang-BLVg1Hah.js.map +1 -0
  8. package/dist/ProductBadge.vue_vue_type_script_setup_true_lang-Cmr2f4Cy.js +187 -0
  9. package/dist/ProductBadge.vue_vue_type_script_setup_true_lang-Cmr2f4Cy.js.map +1 -0
  10. package/dist/_plugin-vue_export-helper-1tPrXgE0.js +11 -0
  11. package/dist/_plugin-vue_export-helper-1tPrXgE0.js.map +1 -0
  12. package/dist/components.css +15 -0
  13. package/dist/composables/index.js +32 -573
  14. package/dist/composables/index.js.map +1 -1
  15. package/dist/data/index.js +18 -0
  16. package/dist/data/index.js.map +1 -0
  17. package/dist/domain/index.js +8 -0
  18. package/dist/domain/index.js.map +1 -0
  19. package/dist/filterHelpers-DgRyoYSa.js +1386 -0
  20. package/dist/filterHelpers-DgRyoYSa.js.map +1 -0
  21. package/dist/forms/index.js +6 -0
  22. package/dist/forms/index.js.map +1 -0
  23. package/dist/index-DGO_pNgG.js +79 -0
  24. package/dist/index-DGO_pNgG.js.map +1 -0
  25. package/dist/index-QK97OdqQ.js +25 -0
  26. package/dist/index-QK97OdqQ.js.map +1 -0
  27. package/dist/index.js +67 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/navigation/index.js +8 -0
  30. package/dist/navigation/index.js.map +1 -0
  31. package/dist/overlays/index.js +8 -0
  32. package/dist/overlays/index.js.map +1 -0
  33. package/dist/stores/index.js +14 -0
  34. package/dist/stores/index.js.map +1 -0
  35. package/dist/useAdminPage-GhgXp0x8.js +1070 -0
  36. package/dist/useAdminPage-GhgXp0x8.js.map +1 -0
  37. package/dist/useTable-DutR1gkg.js +293 -0
  38. package/dist/useTable-DutR1gkg.js.map +1 -0
  39. package/package.json +43 -14
  40. package/src/composables/composables.md +109 -0
  41. package/src/composables/index.ts +69 -0
  42. package/src/composables/useAdminPage.ts +462 -0
  43. package/src/composables/useConfirmation.ts +358 -0
  44. package/src/composables/usePageContext.ts +171 -0
  45. package/src/composables/useStats.ts +361 -0
  46. package/src/composables/useTable.ts +26 -5
  47. package/src/composables/useWizard.ts +448 -0
  48. package/src/data/DataTable.vue +553 -0
  49. package/src/data/Table/Table.vue +295 -0
  50. package/src/data/columnHelpers.ts +503 -0
  51. package/src/data/data.md +106 -0
  52. package/src/data/filterHelpers.ts +358 -0
  53. package/src/data/index.ts +31 -0
  54. package/src/domain/domain.md +102 -0
  55. package/src/forms/JsonSchemaForm.vue +4 -1
  56. package/src/forms/forms.md +89 -0
  57. package/src/index.ts +4 -3
  58. package/src/navigation/navigation.md +80 -0
  59. package/src/overlays/overlays.md +86 -0
  60. package/src/stores/stores.md +82 -0
@@ -0,0 +1,448 @@
1
+ /**
2
+ * Wizard Composable
3
+ *
4
+ * Manages multi-step form/wizard state with validation support.
5
+ * Integrates with Stepper component and JsonSchemaForm.
6
+ */
7
+
8
+ import { ref, computed, type Ref, type ComputedRef, type Component } from 'vue';
9
+
10
+ /**
11
+ * JSON Schema type for form validation
12
+ */
13
+ export interface JsonSchema {
14
+ type: string;
15
+ properties?: Record<string, any>;
16
+ required?: string[];
17
+ title?: string;
18
+ description?: string;
19
+ }
20
+
21
+ /**
22
+ * Step definition for the wizard
23
+ */
24
+ export interface WizardStep<T = any> {
25
+ /** Unique step identifier */
26
+ id: string;
27
+ /** Display label for the step */
28
+ label: string;
29
+ /** Optional description */
30
+ description?: string;
31
+ /** JSON Schema for JsonSchemaForm (optional) */
32
+ schema?: JsonSchema;
33
+ /** Custom validation function (optional) */
34
+ validate?: (data: T) => boolean | Promise<boolean>;
35
+ /** Icon component for the step (optional) */
36
+ icon?: Component;
37
+ /** Whether step can be skipped */
38
+ optional?: boolean;
39
+ }
40
+
41
+ /**
42
+ * Step status for Stepper component
43
+ */
44
+ export type StepStatus = 'complete' | 'current' | 'upcoming' | 'error';
45
+
46
+ /**
47
+ * Stepper-compatible step format
48
+ */
49
+ export interface StepperStep {
50
+ id: string;
51
+ label: string;
52
+ status: StepStatus;
53
+ valid?: boolean;
54
+ }
55
+
56
+ /**
57
+ * Options for useWizard
58
+ */
59
+ export interface UseWizardOptions<T extends Record<string, any>> {
60
+ /** Step definitions */
61
+ steps: WizardStep<T>[];
62
+ /** Initial form data */
63
+ initialData?: Partial<T>;
64
+ /** Callback when wizard completes */
65
+ onComplete?: (data: T) => void | Promise<void>;
66
+ /** Callback when step changes */
67
+ onStepChange?: (fromIndex: number, toIndex: number, data: T) => void;
68
+ /** Whether to validate before advancing */
69
+ validateOnNext?: boolean;
70
+ /** Whether to allow going back without validation */
71
+ allowBackWithoutValidation?: boolean;
72
+ }
73
+
74
+ /**
75
+ * Return type for useWizard
76
+ */
77
+ export interface UseWizardReturn<T extends Record<string, any>> {
78
+ // State
79
+ currentStepIndex: Ref<number>;
80
+ currentStep: ComputedRef<WizardStep<T>>;
81
+ data: Ref<Partial<T>>;
82
+ isFirstStep: ComputedRef<boolean>;
83
+ isLastStep: ComputedRef<boolean>;
84
+ isCompleting: Ref<boolean>;
85
+ stepErrors: Ref<Record<string, string>>;
86
+
87
+ // For Stepper component
88
+ stepperSteps: ComputedRef<StepperStep[]>;
89
+
90
+ // Validation state
91
+ stepValidation: Ref<Record<string, boolean>>;
92
+ currentStepValid: ComputedRef<boolean>;
93
+ allStepsValid: ComputedRef<boolean>;
94
+
95
+ // Navigation
96
+ goToNext: () => Promise<boolean>;
97
+ goToPrevious: () => boolean;
98
+ goToStep: (index: number) => Promise<boolean>;
99
+ canGoToStep: (index: number) => boolean;
100
+
101
+ // Data management
102
+ updateData: (newData: Partial<T>) => void;
103
+ updateStepData: (stepId: string, stepData: Partial<T>) => void;
104
+ setStepValid: (stepId: string, valid: boolean) => void;
105
+ setStepError: (stepId: string, error: string | null) => void;
106
+ resetStep: (stepId: string) => void;
107
+ reset: () => void;
108
+
109
+ // Completion
110
+ complete: () => Promise<boolean>;
111
+
112
+ // Utilities
113
+ getStepIndex: (stepId: string) => number;
114
+ getStep: (stepId: string) => WizardStep<T> | undefined;
115
+ progress: ComputedRef<number>;
116
+ }
117
+
118
+ /**
119
+ * Creates a wizard composable for managing multi-step forms
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * const wizard = useWizard({
124
+ * steps: [
125
+ * { id: 'details', label: 'Details', schema: detailsSchema },
126
+ * { id: 'audience', label: 'Audience', schema: audienceSchema },
127
+ * { id: 'review', label: 'Review' },
128
+ * ],
129
+ * initialData: { name: '', audience: [] },
130
+ * onComplete: async (data) => {
131
+ * await createCampaign(data);
132
+ * },
133
+ * });
134
+ *
135
+ * // In template
136
+ * <Stepper :steps="wizard.stepperSteps" v-model:currentStep="wizard.currentStepIndex" />
137
+ * <JsonSchemaForm
138
+ * v-if="wizard.currentStep.schema"
139
+ * :schema="wizard.currentStep.schema"
140
+ * v-model="wizard.data"
141
+ * />
142
+ * <button @click="wizard.goToPrevious" :disabled="wizard.isFirstStep">Back</button>
143
+ * <button @click="wizard.goToNext" v-if="!wizard.isLastStep">Next</button>
144
+ * <button @click="wizard.complete" v-else :disabled="wizard.isCompleting">Complete</button>
145
+ * ```
146
+ */
147
+ export function useWizard<T extends Record<string, any>>(
148
+ options: UseWizardOptions<T>
149
+ ): UseWizardReturn<T> {
150
+ const {
151
+ steps,
152
+ initialData = {} as Partial<T>,
153
+ onComplete,
154
+ onStepChange,
155
+ validateOnNext = true,
156
+ allowBackWithoutValidation = true,
157
+ } = options;
158
+
159
+ // Core state
160
+ const currentStepIndex = ref(0);
161
+ const data = ref<Partial<T>>({ ...initialData }) as Ref<Partial<T>>;
162
+ const isCompleting = ref(false);
163
+ const stepValidation = ref<Record<string, boolean>>({});
164
+ const stepErrors = ref<Record<string, string>>({});
165
+
166
+ // Computed: Current step
167
+ const currentStep = computed(() => steps[currentStepIndex.value]);
168
+
169
+ // Computed: Navigation flags
170
+ const isFirstStep = computed(() => currentStepIndex.value === 0);
171
+ const isLastStep = computed(() => currentStepIndex.value === steps.length - 1);
172
+
173
+ // Computed: Progress percentage
174
+ const progress = computed(() =>
175
+ Math.round(((currentStepIndex.value + 1) / steps.length) * 100)
176
+ );
177
+
178
+ // Computed: Current step validation status
179
+ const currentStepValid = computed(() => {
180
+ const step = currentStep.value;
181
+ if (!step) return false;
182
+ if (step.optional) return true;
183
+ return stepValidation.value[step.id] !== false;
184
+ });
185
+
186
+ // Computed: All required steps valid
187
+ const allStepsValid = computed(() => {
188
+ return steps.every(step => {
189
+ if (step.optional) return true;
190
+ return stepValidation.value[step.id] === true;
191
+ });
192
+ });
193
+
194
+ // Computed: Steps formatted for Stepper component
195
+ const stepperSteps = computed<StepperStep[]>(() =>
196
+ steps.map((step, index) => {
197
+ let status: StepStatus;
198
+
199
+ if (index < currentStepIndex.value) {
200
+ status = stepValidation.value[step.id] === false ? 'error' : 'complete';
201
+ } else if (index === currentStepIndex.value) {
202
+ status = 'current';
203
+ } else {
204
+ status = 'upcoming';
205
+ }
206
+
207
+ return {
208
+ id: step.id,
209
+ label: step.label,
210
+ status,
211
+ valid: stepValidation.value[step.id] ?? true,
212
+ };
213
+ })
214
+ );
215
+
216
+ // Utility: Get step index by ID
217
+ function getStepIndex(stepId: string): number {
218
+ return steps.findIndex(s => s.id === stepId);
219
+ }
220
+
221
+ // Utility: Get step by ID
222
+ function getStep(stepId: string): WizardStep<T> | undefined {
223
+ return steps.find(s => s.id === stepId);
224
+ }
225
+
226
+ // Validate a specific step
227
+ async function validateStep(stepIndex: number): Promise<boolean> {
228
+ const step = steps[stepIndex];
229
+ if (!step) return false;
230
+
231
+ // Optional steps are always valid
232
+ if (step.optional) {
233
+ stepValidation.value[step.id] = true;
234
+ return true;
235
+ }
236
+
237
+ // Custom validation function
238
+ if (step.validate) {
239
+ try {
240
+ const result = await step.validate(data.value as T);
241
+ stepValidation.value[step.id] = result;
242
+ if (!result) {
243
+ stepErrors.value[step.id] = 'Validation failed';
244
+ } else {
245
+ delete stepErrors.value[step.id];
246
+ }
247
+ return result;
248
+ } catch (error) {
249
+ stepValidation.value[step.id] = false;
250
+ stepErrors.value[step.id] = error instanceof Error ? error.message : 'Validation error';
251
+ return false;
252
+ }
253
+ }
254
+
255
+ // If no custom validation, check if step was marked valid
256
+ // Default to true if not explicitly set
257
+ if (stepValidation.value[step.id] === undefined) {
258
+ stepValidation.value[step.id] = true;
259
+ }
260
+
261
+ return stepValidation.value[step.id] !== false;
262
+ }
263
+
264
+ // Check if navigation to step is allowed
265
+ function canGoToStep(targetIndex: number): boolean {
266
+ if (targetIndex < 0 || targetIndex >= steps.length) return false;
267
+
268
+ // Can always go back if allowed
269
+ if (targetIndex < currentStepIndex.value && allowBackWithoutValidation) {
270
+ return true;
271
+ }
272
+
273
+ // For forward navigation, all previous steps must be valid
274
+ if (targetIndex > currentStepIndex.value && validateOnNext) {
275
+ for (let i = 0; i < targetIndex; i++) {
276
+ const step = steps[i];
277
+ if (!step.optional && stepValidation.value[step.id] === false) {
278
+ return false;
279
+ }
280
+ }
281
+ }
282
+
283
+ return true;
284
+ }
285
+
286
+ // Navigation: Go to next step
287
+ async function goToNext(): Promise<boolean> {
288
+ if (isLastStep.value) return false;
289
+
290
+ // Validate current step before advancing
291
+ if (validateOnNext) {
292
+ const isValid = await validateStep(currentStepIndex.value);
293
+ if (!isValid) return false;
294
+ }
295
+
296
+ const fromIndex = currentStepIndex.value;
297
+ currentStepIndex.value++;
298
+
299
+ onStepChange?.(fromIndex, currentStepIndex.value, data.value as T);
300
+ return true;
301
+ }
302
+
303
+ // Navigation: Go to previous step
304
+ function goToPrevious(): boolean {
305
+ if (isFirstStep.value) return false;
306
+
307
+ const fromIndex = currentStepIndex.value;
308
+ currentStepIndex.value--;
309
+
310
+ onStepChange?.(fromIndex, currentStepIndex.value, data.value as T);
311
+ return true;
312
+ }
313
+
314
+ // Navigation: Go to specific step
315
+ async function goToStep(targetIndex: number): Promise<boolean> {
316
+ if (!canGoToStep(targetIndex)) return false;
317
+
318
+ // If going forward, validate current step
319
+ if (targetIndex > currentStepIndex.value && validateOnNext) {
320
+ const isValid = await validateStep(currentStepIndex.value);
321
+ if (!isValid) return false;
322
+ }
323
+
324
+ const fromIndex = currentStepIndex.value;
325
+ currentStepIndex.value = targetIndex;
326
+
327
+ onStepChange?.(fromIndex, currentStepIndex.value, data.value as T);
328
+ return true;
329
+ }
330
+
331
+ // Data: Update wizard data
332
+ function updateData(newData: Partial<T>): void {
333
+ data.value = { ...data.value, ...newData };
334
+ }
335
+
336
+ // Data: Update data for a specific step
337
+ function updateStepData(stepId: string, stepData: Partial<T>): void {
338
+ updateData(stepData);
339
+ // Clear error when data is updated
340
+ delete stepErrors.value[stepId];
341
+ }
342
+
343
+ // Validation: Set step validation status
344
+ function setStepValid(stepId: string, valid: boolean): void {
345
+ stepValidation.value[stepId] = valid;
346
+ if (valid) {
347
+ delete stepErrors.value[stepId];
348
+ }
349
+ }
350
+
351
+ // Validation: Set step error
352
+ function setStepError(stepId: string, error: string | null): void {
353
+ if (error) {
354
+ stepErrors.value[stepId] = error;
355
+ stepValidation.value[stepId] = false;
356
+ } else {
357
+ delete stepErrors.value[stepId];
358
+ }
359
+ }
360
+
361
+ // Reset: Reset a specific step
362
+ function resetStep(stepId: string): void {
363
+ delete stepValidation.value[stepId];
364
+ delete stepErrors.value[stepId];
365
+ }
366
+
367
+ // Reset: Reset entire wizard
368
+ function reset(): void {
369
+ currentStepIndex.value = 0;
370
+ data.value = { ...initialData };
371
+ stepValidation.value = {};
372
+ stepErrors.value = {};
373
+ isCompleting.value = false;
374
+ }
375
+
376
+ // Complete: Validate all and trigger completion
377
+ async function complete(): Promise<boolean> {
378
+ if (isCompleting.value) return false;
379
+
380
+ isCompleting.value = true;
381
+
382
+ try {
383
+ // Validate all steps
384
+ for (let i = 0; i < steps.length; i++) {
385
+ const isValid = await validateStep(i);
386
+ if (!isValid && !steps[i].optional) {
387
+ // Navigate to failed step
388
+ currentStepIndex.value = i;
389
+ isCompleting.value = false;
390
+ return false;
391
+ }
392
+ }
393
+
394
+ // Call completion handler
395
+ if (onComplete) {
396
+ await onComplete(data.value as T);
397
+ }
398
+
399
+ return true;
400
+ } catch (error) {
401
+ console.error('[useWizard] Completion error:', error);
402
+ return false;
403
+ } finally {
404
+ isCompleting.value = false;
405
+ }
406
+ }
407
+
408
+ return {
409
+ // State
410
+ currentStepIndex,
411
+ currentStep,
412
+ data,
413
+ isFirstStep,
414
+ isLastStep,
415
+ isCompleting,
416
+ stepErrors,
417
+
418
+ // Stepper integration
419
+ stepperSteps,
420
+
421
+ // Validation
422
+ stepValidation,
423
+ currentStepValid,
424
+ allStepsValid,
425
+
426
+ // Navigation
427
+ goToNext,
428
+ goToPrevious,
429
+ goToStep,
430
+ canGoToStep,
431
+
432
+ // Data management
433
+ updateData,
434
+ updateStepData,
435
+ setStepValid,
436
+ setStepError,
437
+ resetStep,
438
+ reset,
439
+
440
+ // Completion
441
+ complete,
442
+
443
+ // Utilities
444
+ getStepIndex,
445
+ getStep,
446
+ progress,
447
+ };
448
+ }