@prolibu-suite/cobalt-form 0.2.1 → 1.0.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.
- package/dist/cjs/co-form-wizard.cjs.entry.js +40 -11
- package/dist/cjs/co-form.cjs.entry.js +1 -1
- package/dist/cjs/cobalt-form.cjs.js +1 -1
- package/dist/cjs/{index-CLL7Ervz.js → index-Brpri7nS.js} +120 -19
- package/dist/cjs/index.cjs.js +146 -5
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cobalt-form/cobalt-form.esm.js +1 -1
- package/dist/cobalt-form/index.esm.js +1 -1
- package/dist/cobalt-form/p-296094ec.entry.js +1 -0
- package/dist/cobalt-form/{p-2168be6b.entry.js → p-95e1cedb.entry.js} +1 -1
- package/dist/cobalt-form/{p-CPE0t-C2.js → p-CzvtCEKX.js} +3 -3
- package/dist/collection/components/co-form/co-form.css +328 -4
- package/dist/collection/components/co-form/co-form.js +167 -4
- package/dist/collection/components/co-form-wizard/co-form-wizard.css +7 -0
- package/dist/collection/components/co-form-wizard/co-form-wizard.js +92 -10
- package/dist/components/co-form-wizard.js +1 -1
- package/dist/components/index.js +7 -7
- package/dist/esm/co-form-wizard.entry.js +40 -11
- package/dist/esm/co-form.entry.js +1 -1
- package/dist/esm/cobalt-form.js +1 -1
- package/dist/esm/{index-CPE0t-C2.js → index-CzvtCEKX.js} +120 -19
- package/dist/esm/index.js +146 -5
- package/dist/esm/loader.js +1 -1
- package/dist/types/components/co-form/co-form.d.ts +7 -0
- package/dist/types/components/co-form-wizard/co-form-wizard.d.ts +15 -1
- package/dist/types/components.d.ts +33 -0
- package/dist/types/jsx-cobalt.d.ts +3 -0
- package/package.json +3 -3
- package/dist/cobalt-form/p-7b8f67bc.entry.js +0 -1
|
@@ -68,13 +68,13 @@ form[data-has-bg] {
|
|
|
68
68
|
padding: var(--co-spacing-2xl, 24px);
|
|
69
69
|
background: var(--co-semantic-surface-page, #fff);
|
|
70
70
|
border-radius: var(--co-border-radius-sm, 12px);
|
|
71
|
-
box-shadow: 0 4px 24px
|
|
71
|
+
box-shadow: var(--co-shadow-lg, 0 4px 24px var(--co-color-opacity-negro-8));
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
form[data-theme="dark"][data-has-bg] {
|
|
75
|
-
background:
|
|
76
|
-
color:
|
|
77
|
-
box-shadow: 0 4px 24px
|
|
75
|
+
background: var(--co-semantic-surface-page);
|
|
76
|
+
color: var(--co-semantic-text-default);
|
|
77
|
+
box-shadow: 0 4px 24px var(--co-color-opacity-negro-50);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
/* Dark mode — re-bind ALL semantic tokens so cards, inputs, and buttons
|
|
@@ -90,6 +90,8 @@ form[data-theme="dark"] {
|
|
|
90
90
|
--co-semantic-surface-muted: #2a3142;
|
|
91
91
|
--co-semantic-surface-hover: rgba(255, 255, 255, 0.06);
|
|
92
92
|
--co-semantic-surface-disabled: rgba(255, 255, 255, 0.04);
|
|
93
|
+
--co-semantic-on-primary: #1a1f2b;
|
|
94
|
+
--co-semantic-on-secondary: #f9fafb;
|
|
93
95
|
--co-semantic-text-default: #f9fafb;
|
|
94
96
|
--co-semantic-text-secondary: #9ca3af;
|
|
95
97
|
--co-semantic-text-muted: #6b7280;
|
|
@@ -187,3 +189,325 @@ form[data-hide-header] .co-form-layout > slot[name="header"] {
|
|
|
187
189
|
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
|
188
190
|
gap: var(--co-spacing-sm, 8px);
|
|
189
191
|
}
|
|
192
|
+
|
|
193
|
+
/* Textarea (long answer) */
|
|
194
|
+
.co-form-textarea-wrap {
|
|
195
|
+
display: flex;
|
|
196
|
+
flex-direction: column;
|
|
197
|
+
gap: var(--co-spacing-xxs, 2px);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.co-form-textarea-wrap__label {
|
|
201
|
+
font-size: var(--co-font-size-14, 14px);
|
|
202
|
+
font-weight: 500;
|
|
203
|
+
color: var(--co-semantic-text-default, #111);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.co-form-textarea {
|
|
207
|
+
width: 100%;
|
|
208
|
+
min-height: 100px;
|
|
209
|
+
padding: var(--co-spacing-sm, 8px) var(--co-spacing-md, 12px);
|
|
210
|
+
font-family: var(--co-font-family-primary, sans-serif);
|
|
211
|
+
font-size: var(--co-font-size-14, 14px);
|
|
212
|
+
color: var(--co-semantic-text-default, #111);
|
|
213
|
+
background: var(--co-semantic-surface-secondary, #f7f6f0);
|
|
214
|
+
border: 1px solid var(--co-semantic-border-default, #e5e7eb);
|
|
215
|
+
border-radius: var(--co-border-radius-xxs, 4px);
|
|
216
|
+
resize: vertical;
|
|
217
|
+
outline: none;
|
|
218
|
+
transition: border-color 120ms;
|
|
219
|
+
box-sizing: border-box;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.co-form-textarea:focus {
|
|
223
|
+
border-color: var(--co-color-primary-azul, #2563eb);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.co-form-textarea--error {
|
|
227
|
+
border-color: var(--co-color-status-error, #AA2E1B);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.co-form-textarea:disabled {
|
|
231
|
+
opacity: 0.5;
|
|
232
|
+
cursor: not-allowed;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.co-form-textarea-wrap__helper {
|
|
236
|
+
margin: 0;
|
|
237
|
+
font-size: var(--co-font-size-12, 12px);
|
|
238
|
+
color: var(--co-semantic-text-secondary, #6b7280);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.co-form-textarea-wrap__helper[data-status="error"] {
|
|
242
|
+
color: var(--co-color-status-error, #AA2E1B);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/* Number field — constrain width */
|
|
246
|
+
co-number-field {
|
|
247
|
+
max-width: 240px;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/* Ordering */
|
|
251
|
+
.co-form-ordering {
|
|
252
|
+
grid-column: 1 / -1;
|
|
253
|
+
display: flex;
|
|
254
|
+
flex-direction: column;
|
|
255
|
+
gap: var(--co-spacing-xs, 4px);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.co-form-ordering__label {
|
|
259
|
+
font-size: var(--co-font-size-14, 14px);
|
|
260
|
+
font-weight: 500;
|
|
261
|
+
color: var(--co-semantic-text-default, #111);
|
|
262
|
+
margin-bottom: var(--co-spacing-xs, 4px);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.co-form-ordering__helper {
|
|
266
|
+
margin: 0 0 var(--co-spacing-xs, 4px);
|
|
267
|
+
font-size: var(--co-font-size-12, 12px);
|
|
268
|
+
color: var(--co-semantic-text-secondary, #6b7280);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.co-form-ordering__list {
|
|
272
|
+
display: flex;
|
|
273
|
+
flex-direction: column;
|
|
274
|
+
gap: var(--co-spacing-xs, 4px);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.co-form-ordering__item {
|
|
278
|
+
display: flex;
|
|
279
|
+
align-items: center;
|
|
280
|
+
gap: var(--co-spacing-sm, 8px);
|
|
281
|
+
padding: var(--co-spacing-sm, 8px) var(--co-spacing-md, 12px);
|
|
282
|
+
border: 1px solid var(--co-semantic-border-default, #e5e7eb);
|
|
283
|
+
border-radius: var(--co-border-radius-xxs, 4px);
|
|
284
|
+
background: var(--co-semantic-surface-secondary, #f7f6f0);
|
|
285
|
+
transition: border-color 120ms, box-shadow 120ms, opacity 120ms;
|
|
286
|
+
cursor: grab;
|
|
287
|
+
user-select: none;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.co-form-ordering__item:hover {
|
|
291
|
+
border-color: var(--co-color-primary-azul, #2563eb);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.co-form-ordering__item.is-dragging {
|
|
295
|
+
opacity: 0.4;
|
|
296
|
+
cursor: grabbing;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.co-form-ordering__item.is-drop-target {
|
|
300
|
+
border-color: var(--co-color-primary-azul, #2563eb);
|
|
301
|
+
box-shadow: 0 -2px 0 0 var(--co-color-primary-azul, #2563eb);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.co-form-ordering__grip {
|
|
305
|
+
display: flex;
|
|
306
|
+
align-items: center;
|
|
307
|
+
color: var(--co-semantic-text-muted, #9ca3af);
|
|
308
|
+
flex-shrink: 0;
|
|
309
|
+
cursor: grab;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.co-form-ordering__num {
|
|
313
|
+
display: inline-flex;
|
|
314
|
+
align-items: center;
|
|
315
|
+
justify-content: center;
|
|
316
|
+
width: 24px;
|
|
317
|
+
height: 24px;
|
|
318
|
+
border-radius: var(--co-border-radius-full, 9999px);
|
|
319
|
+
background: color-mix(in srgb, var(--co-color-primary-azul, #2563eb) 10%, transparent);
|
|
320
|
+
color: var(--co-color-primary-azul, #2563eb);
|
|
321
|
+
font-size: 12px;
|
|
322
|
+
font-weight: 700;
|
|
323
|
+
flex-shrink: 0;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.co-form-ordering__text {
|
|
327
|
+
flex: 1;
|
|
328
|
+
font-size: var(--co-font-size-14, 14px);
|
|
329
|
+
color: var(--co-semantic-text-default, #111);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.co-form-ordering__actions {
|
|
333
|
+
display: flex;
|
|
334
|
+
flex-direction: column;
|
|
335
|
+
gap: 1px;
|
|
336
|
+
flex-shrink: 0;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
.co-form-ordering__move-btn {
|
|
340
|
+
display: flex;
|
|
341
|
+
align-items: center;
|
|
342
|
+
justify-content: center;
|
|
343
|
+
width: 22px;
|
|
344
|
+
height: 16px;
|
|
345
|
+
padding: 0;
|
|
346
|
+
border: none;
|
|
347
|
+
background: transparent;
|
|
348
|
+
color: var(--co-semantic-text-muted, #9ca3af);
|
|
349
|
+
cursor: pointer;
|
|
350
|
+
border-radius: var(--co-border-radius-xxs, 4px);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
.co-form-ordering__move-btn:hover:not(:disabled) {
|
|
354
|
+
background: var(--co-semantic-surface-hover, #f3f4f6);
|
|
355
|
+
color: var(--co-semantic-text-default, #111);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.co-form-ordering__move-btn:disabled {
|
|
359
|
+
opacity: 0.3;
|
|
360
|
+
cursor: not-allowed;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/* Matching */
|
|
364
|
+
.co-form-matching {
|
|
365
|
+
grid-column: 1 / -1;
|
|
366
|
+
display: flex;
|
|
367
|
+
flex-direction: column;
|
|
368
|
+
gap: var(--co-spacing-xs, 4px);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
.co-form-matching__label {
|
|
372
|
+
font-size: var(--co-font-size-14, 14px);
|
|
373
|
+
font-weight: 500;
|
|
374
|
+
color: var(--co-semantic-text-default, #111);
|
|
375
|
+
margin-bottom: var(--co-spacing-xs, 4px);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
.co-form-matching__helper {
|
|
379
|
+
margin: 0 0 var(--co-spacing-xs, 4px);
|
|
380
|
+
font-size: var(--co-font-size-12, 12px);
|
|
381
|
+
color: var(--co-semantic-text-secondary, #6b7280);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
.co-form-matching__list {
|
|
385
|
+
display: flex;
|
|
386
|
+
flex-direction: column;
|
|
387
|
+
gap: var(--co-spacing-sm, 8px);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
.co-form-matching__row {
|
|
391
|
+
display: grid;
|
|
392
|
+
grid-template-columns: 1fr 20px 1fr;
|
|
393
|
+
gap: var(--co-spacing-sm, 8px);
|
|
394
|
+
align-items: center;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
.co-form-matching__term {
|
|
398
|
+
font-size: var(--co-font-size-14, 14px);
|
|
399
|
+
font-weight: 500;
|
|
400
|
+
color: var(--co-semantic-text-default, #111);
|
|
401
|
+
padding: var(--co-spacing-sm, 8px) var(--co-spacing-md, 12px);
|
|
402
|
+
border: 1px solid var(--co-semantic-border-default, #e5e7eb);
|
|
403
|
+
border-radius: var(--co-border-radius-xxs, 4px);
|
|
404
|
+
background: var(--co-semantic-surface-secondary, #f7f6f0);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
.co-form-matching__row co-icon {
|
|
408
|
+
color: var(--co-semantic-text-muted, #9ca3af);
|
|
409
|
+
justify-self: center;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
.co-form-matching__select {
|
|
413
|
+
min-width: 0;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/* Image Choice */
|
|
417
|
+
.co-form-image-choice {
|
|
418
|
+
grid-column: 1 / -1;
|
|
419
|
+
display: flex;
|
|
420
|
+
flex-direction: column;
|
|
421
|
+
gap: var(--co-spacing-xs, 4px);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
.co-form-image-choice__label {
|
|
425
|
+
font-size: var(--co-font-size-14, 14px);
|
|
426
|
+
font-weight: 500;
|
|
427
|
+
color: var(--co-semantic-text-default, #111);
|
|
428
|
+
margin-bottom: var(--co-spacing-xs, 4px);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.co-form-image-choice__helper {
|
|
432
|
+
margin: 0 0 var(--co-spacing-xs, 4px);
|
|
433
|
+
font-size: var(--co-font-size-12, 12px);
|
|
434
|
+
color: var(--co-semantic-text-secondary, #6b7280);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
.co-form-image-choice__helper[data-status="error"] {
|
|
438
|
+
color: var(--co-color-status-error, #AA2E1B);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
.co-form-image-choice__grid {
|
|
442
|
+
display: grid;
|
|
443
|
+
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
|
|
444
|
+
gap: var(--co-spacing-sm, 8px);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
.co-form-image-choice__card {
|
|
448
|
+
display: flex;
|
|
449
|
+
flex-direction: column;
|
|
450
|
+
border: 2px solid var(--co-semantic-border-default, #e5e7eb);
|
|
451
|
+
border-radius: var(--co-border-radius-xs, 8px);
|
|
452
|
+
overflow: hidden;
|
|
453
|
+
cursor: pointer;
|
|
454
|
+
transition: border-color 120ms, box-shadow 120ms;
|
|
455
|
+
background: var(--co-semantic-surface-secondary, #f7f6f0);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
.co-form-image-choice__card:hover:not(.is-disabled) {
|
|
459
|
+
border-color: var(--co-color-primary-azul, #2563eb);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.co-form-image-choice__card.is-selected {
|
|
463
|
+
border-color: var(--co-color-primary-azul, #2563eb);
|
|
464
|
+
box-shadow: 0 0 0 2px color-mix(in srgb, var(--co-color-primary-azul, #2563eb) 20%, transparent);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
.co-form-image-choice__card.is-disabled {
|
|
468
|
+
opacity: 0.5;
|
|
469
|
+
cursor: not-allowed;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
.co-form-image-choice__img-wrap {
|
|
473
|
+
width: 100%;
|
|
474
|
+
height: 100px;
|
|
475
|
+
display: flex;
|
|
476
|
+
align-items: center;
|
|
477
|
+
justify-content: center;
|
|
478
|
+
overflow: hidden;
|
|
479
|
+
color: var(--co-semantic-text-muted, #9ca3af);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
.co-form-image-choice__img {
|
|
483
|
+
width: 100%;
|
|
484
|
+
height: 100%;
|
|
485
|
+
object-fit: cover;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
.co-form-image-choice__footer {
|
|
489
|
+
display: flex;
|
|
490
|
+
align-items: center;
|
|
491
|
+
gap: var(--co-spacing-xs, 4px);
|
|
492
|
+
padding: var(--co-spacing-xs, 4px) var(--co-spacing-sm, 8px);
|
|
493
|
+
border-top: 1px solid var(--co-semantic-border-default, #e5e7eb);
|
|
494
|
+
min-height: 32px;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
.co-form-image-choice__check {
|
|
498
|
+
flex-shrink: 0;
|
|
499
|
+
display: flex;
|
|
500
|
+
color: var(--co-semantic-text-muted, #9ca3af);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
.co-form-image-choice__card.is-selected .co-form-image-choice__check {
|
|
504
|
+
color: var(--co-color-primary-azul, #2563eb);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
.co-form-image-choice__text {
|
|
508
|
+
font-size: var(--co-font-size-13, 13px);
|
|
509
|
+
color: var(--co-semantic-text-default, #111);
|
|
510
|
+
overflow: hidden;
|
|
511
|
+
text-overflow: ellipsis;
|
|
512
|
+
white-space: nowrap;
|
|
513
|
+
}
|
|
@@ -53,6 +53,8 @@ export class CoForm {
|
|
|
53
53
|
this.footerAlign = 'end';
|
|
54
54
|
/** Hide the entire footer (use when embedded in a wizard or custom shell). */
|
|
55
55
|
this.hideFooter = false;
|
|
56
|
+
/** When to run validation: on every change, on blur, or only on submit. */
|
|
57
|
+
this.validateOn = 'change';
|
|
56
58
|
this.snapshot = {
|
|
57
59
|
values: {},
|
|
58
60
|
errors: {},
|
|
@@ -128,6 +130,9 @@ export class CoForm {
|
|
|
128
130
|
}
|
|
129
131
|
this.handleFieldChange(f.name, value);
|
|
130
132
|
};
|
|
133
|
+
// ── Ordering (kind: 'ordering') ───────────────────────────────────────────
|
|
134
|
+
this.orderingDragIdx = null;
|
|
135
|
+
this.orderingDropIdx = null;
|
|
131
136
|
}
|
|
132
137
|
componentWillLoad() {
|
|
133
138
|
this.rebuildController();
|
|
@@ -195,6 +200,7 @@ export class CoForm {
|
|
|
195
200
|
this.controller = createForm({
|
|
196
201
|
schema: { instance },
|
|
197
202
|
initialValues,
|
|
203
|
+
validateOn: this.validateOn,
|
|
198
204
|
});
|
|
199
205
|
this.fields = describeFields(instance.formSchema.properties);
|
|
200
206
|
this.snapshot = this.controller.state;
|
|
@@ -455,8 +461,14 @@ export class CoForm {
|
|
|
455
461
|
switch (f.kind) {
|
|
456
462
|
case 'text':
|
|
457
463
|
return (h("co-input", Object.assign({}, common, { value: value !== null && value !== void 0 ? value : '', onCoInput: (e) => this.handleFieldChange(f.name, e.detail) })));
|
|
458
|
-
case 'textarea':
|
|
459
|
-
|
|
464
|
+
case 'textarea': {
|
|
465
|
+
const textareaId = `co-form-${f.name}`;
|
|
466
|
+
const helperId = helperText ? `co-form-${f.name}-helper` : undefined;
|
|
467
|
+
return (h("div", { class: "co-form-textarea-wrap", "data-full": f.originalAttrs.full ? 'true' : undefined }, f.label && h("label", { class: "co-form-textarea-wrap__label", htmlFor: textareaId }, f.label), h("textarea", { id: textareaId, class: {
|
|
468
|
+
'co-form-textarea': true,
|
|
469
|
+
'co-form-textarea--error': status === 'error',
|
|
470
|
+
}, name: f.name, placeholder: f.placeholder, disabled: disabled, required: required, rows: 4, "aria-invalid": status === 'error' ? 'true' : undefined, "aria-describedby": helperId, value: value !== null && value !== void 0 ? value : '', onInput: (e) => this.handleFieldChange(f.name, e.target.value) }), helperText && h("p", { id: helperId, class: "co-form-textarea-wrap__helper", "data-status": status }, helperText)));
|
|
471
|
+
}
|
|
460
472
|
case 'html':
|
|
461
473
|
return (h("co-input", Object.assign({}, common, { multiline: true, value: value !== null && value !== void 0 ? value : '', onCoInput: (e) => this.handleFieldChange(f.name, e.detail) })));
|
|
462
474
|
case 'date':
|
|
@@ -467,16 +479,28 @@ export class CoForm {
|
|
|
467
479
|
return (h("co-switch", Object.assign({}, common, { checked: !!value, onCoChange: (e) => this.handleFieldChange(f.name, e.detail) })));
|
|
468
480
|
case 'select':
|
|
469
481
|
return (h("co-select", Object.assign({}, common, { options: JSON.stringify(this.optionsFor(f)), value: String(value !== null && value !== void 0 ? value : ''), onCoChange: (e) => this.handleFieldChange(f.name, e.detail) })));
|
|
482
|
+
case 'radio':
|
|
483
|
+
return (h("co-radio-group", Object.assign({}, common, { options: JSON.stringify(this.optionsFor(f)), value: String(value !== null && value !== void 0 ? value : ''), onCoChange: (e) => this.handleFieldChange(f.name, e.detail) })));
|
|
484
|
+
case 'checkbox':
|
|
485
|
+
return (h("co-checkbox-group", Object.assign({}, common, { options: JSON.stringify(this.optionsFor(f)), value: JSON.stringify(Array.isArray(value) ? value : []), onCoChange: (e) => this.handleFieldChange(f.name, e.detail) })));
|
|
470
486
|
case 'rating':
|
|
471
487
|
return (h("co-rating", Object.assign({}, common, { value: typeof value === 'number' ? value : 0, max: Number((_c = f.originalAttrs.max) !== null && _c !== void 0 ? _c : 5), onCoChange: (e) => this.handleFieldChange(f.name, e.detail) })));
|
|
472
488
|
case 'slider':
|
|
473
489
|
return (h("co-slider", Object.assign({}, common, { value: typeof value === 'number' ? value : Number((_d = f.originalAttrs.min) !== null && _d !== void 0 ? _d : 0), min: Number((_e = f.originalAttrs.min) !== null && _e !== void 0 ? _e : 0), max: Number((_f = f.originalAttrs.max) !== null && _f !== void 0 ? _f : 100), step: Number((_g = f.originalAttrs.step) !== null && _g !== void 0 ? _g : 1), onCoChange: (e) => this.handleFieldChange(f.name, e.detail) })));
|
|
474
490
|
case 'color':
|
|
475
|
-
return (h("co-
|
|
491
|
+
return (h("co-color-picker", Object.assign({}, common, { value: typeof value === 'string' ? value : '', presets: f.originalAttrs.presets ? JSON.stringify(f.originalAttrs.presets) : undefined, onCoChange: (e) => this.handleFieldChange(f.name, e.detail) })));
|
|
476
492
|
case 'section':
|
|
477
493
|
return (h("div", { class: "co-form-section", key: f.name }, h("h3", { class: "co-form-section__title" }, f.label), f.helperText && h("p", { class: "co-form-section__desc" }, f.helperText)));
|
|
494
|
+
case 'phone':
|
|
495
|
+
return (h("co-phone-field", Object.assign({}, common, { value: typeof value === 'string' ? value : '', defaultCountry: f.originalAttrs.defaultCountry || '', onCoChange: (e) => this.handleFieldChange(f.name, e.detail) })));
|
|
478
496
|
case 'file':
|
|
479
497
|
return (h("co-input", Object.assign({}, common, { type: "file", onCoInput: (e) => this.handleFieldChange(f.name, e.detail) })));
|
|
498
|
+
case 'ordering':
|
|
499
|
+
return this.renderOrdering(f, value);
|
|
500
|
+
case 'matching':
|
|
501
|
+
return this.renderMatching(f, value);
|
|
502
|
+
case 'image-choice':
|
|
503
|
+
return this.renderImageChoice(f, value);
|
|
480
504
|
case 'array':
|
|
481
505
|
return this.renderRepeater(f, value);
|
|
482
506
|
case 'ref': {
|
|
@@ -529,6 +553,123 @@ export class CoForm {
|
|
|
529
553
|
return (h("co-input", { key: n, label: ((_a = itemSchema[n]) === null || _a === void 0 ? void 0 : _a.label) || n, value: (_b = row[n]) !== null && _b !== void 0 ? _b : '', disabled: this.disabled || f.disabled, onCoInput: (e) => patchRow(idx, n, e.detail) }));
|
|
530
554
|
})), h("co-icon-button", { icon: "trash", variant: "ghost", onClick: () => removeRow(idx), disabled: this.disabled || f.disabled })))), h("co-button", { label: "Agregar", variant: "outlined", "icon-left": "plus", onClick: addRow, disabled: this.disabled || f.disabled })));
|
|
531
555
|
}
|
|
556
|
+
// ── Image Choice (kind: 'image-choice') ────────────────────────────────
|
|
557
|
+
renderImageChoice(f, value) {
|
|
558
|
+
const opts = Array.isArray(f.originalAttrs.enum) ? f.originalAttrs.enum : [];
|
|
559
|
+
const images = Array.isArray(f.originalAttrs.optionImages) ? f.originalAttrs.optionImages : [];
|
|
560
|
+
const isMulti = !!f.originalAttrs.multiSelect;
|
|
561
|
+
const isDisabled = this.disabled || f.disabled;
|
|
562
|
+
const isTouched = !!this.snapshot.touched[f.name];
|
|
563
|
+
const errors = isTouched ? this.snapshot.errors[f.name] || [] : [];
|
|
564
|
+
const helperText = errors[0] || f.helperText;
|
|
565
|
+
// For single select: value is a string (option text or index).
|
|
566
|
+
// For multi select: value is an array.
|
|
567
|
+
const selected = isMulti
|
|
568
|
+
? (Array.isArray(value) ? value : [])
|
|
569
|
+
: (value != null && value !== '' ? [String(value)] : []);
|
|
570
|
+
const toggle = (opt) => {
|
|
571
|
+
if (isDisabled)
|
|
572
|
+
return;
|
|
573
|
+
if (isMulti) {
|
|
574
|
+
const next = selected.includes(opt)
|
|
575
|
+
? selected.filter((s) => s !== opt)
|
|
576
|
+
: [...selected, opt];
|
|
577
|
+
this.handleFieldChange(f.name, next);
|
|
578
|
+
}
|
|
579
|
+
else {
|
|
580
|
+
this.handleFieldChange(f.name, opt);
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
return (h("div", { class: "co-form-image-choice", key: f.name, "data-full": f.originalAttrs.full ? 'true' : undefined }, f.label && h("label", { class: "co-form-image-choice__label" }, f.label), helperText && h("p", { class: "co-form-image-choice__helper", "data-status": errors.length ? 'error' : undefined }, helperText), h("div", { class: "co-form-image-choice__grid", role: isMulti ? 'group' : 'radiogroup', "aria-label": f.label || f.name }, opts.map((opt, idx) => {
|
|
584
|
+
const isSelected = selected.includes(opt);
|
|
585
|
+
const imgSrc = images[idx] || '';
|
|
586
|
+
return (h("div", { class: `co-form-image-choice__card ${isSelected ? 'is-selected' : ''} ${isDisabled ? 'is-disabled' : ''}`, key: `${f.name}-${idx}`, onClick: () => toggle(opt), onKeyDown: (e) => {
|
|
587
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
588
|
+
e.preventDefault();
|
|
589
|
+
toggle(opt);
|
|
590
|
+
}
|
|
591
|
+
}, role: isMulti ? 'checkbox' : 'radio', "aria-checked": isSelected ? 'true' : 'false', "aria-disabled": isDisabled ? 'true' : undefined, tabIndex: isDisabled ? -1 : 0 }, h("div", { class: "co-form-image-choice__img-wrap" }, imgSrc
|
|
592
|
+
? h("img", { src: imgSrc, alt: opt, class: "co-form-image-choice__img" })
|
|
593
|
+
: h("co-icon", { name: "image-square", size: "32" })), h("div", { class: "co-form-image-choice__footer" }, h("span", { class: "co-form-image-choice__check" }, isSelected && h("co-icon", { name: "check-circle", size: "18", weight: "fill" }), !isSelected && h("co-icon", { name: "circle", size: "18" })), opt && h("span", { class: "co-form-image-choice__text" }, opt))));
|
|
594
|
+
}))));
|
|
595
|
+
}
|
|
596
|
+
renderOrdering(f, value) {
|
|
597
|
+
const items = Array.isArray(f.originalAttrs.enum) ? f.originalAttrs.enum : [];
|
|
598
|
+
// Value is the user's ordering: an array of item strings in the order they chose.
|
|
599
|
+
const ordered = Array.isArray(value) ? value : [...items];
|
|
600
|
+
const isDisabled = this.disabled || f.disabled;
|
|
601
|
+
const isTouched = !!this.snapshot.touched[f.name];
|
|
602
|
+
const errors = isTouched ? this.snapshot.errors[f.name] || [] : [];
|
|
603
|
+
const helperText = errors[0] || f.helperText;
|
|
604
|
+
const onDragStart = (ev, idx) => {
|
|
605
|
+
if (isDisabled)
|
|
606
|
+
return;
|
|
607
|
+
this.orderingDragIdx = idx;
|
|
608
|
+
if (ev.dataTransfer) {
|
|
609
|
+
ev.dataTransfer.effectAllowed = 'move';
|
|
610
|
+
ev.dataTransfer.setData('text/plain', String(idx));
|
|
611
|
+
}
|
|
612
|
+
};
|
|
613
|
+
const onDragOver = (ev, idx) => {
|
|
614
|
+
if (this.orderingDragIdx === null)
|
|
615
|
+
return;
|
|
616
|
+
ev.preventDefault();
|
|
617
|
+
if (ev.dataTransfer)
|
|
618
|
+
ev.dataTransfer.dropEffect = 'move';
|
|
619
|
+
this.orderingDropIdx = idx;
|
|
620
|
+
};
|
|
621
|
+
const onDrop = (ev, idx) => {
|
|
622
|
+
ev.preventDefault();
|
|
623
|
+
const fromIdx = this.orderingDragIdx;
|
|
624
|
+
this.orderingDragIdx = null;
|
|
625
|
+
this.orderingDropIdx = null;
|
|
626
|
+
if (fromIdx === null || fromIdx === idx)
|
|
627
|
+
return;
|
|
628
|
+
const next = [...ordered];
|
|
629
|
+
const [moved] = next.splice(fromIdx, 1);
|
|
630
|
+
// Adjust target for downward moves: removing fromIdx shifts later indices down by 1
|
|
631
|
+
const insertAt = fromIdx < idx ? idx - 1 : idx;
|
|
632
|
+
next.splice(insertAt, 0, moved);
|
|
633
|
+
this.handleFieldChange(f.name, next);
|
|
634
|
+
};
|
|
635
|
+
const onDragEnd = () => {
|
|
636
|
+
this.orderingDragIdx = null;
|
|
637
|
+
this.orderingDropIdx = null;
|
|
638
|
+
};
|
|
639
|
+
const moveItem = (fromIdx, toIdx) => {
|
|
640
|
+
if (isDisabled || toIdx < 0 || toIdx >= ordered.length)
|
|
641
|
+
return;
|
|
642
|
+
const next = [...ordered];
|
|
643
|
+
const [moved] = next.splice(fromIdx, 1);
|
|
644
|
+
next.splice(toIdx, 0, moved);
|
|
645
|
+
this.handleFieldChange(f.name, next);
|
|
646
|
+
};
|
|
647
|
+
return (h("div", { class: "co-form-ordering", key: f.name, "data-full": f.originalAttrs.full ? 'true' : undefined }, f.label && h("label", { class: "co-form-ordering__label" }, f.label), helperText && h("p", { class: "co-form-ordering__helper" }, helperText), h("div", { class: "co-form-ordering__list", role: "list", "aria-label": f.label }, ordered.map((item, idx) => (h("div", { class: {
|
|
648
|
+
'co-form-ordering__item': true,
|
|
649
|
+
'is-dragging': this.orderingDragIdx === idx,
|
|
650
|
+
'is-drop-target': this.orderingDropIdx === idx && this.orderingDragIdx !== idx,
|
|
651
|
+
}, key: `${f.name}-${idx}`, role: "listitem", draggable: !isDisabled, onDragStart: (ev) => onDragStart(ev, idx), onDragOver: (ev) => onDragOver(ev, idx), onDrop: (ev) => onDrop(ev, idx), onDragEnd: onDragEnd }, h("span", { class: "co-form-ordering__grip", "aria-hidden": "true" }, h("co-icon", { name: "dots-six-vertical", size: "16" })), h("span", { class: "co-form-ordering__num" }, idx + 1), h("span", { class: "co-form-ordering__text" }, item), h("span", { class: "co-form-ordering__actions" }, h("button", { type: "button", class: "co-form-ordering__move-btn", disabled: isDisabled || idx === 0, onClick: () => moveItem(idx, idx - 1), "aria-label": `Move ${item} up` }, h("co-icon", { name: "caret-up", size: "14" })), h("button", { type: "button", class: "co-form-ordering__move-btn", disabled: isDisabled || idx === ordered.length - 1, onClick: () => moveItem(idx, idx + 1), "aria-label": `Move ${item} down` }, h("co-icon", { name: "caret-down", size: "14" })))))))));
|
|
652
|
+
}
|
|
653
|
+
// ── Matching (kind: 'matching') ───────────────────────────────────────────
|
|
654
|
+
renderMatching(f, value) {
|
|
655
|
+
const leftItems = Array.isArray(f.originalAttrs.matchLeft) ? f.originalAttrs.matchLeft : [];
|
|
656
|
+
const rightItems = Array.isArray(f.originalAttrs.matchRight) ? f.originalAttrs.matchRight : [];
|
|
657
|
+
// Value is an object mapping left index → selected right value string.
|
|
658
|
+
const pairs = value && typeof value === 'object' ? value : {};
|
|
659
|
+
const isDisabled = this.disabled || f.disabled;
|
|
660
|
+
const isTouched = !!this.snapshot.touched[f.name];
|
|
661
|
+
const errors = isTouched ? this.snapshot.errors[f.name] || [] : [];
|
|
662
|
+
const helperText = errors[0] || f.helperText;
|
|
663
|
+
const rightOptions = rightItems.map((r) => ({ label: r, value: r }));
|
|
664
|
+
const handleSelect = (leftIdx, selectedValue) => {
|
|
665
|
+
const next = Object.assign(Object.assign({}, pairs), { [String(leftIdx)]: selectedValue });
|
|
666
|
+
this.handleFieldChange(f.name, next);
|
|
667
|
+
};
|
|
668
|
+
return (h("div", { class: "co-form-matching", key: f.name, "data-full": f.originalAttrs.full ? 'true' : undefined }, f.label && h("label", { class: "co-form-matching__label" }, f.label), helperText && h("p", { class: "co-form-matching__helper" }, helperText), h("div", { class: "co-form-matching__list" }, leftItems.map((term, idx) => {
|
|
669
|
+
var _a;
|
|
670
|
+
return (h("div", { class: "co-form-matching__row", key: `${f.name}-${idx}` }, h("span", { class: "co-form-matching__term" }, term), h("co-icon", { name: "arrow-right", size: "16" }), h("co-select", { class: "co-form-matching__select", options: JSON.stringify(rightOptions), value: (_a = pairs[String(idx)]) !== null && _a !== void 0 ? _a : '', placeholder: "Select match\u2026", disabled: isDisabled, onCoChange: (e) => handleSelect(idx, e.detail) })));
|
|
671
|
+
}))));
|
|
672
|
+
}
|
|
532
673
|
static get is() { return "co-form"; }
|
|
533
674
|
static get originalStyleUrls() {
|
|
534
675
|
return {
|
|
@@ -814,6 +955,26 @@ export class CoForm {
|
|
|
814
955
|
"attribute": "hide-footer",
|
|
815
956
|
"defaultValue": "false"
|
|
816
957
|
},
|
|
958
|
+
"validateOn": {
|
|
959
|
+
"type": "string",
|
|
960
|
+
"mutable": false,
|
|
961
|
+
"complexType": {
|
|
962
|
+
"original": "'change' | 'blur' | 'submit'",
|
|
963
|
+
"resolved": "\"blur\" | \"change\" | \"submit\"",
|
|
964
|
+
"references": {}
|
|
965
|
+
},
|
|
966
|
+
"required": false,
|
|
967
|
+
"optional": false,
|
|
968
|
+
"docs": {
|
|
969
|
+
"tags": [],
|
|
970
|
+
"text": "When to run validation: on every change, on blur, or only on submit."
|
|
971
|
+
},
|
|
972
|
+
"getter": false,
|
|
973
|
+
"setter": false,
|
|
974
|
+
"reflect": false,
|
|
975
|
+
"attribute": "validate-on",
|
|
976
|
+
"defaultValue": "'change'"
|
|
977
|
+
},
|
|
817
978
|
"theme": {
|
|
818
979
|
"type": "string",
|
|
819
980
|
"mutable": false,
|
|
@@ -847,7 +1008,9 @@ export class CoForm {
|
|
|
847
1008
|
"snapshot": {},
|
|
848
1009
|
"refStates": {},
|
|
849
1010
|
"themeStyles": {},
|
|
850
|
-
"hasBg": {}
|
|
1011
|
+
"hasBg": {},
|
|
1012
|
+
"orderingDragIdx": {},
|
|
1013
|
+
"orderingDropIdx": {}
|
|
851
1014
|
};
|
|
852
1015
|
}
|
|
853
1016
|
static get events() {
|
|
@@ -190,6 +190,11 @@
|
|
|
190
190
|
background: var(--co-semantic-surface-hover, #f9fafb);
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
+
/* When only the submit/next button is present, push it right */
|
|
194
|
+
.co-form-wizard__nav co-button:only-child {
|
|
195
|
+
margin-left: auto;
|
|
196
|
+
}
|
|
197
|
+
|
|
193
198
|
.co-form-wizard__empty {
|
|
194
199
|
padding: var(--co-spacing-lg, 16px);
|
|
195
200
|
text-align: center;
|
|
@@ -275,6 +280,8 @@
|
|
|
275
280
|
--co-semantic-surface-muted: #2a3142;
|
|
276
281
|
--co-semantic-surface-hover: rgba(255, 255, 255, 0.06);
|
|
277
282
|
--co-semantic-surface-disabled: rgba(255, 255, 255, 0.04);
|
|
283
|
+
--co-semantic-on-primary: #1a1f2b;
|
|
284
|
+
--co-semantic-on-secondary: #f9fafb;
|
|
278
285
|
--co-semantic-text-default: #f9fafb;
|
|
279
286
|
--co-semantic-text-secondary: #9ca3af;
|
|
280
287
|
--co-semantic-text-muted: #6b7280;
|