@getmicdrop/svelte-components 5.7.1 → 5.8.0

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 (46) hide show
  1. package/dist/components/Heading.svelte +2 -1
  2. package/dist/components/Heading.svelte.d.ts +1 -1
  3. package/dist/components/Heading.svelte.d.ts.map +1 -1
  4. package/dist/components/Layout/index.d.ts +0 -1
  5. package/dist/components/Layout/index.js +1 -1
  6. package/dist/components/Text.svelte +15 -2
  7. package/dist/components/Text.svelte.d.ts +2 -1
  8. package/dist/components/Text.svelte.d.ts.map +1 -1
  9. package/dist/patterns/layout/index.d.ts +0 -2
  10. package/dist/patterns/layout/index.js +3 -2
  11. package/dist/primitives/Checkbox/Checkbox.svelte +3 -3
  12. package/dist/stores/auth.js +8 -0
  13. package/dist/stores/auth.svelte.d.ts +39 -0
  14. package/dist/stores/auth.svelte.d.ts.map +1 -0
  15. package/dist/stores/auth.svelte.js +60 -0
  16. package/dist/stores/formDataStore.d.ts.map +1 -1
  17. package/dist/stores/formDataStore.js +8 -0
  18. package/dist/stores/formDataStore.svelte.d.ts +47 -0
  19. package/dist/stores/formDataStore.svelte.d.ts.map +1 -0
  20. package/dist/stores/formDataStore.svelte.js +84 -0
  21. package/dist/stores/formSave.d.ts.map +1 -1
  22. package/dist/stores/formSave.js +8 -0
  23. package/dist/stores/formSave.svelte.d.ts +33 -0
  24. package/dist/stores/formSave.svelte.d.ts.map +1 -0
  25. package/dist/stores/formSave.svelte.js +113 -0
  26. package/dist/stores/navigation.d.ts.map +1 -1
  27. package/dist/stores/navigation.js +8 -0
  28. package/dist/stores/navigation.svelte.d.ts +35 -0
  29. package/dist/stores/navigation.svelte.d.ts.map +1 -0
  30. package/dist/stores/navigation.svelte.js +69 -0
  31. package/package.json +8 -9
  32. package/dist/stores/auth.spec.d.ts +0 -2
  33. package/dist/stores/auth.spec.d.ts.map +0 -1
  34. package/dist/stores/auth.spec.js +0 -139
  35. package/dist/stores/createFormStore.spec.d.ts +0 -2
  36. package/dist/stores/createFormStore.spec.d.ts.map +0 -1
  37. package/dist/stores/createFormStore.spec.js +0 -540
  38. package/dist/stores/formDataStore.spec.d.ts +0 -2
  39. package/dist/stores/formDataStore.spec.d.ts.map +0 -1
  40. package/dist/stores/formDataStore.spec.js +0 -257
  41. package/dist/stores/formSave.spec.d.ts +0 -2
  42. package/dist/stores/formSave.spec.d.ts.map +0 -1
  43. package/dist/stores/formSave.spec.js +0 -296
  44. package/dist/stores/navigation.spec.d.ts +0 -2
  45. package/dist/stores/navigation.spec.d.ts.map +0 -1
  46. package/dist/stores/navigation.spec.js +0 -136
@@ -1,540 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import { get } from 'svelte/store';
3
- import { createFormStore } from './createFormStore';
4
-
5
- // Mock showToast
6
- vi.mock('./toaster', () => ({
7
- showToast: vi.fn()
8
- }));
9
-
10
- describe('createFormStore', () => {
11
- beforeEach(() => {
12
- vi.clearAllMocks();
13
- global.fetch = vi.fn();
14
- });
15
-
16
- describe('initialization', () => {
17
- it('creates a form store with initial data', () => {
18
- const form = createFormStore({
19
- initialData: { name: 'John', email: 'john@example.com' }
20
- });
21
-
22
- expect(get(form.data)).toEqual({ name: 'John', email: 'john@example.com' });
23
- });
24
-
25
- it('starts with isDirty as false', () => {
26
- const form = createFormStore({
27
- initialData: { name: 'John' }
28
- });
29
-
30
- expect(get(form.isDirty)).toBe(false);
31
- });
32
-
33
- it('starts with isLoading as false', () => {
34
- const form = createFormStore({
35
- initialData: { name: 'John' }
36
- });
37
-
38
- expect(get(form.isLoading)).toBe(false);
39
- });
40
-
41
- it('starts with isSuccess as false', () => {
42
- const form = createFormStore({
43
- initialData: { name: 'John' }
44
- });
45
-
46
- expect(get(form.isSuccess)).toBe(false);
47
- });
48
-
49
- it('starts with empty errors', () => {
50
- const form = createFormStore({
51
- initialData: { name: 'John' }
52
- });
53
-
54
- expect(get(form.errors)).toEqual({});
55
- });
56
- });
57
-
58
- describe('dirty tracking', () => {
59
- it('detects when data changes', () => {
60
- const form = createFormStore({
61
- initialData: { name: 'John' }
62
- });
63
-
64
- form.data.set({ name: 'Jane' });
65
- expect(get(form.isDirty)).toBe(true);
66
- });
67
-
68
- it('detects when data returns to initial state', () => {
69
- const form = createFormStore({
70
- initialData: { name: 'John' }
71
- });
72
-
73
- form.data.set({ name: 'Jane' });
74
- expect(get(form.isDirty)).toBe(true);
75
-
76
- form.data.set({ name: 'John' });
77
- expect(get(form.isDirty)).toBe(false);
78
- });
79
-
80
- it('resets success state when form becomes dirty', () => {
81
- const form = createFormStore({
82
- initialData: { name: 'John' }
83
- });
84
-
85
- form.isSuccess.set(true);
86
- form.data.set({ name: 'Jane' });
87
- form.checkDirty();
88
-
89
- expect(get(form.isSuccess)).toBe(false);
90
- });
91
- });
92
-
93
- describe('updateData', () => {
94
- it('partially updates form data', () => {
95
- const form = createFormStore({
96
- initialData: { name: 'John', email: 'john@example.com' }
97
- });
98
-
99
- form.updateData({ name: 'Jane' });
100
-
101
- expect(get(form.data)).toEqual({ name: 'Jane', email: 'john@example.com' });
102
- });
103
- });
104
-
105
- describe('updateSection', () => {
106
- it('updates a specific section', () => {
107
- const form = createFormStore({
108
- initialData: {
109
- basicInfo: { name: 'John', email: 'john@example.com' },
110
- social: { twitter: '' }
111
- }
112
- });
113
-
114
- form.updateSection('basicInfo', { name: 'Jane' });
115
-
116
- expect(get(form.data).basicInfo).toEqual({ name: 'Jane', email: 'john@example.com' });
117
- expect(get(form.data).social).toEqual({ twitter: '' });
118
- });
119
- });
120
-
121
- describe('updateField', () => {
122
- it('updates a specific field in a section', () => {
123
- const form = createFormStore({
124
- initialData: {
125
- basicInfo: { name: 'John', email: 'john@example.com' }
126
- }
127
- });
128
-
129
- form.updateField('basicInfo', 'name', 'Jane');
130
-
131
- expect(get(form.data).basicInfo.name).toBe('Jane');
132
- expect(get(form.data).basicInfo.email).toBe('john@example.com');
133
- });
134
- });
135
-
136
- describe('validation', () => {
137
- it('runs validation and populates errors', () => {
138
- const form = createFormStore({
139
- initialData: { name: '', email: '' },
140
- validate: (data) => ({
141
- isValid: false,
142
- errors: {
143
- basicInfo: { name: 'Name is required' }
144
- }
145
- })
146
- });
147
-
148
- const isValid = form.runValidation();
149
-
150
- expect(isValid).toBe(false);
151
- expect(get(form.errors)).toEqual({ basicInfo: { name: 'Name is required' } });
152
- });
153
-
154
- it('clears errors when validation passes', () => {
155
- const form = createFormStore({
156
- initialData: { name: 'John' },
157
- validate: (data) => ({
158
- isValid: true,
159
- errors: {}
160
- })
161
- });
162
-
163
- const isValid = form.runValidation();
164
-
165
- expect(isValid).toBe(true);
166
- expect(get(form.errors)).toEqual({});
167
- });
168
-
169
- it('counts errors correctly', () => {
170
- const form = createFormStore({
171
- initialData: {},
172
- validate: () => ({
173
- isValid: false,
174
- errors: {
175
- basicInfo: { name: 'Required', email: 'Invalid' },
176
- social: { twitter: 'Invalid format' }
177
- }
178
- })
179
- });
180
-
181
- form.runValidation();
182
-
183
- expect(get(form.errorCount)).toBe(3);
184
- });
185
-
186
- it('flattens errors into list', () => {
187
- const form = createFormStore({
188
- initialData: {},
189
- validate: () => ({
190
- isValid: false,
191
- errors: {
192
- basicInfo: { name: 'Name required' }
193
- }
194
- })
195
- });
196
-
197
- form.runValidation();
198
-
199
- const list = get(form.errorList);
200
- expect(list).toContainEqual({ field: 'name', message: 'Name required', section: 'basicInfo' });
201
- });
202
- });
203
-
204
- describe('clearErrors', () => {
205
- it('clears all errors', () => {
206
- const form = createFormStore({
207
- initialData: {}
208
- });
209
-
210
- form.errors.set({ basicInfo: { name: 'Error' } });
211
- form.clearErrors();
212
-
213
- expect(get(form.errors)).toEqual({});
214
- });
215
-
216
- it('resets showErrors to false', () => {
217
- const form = createFormStore({
218
- initialData: {}
219
- });
220
-
221
- form.showErrors.set(true);
222
- form.clearErrors();
223
-
224
- expect(get(form.showErrors)).toBe(false);
225
- });
226
- });
227
-
228
- describe('setFieldError and clearFieldError', () => {
229
- it('sets error for specific field', () => {
230
- const form = createFormStore({
231
- initialData: {}
232
- });
233
-
234
- form.setFieldError('basicInfo', 'name', 'Name is required');
235
-
236
- expect(get(form.errors).basicInfo.name).toBe('Name is required');
237
- });
238
-
239
- it('clears error for specific field', () => {
240
- const form = createFormStore({
241
- initialData: {}
242
- });
243
-
244
- form.errors.set({ basicInfo: { name: 'Error', email: 'Error' } });
245
- form.clearFieldError('basicInfo', 'name');
246
-
247
- expect(get(form.errors).basicInfo.name).toBeUndefined();
248
- expect(get(form.errors).basicInfo.email).toBe('Error');
249
- });
250
- });
251
-
252
- describe('submit', () => {
253
- it('validates before submitting', async () => {
254
- const form = createFormStore({
255
- initialData: { name: '' },
256
- endpoint: '/api/test',
257
- validate: () => ({ isValid: false, errors: { name: 'Required' } })
258
- });
259
-
260
- const result = await form.submit();
261
-
262
- expect(result).toBe(false);
263
- expect(global.fetch).not.toHaveBeenCalled();
264
- });
265
-
266
- it('sends POST request to endpoint', async () => {
267
- global.fetch.mockResolvedValueOnce({ ok: true });
268
-
269
- const form = createFormStore({
270
- initialData: { name: 'John' },
271
- endpoint: '/api/test'
272
- });
273
-
274
- await form.submit();
275
-
276
- expect(global.fetch).toHaveBeenCalledWith('/api/test', {
277
- method: 'POST',
278
- headers: { 'Content-Type': 'application/json' },
279
- body: JSON.stringify({ name: 'John' })
280
- });
281
- });
282
-
283
- it('sets isLoading during request', async () => {
284
- let loadingDuringRequest;
285
- global.fetch.mockImplementation(async () => {
286
- loadingDuringRequest = get(form.isLoading);
287
- return { ok: true };
288
- });
289
-
290
- const form = createFormStore({
291
- initialData: { name: 'John' },
292
- endpoint: '/api/test'
293
- });
294
-
295
- await form.submit();
296
-
297
- expect(loadingDuringRequest).toBe(true);
298
- expect(get(form.isLoading)).toBe(false);
299
- });
300
-
301
- it('sets isSuccess on successful response', async () => {
302
- global.fetch.mockResolvedValueOnce({ ok: true });
303
-
304
- const form = createFormStore({
305
- initialData: { name: 'John' },
306
- endpoint: '/api/test'
307
- });
308
-
309
- const result = await form.submit();
310
-
311
- expect(result).toBe(true);
312
- expect(get(form.isSuccess)).toBe(true);
313
- });
314
-
315
- it('updates initial data on success (form becomes clean)', async () => {
316
- global.fetch.mockResolvedValueOnce({ ok: true });
317
-
318
- const form = createFormStore({
319
- initialData: { name: 'John' },
320
- endpoint: '/api/test'
321
- });
322
-
323
- form.data.set({ name: 'Jane' });
324
- expect(get(form.isDirty)).toBe(true);
325
-
326
- await form.submit();
327
-
328
- expect(get(form.isDirty)).toBe(false);
329
- });
330
-
331
- it('calls onSuccess callback', async () => {
332
- global.fetch.mockResolvedValueOnce({ ok: true });
333
- const onSuccess = vi.fn();
334
-
335
- const form = createFormStore({
336
- initialData: { name: 'John' },
337
- endpoint: '/api/test',
338
- onSuccess
339
- });
340
-
341
- await form.submit();
342
-
343
- expect(onSuccess).toHaveBeenCalled();
344
- });
345
-
346
- it('handles error response', async () => {
347
- global.fetch.mockResolvedValueOnce({
348
- ok: false,
349
- json: async () => ({ message: 'Server error' })
350
- });
351
-
352
- const form = createFormStore({
353
- initialData: { name: 'John' },
354
- endpoint: '/api/test'
355
- });
356
-
357
- const result = await form.submit();
358
-
359
- expect(result).toBe(false);
360
- expect(get(form.saveError)).toBe('Server error');
361
- });
362
-
363
- it('calls onError callback on failure', async () => {
364
- global.fetch.mockResolvedValueOnce({
365
- ok: false,
366
- json: async () => ({})
367
- });
368
- const onError = vi.fn();
369
-
370
- const form = createFormStore({
371
- initialData: { name: 'John' },
372
- endpoint: '/api/test',
373
- onError
374
- });
375
-
376
- await form.submit();
377
-
378
- expect(onError).toHaveBeenCalled();
379
- });
380
-
381
- it('handles network error', async () => {
382
- global.fetch.mockRejectedValueOnce(new Error('Network error'));
383
-
384
- const form = createFormStore({
385
- initialData: { name: 'John' },
386
- endpoint: '/api/test'
387
- });
388
-
389
- const result = await form.submit();
390
-
391
- expect(result).toBe(false);
392
- expect(get(form.saveError)).toBe('Network error');
393
- });
394
-
395
- it('transforms data before submitting', async () => {
396
- global.fetch.mockResolvedValueOnce({ ok: true });
397
-
398
- const form = createFormStore({
399
- initialData: { name: 'John' },
400
- endpoint: '/api/test',
401
- transformData: (data) => ({ ...data, transformed: true })
402
- });
403
-
404
- await form.submit();
405
-
406
- expect(global.fetch).toHaveBeenCalledWith('/api/test', expect.objectContaining({
407
- body: JSON.stringify({ name: 'John', transformed: true })
408
- }));
409
- });
410
-
411
- it('allows custom endpoint override', async () => {
412
- global.fetch.mockResolvedValueOnce({ ok: true });
413
-
414
- const form = createFormStore({
415
- initialData: { name: 'John' },
416
- endpoint: '/api/default'
417
- });
418
-
419
- await form.submit('/api/custom');
420
-
421
- expect(global.fetch).toHaveBeenCalledWith('/api/custom', expect.any(Object));
422
- });
423
- });
424
-
425
- describe('reset', () => {
426
- it('resets data to initial state', () => {
427
- const form = createFormStore({
428
- initialData: { name: 'John' }
429
- });
430
-
431
- form.data.set({ name: 'Jane' });
432
- form.reset();
433
-
434
- expect(get(form.data)).toEqual({ name: 'John' });
435
- });
436
-
437
- it('clears errors', () => {
438
- const form = createFormStore({
439
- initialData: { name: 'John' }
440
- });
441
-
442
- form.errors.set({ basicInfo: { name: 'Error' } });
443
- form.reset();
444
-
445
- expect(get(form.errors)).toEqual({});
446
- });
447
-
448
- it('resets all state flags', () => {
449
- const form = createFormStore({
450
- initialData: { name: 'John' }
451
- });
452
-
453
- form.showErrors.set(true);
454
- form.isSuccess.set(true);
455
- form.saveError.set('Error');
456
- form.reset();
457
-
458
- expect(get(form.showErrors)).toBe(false);
459
- expect(get(form.isSuccess)).toBe(false);
460
- expect(get(form.saveError)).toBe(null);
461
- });
462
- });
463
-
464
- describe('resetTo', () => {
465
- it('resets to new initial data', () => {
466
- const form = createFormStore({
467
- initialData: { name: 'John' }
468
- });
469
-
470
- form.resetTo({ name: 'Jane', email: 'jane@example.com' });
471
-
472
- expect(get(form.data)).toEqual({ name: 'Jane', email: 'jane@example.com' });
473
- expect(get(form.isDirty)).toBe(false);
474
- });
475
- });
476
-
477
- describe('markSaved', () => {
478
- it('updates initial to match current and sets success', () => {
479
- const form = createFormStore({
480
- initialData: { name: 'John' }
481
- });
482
-
483
- form.data.set({ name: 'Jane' });
484
- expect(get(form.isDirty)).toBe(true);
485
-
486
- form.markSaved();
487
-
488
- expect(get(form.isDirty)).toBe(false);
489
- expect(get(form.isSuccess)).toBe(true);
490
- });
491
- });
492
-
493
- describe('combined store subscription', () => {
494
- it('provides all state via subscribe', () => {
495
- const form = createFormStore({
496
- initialData: { name: 'John' }
497
- });
498
-
499
- let state;
500
- const unsubscribe = form.subscribe(s => { state = s; });
501
-
502
- expect(state.data).toEqual({ name: 'John' });
503
- expect(state.isDirty).toBe(false);
504
- expect(state.isLoading).toBe(false);
505
- expect(state.isSuccess).toBe(false);
506
- expect(state.errors).toEqual({});
507
-
508
- unsubscribe();
509
- });
510
- });
511
-
512
- describe('convenience getters', () => {
513
- it('provides currentData getter', () => {
514
- const form = createFormStore({
515
- initialData: { name: 'John' }
516
- });
517
-
518
- expect(form.currentData).toEqual({ name: 'John' });
519
- });
520
-
521
- it('provides loading getter', () => {
522
- const form = createFormStore({
523
- initialData: { name: 'John' }
524
- });
525
-
526
- expect(form.loading).toBe(false);
527
- });
528
-
529
- it('provides dirty getter', () => {
530
- const form = createFormStore({
531
- initialData: { name: 'John' }
532
- });
533
-
534
- expect(form.dirty).toBe(false);
535
-
536
- form.data.set({ name: 'Jane' });
537
- expect(form.dirty).toBe(true);
538
- });
539
- });
540
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=formDataStore.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"formDataStore.spec.d.ts","sourceRoot":"","sources":["../../src/lib/stores/formDataStore.spec.js"],"names":[],"mappings":""}