@prolibu-suite/cobalt-form 0.2.2 → 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.
Files changed (29) hide show
  1. package/dist/cjs/co-form-wizard.cjs.entry.js +40 -11
  2. package/dist/cjs/co-form.cjs.entry.js +1 -1
  3. package/dist/cjs/cobalt-form.cjs.js +1 -1
  4. package/dist/cjs/{index-CLL7Ervz.js → index-Brpri7nS.js} +120 -19
  5. package/dist/cjs/index.cjs.js +146 -5
  6. package/dist/cjs/loader.cjs.js +1 -1
  7. package/dist/cobalt-form/cobalt-form.esm.js +1 -1
  8. package/dist/cobalt-form/index.esm.js +1 -1
  9. package/dist/cobalt-form/p-296094ec.entry.js +1 -0
  10. package/dist/cobalt-form/{p-2168be6b.entry.js → p-95e1cedb.entry.js} +1 -1
  11. package/dist/cobalt-form/{p-CPE0t-C2.js → p-CzvtCEKX.js} +3 -3
  12. package/dist/collection/components/co-form/co-form.css +326 -4
  13. package/dist/collection/components/co-form/co-form.js +167 -4
  14. package/dist/collection/components/co-form-wizard/co-form-wizard.css +5 -0
  15. package/dist/collection/components/co-form-wizard/co-form-wizard.js +92 -10
  16. package/dist/components/co-form-wizard.js +1 -1
  17. package/dist/components/index.js +7 -7
  18. package/dist/esm/co-form-wizard.entry.js +40 -11
  19. package/dist/esm/co-form.entry.js +1 -1
  20. package/dist/esm/cobalt-form.js +1 -1
  21. package/dist/esm/{index-CPE0t-C2.js → index-CzvtCEKX.js} +120 -19
  22. package/dist/esm/index.js +146 -5
  23. package/dist/esm/loader.js +1 -1
  24. package/dist/types/components/co-form/co-form.d.ts +7 -0
  25. package/dist/types/components/co-form-wizard/co-form-wizard.d.ts +15 -1
  26. package/dist/types/components.d.ts +33 -0
  27. package/dist/types/jsx-cobalt.d.ts +3 -0
  28. package/package.json +3 -3
  29. package/dist/cobalt-form/p-0a2a284f.entry.js +0 -1
package/dist/esm/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { r as registerInstance, c as createEvent, h, H as Host, g as getElement } from './index-C1670_IO.js';
2
- import { n as normalizeForValidation, r as resolveTheme, t as themeToStyles, d as createForm, f as describeFields, g as createInlineValidator } from './index-CPE0t-C2.js';
2
+ import { n as normalizeForValidation, r as resolveTheme, t as themeToStyles, d as createForm, f as describeFields, g as createInlineValidator } from './index-CzvtCEKX.js';
3
3
 
4
- const coFormCss = () => `:host{display:block;font-family:var(--co-font-family-primary, sans-serif)}.co-form-layout{display:grid;gap:var(--co-spacing-lg, 16px)}.co-form-layout--gap-sm{gap:var(--co-spacing-sm, 8px)}.co-form-layout--gap-md{gap:var(--co-spacing-md, 12px)}.co-form-layout--gap-lg{gap:var(--co-spacing-lg, 16px)}.co-form-layout--grid{grid-template-columns:repeat(2, minmax(0, 1fr))}.co-form-layout--stack{grid-template-columns:1fr}@media (max-width: 640px){.co-form-layout--grid{grid-template-columns:1fr !important}}.co-form-layout>[data-full="true"],.co-form-layout .co-form-section,.co-form-layout .co-form-repeater{grid-column:1 / -1}.co-form-footer--start{justify-content:flex-start}.co-form-footer--end{justify-content:flex-end}.co-form-footer--center{justify-content:center}.co-form-footer--between{justify-content:space-between}.co-form-footer--stretch{justify-content:stretch}.co-form-footer--stretch>*{flex:1}.co-form-footer{margin-top:var(--co-spacing-lg, 16px);display:flex;justify-content:flex-end;gap:var(--co-spacing-sm, 8px)}:host{display:block;background-repeat:no-repeat}form[data-has-bg]{max-width:720px;margin:var(--co-spacing-3xl, 32px) auto;padding:var(--co-spacing-2xl, 24px);background:var(--co-semantic-surface-page, #fff);border-radius:var(--co-border-radius-sm, 12px);box-shadow:0 4px 24px rgba(0, 0, 0, 0.08)}form[data-theme="dark"][data-has-bg]{background:#232936;color:#f9fafb;box-shadow:0 4px 24px rgba(0, 0, 0, 0.4)}form[data-theme="dark"]{--co-semantic-surface-page:#1a1f2b;--co-semantic-surface-secondary:#1a1f2b;--co-semantic-surface-primary:#ffffff;--co-semantic-surface-muted:#2a3142;--co-semantic-surface-hover:rgba(255, 255, 255, 0.06);--co-semantic-surface-disabled:rgba(255, 255, 255, 0.04);--co-semantic-on-primary:#1a1f2b;--co-semantic-on-secondary:#f9fafb;--co-semantic-text-default:#f9fafb;--co-semantic-text-secondary:#9ca3af;--co-semantic-text-muted:#6b7280;--co-semantic-text-disabled:#4b5563;--co-semantic-border-default:rgba(255, 255, 255, 0.12);--co-semantic-border-subtle:rgba(255, 255, 255, 0.14);--co-semantic-border-strong:rgba(255, 255, 255, 0.25);--co-semantic-border-focus:rgba(255, 255, 255, 0.25);--co-semantic-border-focus-ring:rgba(255, 255, 255, 0.1);color:var(--co-semantic-text-default)}form[data-density="compact"] .co-form-layout{gap:var(--co-spacing-sm, 8px)}form[data-density="compact"] .co-form-footer{margin-top:var(--co-spacing-sm, 8px)}form[data-appearance="flat"] .co-form-section{border-top:0;padding-top:0}form[data-appearance="flat"][data-has-bg]{background:transparent;box-shadow:none;padding:0}form[data-hide-header] .co-form-layout>slot[name="header"]{display:none}:host{--co-form-header-bg-applied:var(--co-form-header-bg, transparent)}.co-form-section{grid-column:1 / -1;border-top:1px solid var(--co-semantic-border-default, #e5e7eb);padding-top:var(--co-spacing-md, 12px);margin-top:var(--co-spacing-sm, 8px)}.co-form-section__title{margin:0 0 var(--co-spacing-xxs, 2px);font-size:var(--co-font-size-16, 16px);font-weight:600;color:var(--co-semantic-text-default, #111)}.co-form-section__desc{margin:0;font-size:var(--co-font-size-12, 12px);color:var(--co-semantic-text-secondary, #6b7280)}.co-form-repeater{grid-column:1 / -1;display:flex;flex-direction:column;gap:var(--co-spacing-sm, 8px)}.co-form-repeater__label{font-size:var(--co-font-size-14, 14px);font-weight:500;color:var(--co-semantic-text-default, #111)}.co-form-repeater__row{display:flex;align-items:flex-start;gap:var(--co-spacing-sm, 8px);padding:var(--co-spacing-sm, 8px);border:1px solid var(--co-semantic-border-default, #e5e7eb);border-radius:var(--co-border-radius-xs, 8px);background:var(--co-semantic-surface-primary, #fff)}.co-form-repeater__fields{flex:1;display:grid;grid-template-columns:repeat(auto-fit, minmax(160px, 1fr));gap:var(--co-spacing-sm, 8px)}`;
4
+ const coFormCss = () => `:host{display:block;font-family:var(--co-font-family-primary, sans-serif)}.co-form-layout{display:grid;gap:var(--co-spacing-lg, 16px)}.co-form-layout--gap-sm{gap:var(--co-spacing-sm, 8px)}.co-form-layout--gap-md{gap:var(--co-spacing-md, 12px)}.co-form-layout--gap-lg{gap:var(--co-spacing-lg, 16px)}.co-form-layout--grid{grid-template-columns:repeat(2, minmax(0, 1fr))}.co-form-layout--stack{grid-template-columns:1fr}@media (max-width: 640px){.co-form-layout--grid{grid-template-columns:1fr !important}}.co-form-layout>[data-full="true"],.co-form-layout .co-form-section,.co-form-layout .co-form-repeater{grid-column:1 / -1}.co-form-footer--start{justify-content:flex-start}.co-form-footer--end{justify-content:flex-end}.co-form-footer--center{justify-content:center}.co-form-footer--between{justify-content:space-between}.co-form-footer--stretch{justify-content:stretch}.co-form-footer--stretch>*{flex:1}.co-form-footer{margin-top:var(--co-spacing-lg, 16px);display:flex;justify-content:flex-end;gap:var(--co-spacing-sm, 8px)}:host{display:block;background-repeat:no-repeat}form[data-has-bg]{max-width:720px;margin:var(--co-spacing-3xl, 32px) auto;padding:var(--co-spacing-2xl, 24px);background:var(--co-semantic-surface-page, #fff);border-radius:var(--co-border-radius-sm, 12px);box-shadow:var(--co-shadow-lg, 0 4px 24px var(--co-color-opacity-negro-8))}form[data-theme="dark"][data-has-bg]{background:var(--co-semantic-surface-page);color:var(--co-semantic-text-default);box-shadow:0 4px 24px var(--co-color-opacity-negro-50)}form[data-theme="dark"]{--co-semantic-surface-page:#1a1f2b;--co-semantic-surface-secondary:#1a1f2b;--co-semantic-surface-primary:#ffffff;--co-semantic-surface-muted:#2a3142;--co-semantic-surface-hover:rgba(255, 255, 255, 0.06);--co-semantic-surface-disabled:rgba(255, 255, 255, 0.04);--co-semantic-on-primary:#1a1f2b;--co-semantic-on-secondary:#f9fafb;--co-semantic-text-default:#f9fafb;--co-semantic-text-secondary:#9ca3af;--co-semantic-text-muted:#6b7280;--co-semantic-text-disabled:#4b5563;--co-semantic-border-default:rgba(255, 255, 255, 0.12);--co-semantic-border-subtle:rgba(255, 255, 255, 0.14);--co-semantic-border-strong:rgba(255, 255, 255, 0.25);--co-semantic-border-focus:rgba(255, 255, 255, 0.25);--co-semantic-border-focus-ring:rgba(255, 255, 255, 0.1);color:var(--co-semantic-text-default)}form[data-density="compact"] .co-form-layout{gap:var(--co-spacing-sm, 8px)}form[data-density="compact"] .co-form-footer{margin-top:var(--co-spacing-sm, 8px)}form[data-appearance="flat"] .co-form-section{border-top:0;padding-top:0}form[data-appearance="flat"][data-has-bg]{background:transparent;box-shadow:none;padding:0}form[data-hide-header] .co-form-layout>slot[name="header"]{display:none}:host{--co-form-header-bg-applied:var(--co-form-header-bg, transparent)}.co-form-section{grid-column:1 / -1;border-top:1px solid var(--co-semantic-border-default, #e5e7eb);padding-top:var(--co-spacing-md, 12px);margin-top:var(--co-spacing-sm, 8px)}.co-form-section__title{margin:0 0 var(--co-spacing-xxs, 2px);font-size:var(--co-font-size-16, 16px);font-weight:600;color:var(--co-semantic-text-default, #111)}.co-form-section__desc{margin:0;font-size:var(--co-font-size-12, 12px);color:var(--co-semantic-text-secondary, #6b7280)}.co-form-repeater{grid-column:1 / -1;display:flex;flex-direction:column;gap:var(--co-spacing-sm, 8px)}.co-form-repeater__label{font-size:var(--co-font-size-14, 14px);font-weight:500;color:var(--co-semantic-text-default, #111)}.co-form-repeater__row{display:flex;align-items:flex-start;gap:var(--co-spacing-sm, 8px);padding:var(--co-spacing-sm, 8px);border:1px solid var(--co-semantic-border-default, #e5e7eb);border-radius:var(--co-border-radius-xs, 8px);background:var(--co-semantic-surface-primary, #fff)}.co-form-repeater__fields{flex:1;display:grid;grid-template-columns:repeat(auto-fit, minmax(160px, 1fr));gap:var(--co-spacing-sm, 8px)}.co-form-textarea-wrap{display:flex;flex-direction:column;gap:var(--co-spacing-xxs, 2px)}.co-form-textarea-wrap__label{font-size:var(--co-font-size-14, 14px);font-weight:500;color:var(--co-semantic-text-default, #111)}.co-form-textarea{width:100%;min-height:100px;padding:var(--co-spacing-sm, 8px) var(--co-spacing-md, 12px);font-family:var(--co-font-family-primary, sans-serif);font-size:var(--co-font-size-14, 14px);color:var(--co-semantic-text-default, #111);background:var(--co-semantic-surface-secondary, #f7f6f0);border:1px solid var(--co-semantic-border-default, #e5e7eb);border-radius:var(--co-border-radius-xxs, 4px);resize:vertical;outline:none;transition:border-color 120ms;box-sizing:border-box}.co-form-textarea:focus{border-color:var(--co-color-primary-azul, #2563eb)}.co-form-textarea--error{border-color:var(--co-color-status-error, #AA2E1B)}.co-form-textarea:disabled{opacity:0.5;cursor:not-allowed}.co-form-textarea-wrap__helper{margin:0;font-size:var(--co-font-size-12, 12px);color:var(--co-semantic-text-secondary, #6b7280)}.co-form-textarea-wrap__helper[data-status="error"]{color:var(--co-color-status-error, #AA2E1B)}co-number-field{max-width:240px}.co-form-ordering{grid-column:1 / -1;display:flex;flex-direction:column;gap:var(--co-spacing-xs, 4px)}.co-form-ordering__label{font-size:var(--co-font-size-14, 14px);font-weight:500;color:var(--co-semantic-text-default, #111);margin-bottom:var(--co-spacing-xs, 4px)}.co-form-ordering__helper{margin:0 0 var(--co-spacing-xs, 4px);font-size:var(--co-font-size-12, 12px);color:var(--co-semantic-text-secondary, #6b7280)}.co-form-ordering__list{display:flex;flex-direction:column;gap:var(--co-spacing-xs, 4px)}.co-form-ordering__item{display:flex;align-items:center;gap:var(--co-spacing-sm, 8px);padding:var(--co-spacing-sm, 8px) var(--co-spacing-md, 12px);border:1px solid var(--co-semantic-border-default, #e5e7eb);border-radius:var(--co-border-radius-xxs, 4px);background:var(--co-semantic-surface-secondary, #f7f6f0);transition:border-color 120ms, box-shadow 120ms, opacity 120ms;cursor:grab;user-select:none}.co-form-ordering__item:hover{border-color:var(--co-color-primary-azul, #2563eb)}.co-form-ordering__item.is-dragging{opacity:0.4;cursor:grabbing}.co-form-ordering__item.is-drop-target{border-color:var(--co-color-primary-azul, #2563eb);box-shadow:0 -2px 0 0 var(--co-color-primary-azul, #2563eb)}.co-form-ordering__grip{display:flex;align-items:center;color:var(--co-semantic-text-muted, #9ca3af);flex-shrink:0;cursor:grab}.co-form-ordering__num{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:var(--co-border-radius-full, 9999px);background:color-mix(in srgb, var(--co-color-primary-azul, #2563eb) 10%, transparent);color:var(--co-color-primary-azul, #2563eb);font-size:12px;font-weight:700;flex-shrink:0}.co-form-ordering__text{flex:1;font-size:var(--co-font-size-14, 14px);color:var(--co-semantic-text-default, #111)}.co-form-ordering__actions{display:flex;flex-direction:column;gap:1px;flex-shrink:0}.co-form-ordering__move-btn{display:flex;align-items:center;justify-content:center;width:22px;height:16px;padding:0;border:none;background:transparent;color:var(--co-semantic-text-muted, #9ca3af);cursor:pointer;border-radius:var(--co-border-radius-xxs, 4px)}.co-form-ordering__move-btn:hover:not(:disabled){background:var(--co-semantic-surface-hover, #f3f4f6);color:var(--co-semantic-text-default, #111)}.co-form-ordering__move-btn:disabled{opacity:0.3;cursor:not-allowed}.co-form-matching{grid-column:1 / -1;display:flex;flex-direction:column;gap:var(--co-spacing-xs, 4px)}.co-form-matching__label{font-size:var(--co-font-size-14, 14px);font-weight:500;color:var(--co-semantic-text-default, #111);margin-bottom:var(--co-spacing-xs, 4px)}.co-form-matching__helper{margin:0 0 var(--co-spacing-xs, 4px);font-size:var(--co-font-size-12, 12px);color:var(--co-semantic-text-secondary, #6b7280)}.co-form-matching__list{display:flex;flex-direction:column;gap:var(--co-spacing-sm, 8px)}.co-form-matching__row{display:grid;grid-template-columns:1fr 20px 1fr;gap:var(--co-spacing-sm, 8px);align-items:center}.co-form-matching__term{font-size:var(--co-font-size-14, 14px);font-weight:500;color:var(--co-semantic-text-default, #111);padding:var(--co-spacing-sm, 8px) var(--co-spacing-md, 12px);border:1px solid var(--co-semantic-border-default, #e5e7eb);border-radius:var(--co-border-radius-xxs, 4px);background:var(--co-semantic-surface-secondary, #f7f6f0)}.co-form-matching__row co-icon{color:var(--co-semantic-text-muted, #9ca3af);justify-self:center}.co-form-matching__select{min-width:0}.co-form-image-choice{grid-column:1 / -1;display:flex;flex-direction:column;gap:var(--co-spacing-xs, 4px)}.co-form-image-choice__label{font-size:var(--co-font-size-14, 14px);font-weight:500;color:var(--co-semantic-text-default, #111);margin-bottom:var(--co-spacing-xs, 4px)}.co-form-image-choice__helper{margin:0 0 var(--co-spacing-xs, 4px);font-size:var(--co-font-size-12, 12px);color:var(--co-semantic-text-secondary, #6b7280)}.co-form-image-choice__helper[data-status="error"]{color:var(--co-color-status-error, #AA2E1B)}.co-form-image-choice__grid{display:grid;grid-template-columns:repeat(auto-fill, minmax(140px, 1fr));gap:var(--co-spacing-sm, 8px)}.co-form-image-choice__card{display:flex;flex-direction:column;border:2px solid var(--co-semantic-border-default, #e5e7eb);border-radius:var(--co-border-radius-xs, 8px);overflow:hidden;cursor:pointer;transition:border-color 120ms, box-shadow 120ms;background:var(--co-semantic-surface-secondary, #f7f6f0)}.co-form-image-choice__card:hover:not(.is-disabled){border-color:var(--co-color-primary-azul, #2563eb)}.co-form-image-choice__card.is-selected{border-color:var(--co-color-primary-azul, #2563eb);box-shadow:0 0 0 2px color-mix(in srgb, var(--co-color-primary-azul, #2563eb) 20%, transparent)}.co-form-image-choice__card.is-disabled{opacity:0.5;cursor:not-allowed}.co-form-image-choice__img-wrap{width:100%;height:100px;display:flex;align-items:center;justify-content:center;overflow:hidden;color:var(--co-semantic-text-muted, #9ca3af)}.co-form-image-choice__img{width:100%;height:100%;object-fit:cover}.co-form-image-choice__footer{display:flex;align-items:center;gap:var(--co-spacing-xs, 4px);padding:var(--co-spacing-xs, 4px) var(--co-spacing-sm, 8px);border-top:1px solid var(--co-semantic-border-default, #e5e7eb);min-height:32px}.co-form-image-choice__check{flex-shrink:0;display:flex;color:var(--co-semantic-text-muted, #9ca3af)}.co-form-image-choice__card.is-selected .co-form-image-choice__check{color:var(--co-color-primary-azul, #2563eb)}.co-form-image-choice__text{font-size:var(--co-font-size-13, 13px);color:var(--co-semantic-text-default, #111);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}`;
5
5
 
6
6
  const PAGE_SIZE = 20;
7
7
  function safeParse(json) {
@@ -43,6 +43,8 @@ const CoForm = class {
43
43
  this.footerAlign = 'end';
44
44
  /** Hide the entire footer (use when embedded in a wizard or custom shell). */
45
45
  this.hideFooter = false;
46
+ /** When to run validation: on every change, on blur, or only on submit. */
47
+ this.validateOn = 'change';
46
48
  this.snapshot = {
47
49
  values: {},
48
50
  errors: {},
@@ -118,6 +120,9 @@ const CoForm = class {
118
120
  }
119
121
  this.handleFieldChange(f.name, value);
120
122
  };
123
+ // ── Ordering (kind: 'ordering') ───────────────────────────────────────────
124
+ this.orderingDragIdx = null;
125
+ this.orderingDropIdx = null;
121
126
  }
122
127
  componentWillLoad() {
123
128
  this.rebuildController();
@@ -185,6 +190,7 @@ const CoForm = class {
185
190
  this.controller = createForm({
186
191
  schema: { instance },
187
192
  initialValues,
193
+ validateOn: this.validateOn,
188
194
  });
189
195
  this.fields = describeFields(instance.formSchema.properties);
190
196
  this.snapshot = this.controller.state;
@@ -445,8 +451,14 @@ const CoForm = class {
445
451
  switch (f.kind) {
446
452
  case 'text':
447
453
  return (h("co-input", Object.assign({}, common, { value: value !== null && value !== void 0 ? value : '', onCoInput: (e) => this.handleFieldChange(f.name, e.detail) })));
448
- case 'textarea':
449
- return (h("co-input", Object.assign({}, common, { multiline: true, value: value !== null && value !== void 0 ? value : '', onCoInput: (e) => this.handleFieldChange(f.name, e.detail) })));
454
+ case 'textarea': {
455
+ const textareaId = `co-form-${f.name}`;
456
+ const helperId = helperText ? `co-form-${f.name}-helper` : undefined;
457
+ 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: {
458
+ 'co-form-textarea': true,
459
+ 'co-form-textarea--error': status === 'error',
460
+ }, 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)));
461
+ }
450
462
  case 'html':
451
463
  return (h("co-input", Object.assign({}, common, { multiline: true, value: value !== null && value !== void 0 ? value : '', onCoInput: (e) => this.handleFieldChange(f.name, e.detail) })));
452
464
  case 'date':
@@ -457,16 +469,28 @@ const CoForm = class {
457
469
  return (h("co-switch", Object.assign({}, common, { checked: !!value, onCoChange: (e) => this.handleFieldChange(f.name, e.detail) })));
458
470
  case 'select':
459
471
  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) })));
472
+ case 'radio':
473
+ 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) })));
474
+ case 'checkbox':
475
+ 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) })));
460
476
  case 'rating':
461
477
  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) })));
462
478
  case 'slider':
463
479
  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) })));
464
480
  case 'color':
465
- return (h("co-input", Object.assign({}, common, { type: "color", value: typeof value === 'string' ? value : '#000000', onCoInput: (e) => this.handleFieldChange(f.name, e.detail) })));
481
+ 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) })));
466
482
  case 'section':
467
483
  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)));
484
+ case 'phone':
485
+ 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) })));
468
486
  case 'file':
469
487
  return (h("co-input", Object.assign({}, common, { type: "file", onCoInput: (e) => this.handleFieldChange(f.name, e.detail) })));
488
+ case 'ordering':
489
+ return this.renderOrdering(f, value);
490
+ case 'matching':
491
+ return this.renderMatching(f, value);
492
+ case 'image-choice':
493
+ return this.renderImageChoice(f, value);
470
494
  case 'array':
471
495
  return this.renderRepeater(f, value);
472
496
  case 'ref': {
@@ -519,6 +543,123 @@ const CoForm = class {
519
543
  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) }));
520
544
  })), 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 })));
521
545
  }
546
+ // ── Image Choice (kind: 'image-choice') ────────────────────────────────
547
+ renderImageChoice(f, value) {
548
+ const opts = Array.isArray(f.originalAttrs.enum) ? f.originalAttrs.enum : [];
549
+ const images = Array.isArray(f.originalAttrs.optionImages) ? f.originalAttrs.optionImages : [];
550
+ const isMulti = !!f.originalAttrs.multiSelect;
551
+ const isDisabled = this.disabled || f.disabled;
552
+ const isTouched = !!this.snapshot.touched[f.name];
553
+ const errors = isTouched ? this.snapshot.errors[f.name] || [] : [];
554
+ const helperText = errors[0] || f.helperText;
555
+ // For single select: value is a string (option text or index).
556
+ // For multi select: value is an array.
557
+ const selected = isMulti
558
+ ? (Array.isArray(value) ? value : [])
559
+ : (value != null && value !== '' ? [String(value)] : []);
560
+ const toggle = (opt) => {
561
+ if (isDisabled)
562
+ return;
563
+ if (isMulti) {
564
+ const next = selected.includes(opt)
565
+ ? selected.filter((s) => s !== opt)
566
+ : [...selected, opt];
567
+ this.handleFieldChange(f.name, next);
568
+ }
569
+ else {
570
+ this.handleFieldChange(f.name, opt);
571
+ }
572
+ };
573
+ 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) => {
574
+ const isSelected = selected.includes(opt);
575
+ const imgSrc = images[idx] || '';
576
+ return (h("div", { class: `co-form-image-choice__card ${isSelected ? 'is-selected' : ''} ${isDisabled ? 'is-disabled' : ''}`, key: `${f.name}-${idx}`, onClick: () => toggle(opt), onKeyDown: (e) => {
577
+ if (e.key === 'Enter' || e.key === ' ') {
578
+ e.preventDefault();
579
+ toggle(opt);
580
+ }
581
+ }, 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
582
+ ? h("img", { src: imgSrc, alt: opt, class: "co-form-image-choice__img" })
583
+ : 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))));
584
+ }))));
585
+ }
586
+ renderOrdering(f, value) {
587
+ const items = Array.isArray(f.originalAttrs.enum) ? f.originalAttrs.enum : [];
588
+ // Value is the user's ordering: an array of item strings in the order they chose.
589
+ const ordered = Array.isArray(value) ? value : [...items];
590
+ const isDisabled = this.disabled || f.disabled;
591
+ const isTouched = !!this.snapshot.touched[f.name];
592
+ const errors = isTouched ? this.snapshot.errors[f.name] || [] : [];
593
+ const helperText = errors[0] || f.helperText;
594
+ const onDragStart = (ev, idx) => {
595
+ if (isDisabled)
596
+ return;
597
+ this.orderingDragIdx = idx;
598
+ if (ev.dataTransfer) {
599
+ ev.dataTransfer.effectAllowed = 'move';
600
+ ev.dataTransfer.setData('text/plain', String(idx));
601
+ }
602
+ };
603
+ const onDragOver = (ev, idx) => {
604
+ if (this.orderingDragIdx === null)
605
+ return;
606
+ ev.preventDefault();
607
+ if (ev.dataTransfer)
608
+ ev.dataTransfer.dropEffect = 'move';
609
+ this.orderingDropIdx = idx;
610
+ };
611
+ const onDrop = (ev, idx) => {
612
+ ev.preventDefault();
613
+ const fromIdx = this.orderingDragIdx;
614
+ this.orderingDragIdx = null;
615
+ this.orderingDropIdx = null;
616
+ if (fromIdx === null || fromIdx === idx)
617
+ return;
618
+ const next = [...ordered];
619
+ const [moved] = next.splice(fromIdx, 1);
620
+ // Adjust target for downward moves: removing fromIdx shifts later indices down by 1
621
+ const insertAt = fromIdx < idx ? idx - 1 : idx;
622
+ next.splice(insertAt, 0, moved);
623
+ this.handleFieldChange(f.name, next);
624
+ };
625
+ const onDragEnd = () => {
626
+ this.orderingDragIdx = null;
627
+ this.orderingDropIdx = null;
628
+ };
629
+ const moveItem = (fromIdx, toIdx) => {
630
+ if (isDisabled || toIdx < 0 || toIdx >= ordered.length)
631
+ return;
632
+ const next = [...ordered];
633
+ const [moved] = next.splice(fromIdx, 1);
634
+ next.splice(toIdx, 0, moved);
635
+ this.handleFieldChange(f.name, next);
636
+ };
637
+ 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: {
638
+ 'co-form-ordering__item': true,
639
+ 'is-dragging': this.orderingDragIdx === idx,
640
+ 'is-drop-target': this.orderingDropIdx === idx && this.orderingDragIdx !== idx,
641
+ }, 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" })))))))));
642
+ }
643
+ // ── Matching (kind: 'matching') ───────────────────────────────────────────
644
+ renderMatching(f, value) {
645
+ const leftItems = Array.isArray(f.originalAttrs.matchLeft) ? f.originalAttrs.matchLeft : [];
646
+ const rightItems = Array.isArray(f.originalAttrs.matchRight) ? f.originalAttrs.matchRight : [];
647
+ // Value is an object mapping left index → selected right value string.
648
+ const pairs = value && typeof value === 'object' ? value : {};
649
+ const isDisabled = this.disabled || f.disabled;
650
+ const isTouched = !!this.snapshot.touched[f.name];
651
+ const errors = isTouched ? this.snapshot.errors[f.name] || [] : [];
652
+ const helperText = errors[0] || f.helperText;
653
+ const rightOptions = rightItems.map((r) => ({ label: r, value: r }));
654
+ const handleSelect = (leftIdx, selectedValue) => {
655
+ const next = Object.assign(Object.assign({}, pairs), { [String(leftIdx)]: selectedValue });
656
+ this.handleFieldChange(f.name, next);
657
+ };
658
+ 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) => {
659
+ var _a;
660
+ 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) })));
661
+ }))));
662
+ }
522
663
  get host() { return getElement(this); }
523
664
  static get watchers() { return {
524
665
  "schema": [{
@@ -5,7 +5,7 @@ import { g as globalScripts } from './app-globals-DQuL1Twl.js';
5
5
  const defineCustomElements = async (win, options) => {
6
6
  if (typeof window === 'undefined') return undefined;
7
7
  await globalScripts();
8
- return bootstrapLazy([["co-form",[[260,"co-form",{"schema":[1],"initialValues":[1,"initial-values"],"schemaInstance":[16],"refResolver":[16],"locale":[1],"layout":[1],"excludeFields":[1,"exclude-fields"],"disabled":[4],"readOnly":[4,"read-only"],"columns":[2],"gap":[1],"footerAlign":[1,"footer-align"],"hideFooter":[4,"hide-footer"],"theme":[1],"snapshot":[32],"refStates":[32],"themeStyles":[32],"hasBg":[32],"setValue":[64],"getValue":[64],"touch":[64],"validateAndCollect":[64]},null,{"schema":[{"onSchemaChange":0}],"schemaInstance":[{"onSchemaChange":0}],"locale":[{"onSchemaChange":0}],"theme":[{"onThemeChange":0}]}]]],["co-form-wizard",[[260,"co-form-wizard",{"schema":[1],"initialValues":[1,"initial-values"],"locale":[1],"layout":[1],"columns":[2],"theme":[1],"currentIndex":[32],"values":[32],"finalScore":[32],"themeStyles":[32],"hasBg":[32]},null,{"schema":[{"onSchemaChange":0}],"theme":[{"onThemeChange":0}]}]]]], options);
8
+ return bootstrapLazy([["co-form",[[260,"co-form",{"schema":[1],"initialValues":[1,"initial-values"],"schemaInstance":[16],"refResolver":[16],"locale":[1],"layout":[1],"excludeFields":[1,"exclude-fields"],"disabled":[4],"readOnly":[4,"read-only"],"columns":[2],"gap":[1],"footerAlign":[1,"footer-align"],"hideFooter":[4,"hide-footer"],"validateOn":[1,"validate-on"],"theme":[1],"snapshot":[32],"refStates":[32],"themeStyles":[32],"hasBg":[32],"orderingDragIdx":[32],"orderingDropIdx":[32],"setValue":[64],"getValue":[64],"touch":[64],"validateAndCollect":[64]},null,{"schema":[{"onSchemaChange":0}],"schemaInstance":[{"onSchemaChange":0}],"locale":[{"onSchemaChange":0}],"theme":[{"onThemeChange":0}]}]]],["co-form-wizard",[[260,"co-form-wizard",{"schema":[1],"initialValues":[1,"initial-values"],"locale":[1],"layout":[1],"columns":[2],"theme":[1],"validateOn":[1,"validate-on"],"labels":[1],"currentIndex":[32],"values":[32],"finalScore":[32],"themeStyles":[32],"hasBg":[32]},null,{"schema":[{"onSchemaChange":0}],"theme":[{"onThemeChange":0}]}]]]], options);
9
9
  };
10
10
 
11
11
  export { defineCustomElements };
@@ -45,6 +45,8 @@ export declare class CoForm {
45
45
  footerAlign: 'start' | 'end' | 'center' | 'between' | 'stretch';
46
46
  /** Hide the entire footer (use when embedded in a wizard or custom shell). */
47
47
  hideFooter: boolean;
48
+ /** When to run validation: on every change, on blur, or only on submit. */
49
+ validateOn: 'change' | 'blur' | 'submit';
48
50
  /**
49
51
  * Theme overrides. JSON string OR a ThemeSpec assigned as a JS property.
50
52
  * Applied as scoped CSS custom properties on the host so global tokens are
@@ -137,4 +139,9 @@ export declare class CoForm {
137
139
  * Values are stored as an array of objects.
138
140
  */
139
141
  private renderRepeater;
142
+ private renderImageChoice;
143
+ private orderingDragIdx;
144
+ private orderingDropIdx;
145
+ private renderOrdering;
146
+ private renderMatching;
140
147
  }
@@ -1,5 +1,5 @@
1
- import { EventEmitter } from '../../stencil-public-runtime';
2
1
  import { type PageDefinition, type ScoreResult } from '@prolibu-suite/cobalt-form-core';
2
+ import { EventEmitter } from '../../stencil-public-runtime';
3
3
  /**
4
4
  * Multi-page wrapper around `<co-form>`. Consumes a paged schema (or a flat
5
5
  * one, which it auto-wraps as a single page) and renders one page at a time
@@ -30,6 +30,14 @@ export declare class CoFormWizard {
30
30
  * here so authors can ship a single bundled schema.
31
31
  */
32
32
  theme?: string;
33
+ /** When to run validation. Forwarded to each page's `<co-form>`. */
34
+ validateOn: 'change' | 'blur' | 'submit';
35
+ /**
36
+ * UI labels as a JSON string. Allows consumers to override any label
37
+ * for i18n without coupling the component to a specific i18n library.
38
+ * Pass a partial object — unset keys fall back to English defaults.
39
+ */
40
+ labels?: string;
33
41
  coSubmit: EventEmitter<{
34
42
  values: Record<string, any>;
35
43
  score?: ScoreResult;
@@ -38,6 +46,10 @@ export declare class CoFormWizard {
38
46
  index: number;
39
47
  page: PageDefinition;
40
48
  }>;
49
+ coChange: EventEmitter<{
50
+ name: string;
51
+ value: any;
52
+ }>;
41
53
  private currentIndex;
42
54
  private values;
43
55
  private finalScore;
@@ -50,6 +62,7 @@ export declare class CoFormWizard {
50
62
  private hasBg;
51
63
  private paged;
52
64
  private currentFormEl;
65
+ private get mergedLabels();
53
66
  componentWillLoad(): void;
54
67
  onSchemaChange(): void;
55
68
  onThemeChange(): void;
@@ -74,6 +87,7 @@ export declare class CoFormWizard {
74
87
  */
75
88
  private get activePages();
76
89
  private get currentPage();
90
+ private emitPageChange;
77
91
  private commitCurrentPage;
78
92
  private handleNext;
79
93
  private handlePrev;
@@ -100,6 +100,11 @@ export namespace Components {
100
100
  * Validate and return the current values. Used by `<co-form-wizard>` to commit a page before advancing. If validation fails, marks all fields touched (so errors render) and returns `valid: false`.
101
101
  */
102
102
  "validateAndCollect": () => Promise<{ valid: boolean; values: Record<string, any>; }>;
103
+ /**
104
+ * When to run validation: on every change, on blur, or only on submit.
105
+ * @default 'change'
106
+ */
107
+ "validateOn": 'change' | 'blur' | 'submit';
103
108
  }
104
109
  /**
105
110
  * Multi-page wrapper around `<co-form>`. Consumes a paged schema (or a flat
@@ -119,6 +124,10 @@ export namespace Components {
119
124
  * Initial values across all pages, JSON-encoded.
120
125
  */
121
126
  "initialValues"?: string;
127
+ /**
128
+ * UI labels as a JSON string. Allows consumers to override any label for i18n without coupling the component to a specific i18n library. Pass a partial object — unset keys fall back to English defaults.
129
+ */
130
+ "labels"?: string;
122
131
  /**
123
132
  * Layout passed to each page's <co-form>.
124
133
  * @default 'grid'
@@ -137,6 +146,11 @@ export namespace Components {
137
146
  * Theme overrides. Forwarded to each page's `<co-form>`. The wizard itself reads `theme` from the parsed paged schema if not supplied here so authors can ship a single bundled schema.
138
147
  */
139
148
  "theme"?: string;
149
+ /**
150
+ * When to run validation. Forwarded to each page's `<co-form>`.
151
+ * @default 'change'
152
+ */
153
+ "validateOn": 'change' | 'blur' | 'submit';
140
154
  }
141
155
  }
142
156
  export interface CoFormCustomEvent<T> extends CustomEvent<T> {
@@ -181,6 +195,7 @@ declare global {
181
195
  interface HTMLCoFormWizardElementEventMap {
182
196
  "coSubmit": { values: Record<string, any>; score?: ScoreResult };
183
197
  "coPageChange": { index: number; page: PageDefinition };
198
+ "coChange": { name: string; value: any };
184
199
  }
185
200
  /**
186
201
  * Multi-page wrapper around `<co-form>`. Consumes a paged schema (or a flat
@@ -300,6 +315,11 @@ declare namespace LocalJSX {
300
315
  * Theme overrides. JSON string OR a ThemeSpec assigned as a JS property. Applied as scoped CSS custom properties on the host so global tokens are never touched. See `@prolibu-suite/cobalt-form-core` `resolveTheme` for accepted shape and defaults.
301
316
  */
302
317
  "theme"?: string | ThemeSpec;
318
+ /**
319
+ * When to run validation: on every change, on blur, or only on submit.
320
+ * @default 'change'
321
+ */
322
+ "validateOn"?: 'change' | 'blur' | 'submit';
303
323
  }
304
324
  /**
305
325
  * Multi-page wrapper around `<co-form>`. Consumes a paged schema (or a flat
@@ -319,6 +339,10 @@ declare namespace LocalJSX {
319
339
  * Initial values across all pages, JSON-encoded.
320
340
  */
321
341
  "initialValues"?: string;
342
+ /**
343
+ * UI labels as a JSON string. Allows consumers to override any label for i18n without coupling the component to a specific i18n library. Pass a partial object — unset keys fall back to English defaults.
344
+ */
345
+ "labels"?: string;
322
346
  /**
323
347
  * Layout passed to each page's <co-form>.
324
348
  * @default 'grid'
@@ -329,6 +353,7 @@ declare namespace LocalJSX {
329
353
  * @default 'es'
330
354
  */
331
355
  "locale"?: 'en' | 'es' | 'pt';
356
+ "onCoChange"?: (event: CoFormWizardCustomEvent<{ name: string; value: any }>) => void;
332
357
  "onCoPageChange"?: (event: CoFormWizardCustomEvent<{ index: number; page: PageDefinition }>) => void;
333
358
  "onCoSubmit"?: (event: CoFormWizardCustomEvent<{ values: Record<string, any>; score?: ScoreResult }>) => void;
334
359
  /**
@@ -339,6 +364,11 @@ declare namespace LocalJSX {
339
364
  * Theme overrides. Forwarded to each page's `<co-form>`. The wizard itself reads `theme` from the parsed paged schema if not supplied here so authors can ship a single bundled schema.
340
365
  */
341
366
  "theme"?: string;
367
+ /**
368
+ * When to run validation. Forwarded to each page's `<co-form>`.
369
+ * @default 'change'
370
+ */
371
+ "validateOn"?: 'change' | 'blur' | 'submit';
342
372
  }
343
373
 
344
374
  interface CoFormAttributes {
@@ -353,6 +383,7 @@ declare namespace LocalJSX {
353
383
  "gap": 'sm' | 'md' | 'lg';
354
384
  "footerAlign": 'start' | 'end' | 'center' | 'between' | 'stretch';
355
385
  "hideFooter": boolean;
386
+ "validateOn": 'change' | 'blur' | 'submit';
356
387
  "theme": string | ThemeSpec;
357
388
  }
358
389
  interface CoFormWizardAttributes {
@@ -362,6 +393,8 @@ declare namespace LocalJSX {
362
393
  "layout": 'grid' | 'stack';
363
394
  "columns": 1 | 2 | 3 | 4;
364
395
  "theme": string;
396
+ "validateOn": 'change' | 'blur' | 'submit';
397
+ "labels": string;
365
398
  }
366
399
 
367
400
  interface IntrinsicElements {
@@ -45,6 +45,9 @@ declare module '@stencil/core' {
45
45
  'onCoRemove'?: (e: CustomEvent<string>) => void;
46
46
  'onCoOpen'?: (e: CustomEvent<void>) => void;
47
47
  };
48
+ 'co-phone-field': CommonFieldAttrs & {
49
+ defaultCountry?: string;
50
+ };
48
51
  'co-switch': CommonFieldAttrs & { checked?: boolean };
49
52
  'co-button': {
50
53
  label?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prolibu-suite/cobalt-form",
3
- "version": "0.2.2",
3
+ "version": "1.0.0",
4
4
  "description": "Cobalt Form — schema-driven <co-form> Web Component. CDN entry point.",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.js",
@@ -37,10 +37,10 @@
37
37
  "author": "Prolibu <contact@prolibu.com>",
38
38
  "license": "MIT",
39
39
  "peerDependencies": {
40
- "@prolibu-suite/cobalt-core": "0.1.2"
40
+ "@prolibu-suite/cobalt-core": "0.2.0"
41
41
  },
42
42
  "dependencies": {
43
- "@prolibu-suite/cobalt-form-core": "0.2.0"
43
+ "@prolibu-suite/cobalt-form-core": "0.3.0"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@rollup/plugin-commonjs": "^29.0.2",
@@ -1 +0,0 @@
1
- import{r as a,c as r,h as o,H as t,g as i}from"./p-C1670_IO.js";import{c as e,a as c,r as s,t as d,b as n,e as f}from"./p-CPE0t-C2.js";function l(a){try{return JSON.parse(a)}catch(a){return null}}const p=class{constructor(o){a(this,o),this.coSubmit=r(this,"coSubmit"),this.coPageChange=r(this,"coPageChange"),this.locale="es",this.layout="grid",this.columns=1,this.currentIndex=0,this.values={},this.finalScore=null,this.themeStyles=null,this.hasBg=!1,this.paged={pages:[]},this.currentFormEl=null,this.handleNext=async()=>{await this.commitCurrentPage()&&this.currentIndex<this.activePages.length-1&&(this.currentIndex+=1,this.coPageChange.emit({index:this.currentIndex,page:this.currentPage}))},this.handlePrev=()=>{this.currentIndex>0&&(this.currentIndex-=1,this.coPageChange.emit({index:this.currentIndex,page:this.currentPage}))},this.handleStepClick=async a=>{if(a!==this.currentIndex){if(a<this.currentIndex)return this.currentIndex=a,void this.coPageChange.emit({index:this.currentIndex,page:this.currentPage});for(;this.currentIndex<a;){if(!await this.commitCurrentPage())return;this.currentIndex+=1}this.coPageChange.emit({index:this.currentIndex,page:this.currentPage})}},this.handleSubmit=async()=>{if(!await this.commitCurrentPage())return;let a;if("quiz"===this.paged.mode){const r=e(this.paged.pages);a=c(this.values,r,this.paged.scoring),this.finalScore=a}this.coSubmit.emit({values:this.values,score:a})},this.handlePageChange=a=>{this.values=Object.assign(Object.assign({},this.values),{[a.detail.name]:a.detail.value})}}componentWillLoad(){this.parseSchema(),this.values=this.parseInitialValues(),this.applyTheme()}onSchemaChange(){this.parseSchema(),this.currentIndex=0,this.applyTheme()}onThemeChange(){this.applyTheme()}applyTheme(){var a;const r=this.theme?"string"==typeof this.theme?l(this.theme):this.theme:this.paged.theme;if(console.log("[co-form-wizard] applyTheme called",{themeProp:this.theme,pagedTheme:null===(a=this.paged)||void 0===a?void 0:a.theme,raw:r}),!r)return this.themeStyles=null,this.hasBg=!1,void console.log("[co-form-wizard] no theme — cleared");const o=s(r);this.themeStyles=d(o),this.hasBg=!(!o.background.color&&!o.background.imageUrl),console.log("[co-form-wizard] theme resolved",{resolved:o,modifiers:this.themeStyles.modifiers,customProps:this.themeStyles.customProperties,hasBg:this.hasBg})}parseSchema(){try{const a=JSON.parse(this.schema);this.paged=n(a)}catch(a){console.error("[co-form-wizard] failed to parse schema:",a),this.paged={pages:[]}}}parseInitialValues(){if(!this.initialValues)return{};try{return JSON.parse(this.initialValues)||{}}catch(a){return console.error("[co-form-wizard] failed to parse initialValues:",a),{}}}get themeForChildren(){var a;const r=this.theme?"string"==typeof this.theme?l(this.theme):this.theme:null===(a=this.paged)||void 0===a?void 0:a.theme;if(!r||"object"!=typeof r)return;const o=function(a,r){var o={};for(var t in a)Object.prototype.hasOwnProperty.call(a,t)&&r.indexOf(t)<0&&(o[t]=a[t]);if(null!=a&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(t=Object.getOwnPropertySymbols(a);i<t.length;i++)r.indexOf(t[i])<0&&Object.prototype.propertyIsEnumerable.call(a,t[i])&&(o[t[i]]=a[t[i]])}return o}(r,["background"]);return JSON.stringify(o)}get activePages(){return this.paged.pages.filter((a=>!a.visibleIf||f(a.visibleIf,this.values)))}get currentPage(){var a;return null!==(a=this.activePages[this.currentIndex])&&void 0!==a?a:null}async commitCurrentPage(){var a,r;if(!this.currentFormEl)return!0;const o=await(null===(r=(a=this.currentFormEl).validateAndCollect)||void 0===r?void 0:r.call(a));return!!(null==o?void 0:o.valid)&&(this.values=Object.assign(Object.assign({},this.values),o.values),!0)}hostProps(){return{}}wrapperProps(){const a=this.themeStyles;return a?Object.assign(Object.assign(Object.assign({class:"co-form-wizard","data-theme":a.modifiers.colorScheme,"data-density":a.modifiers.density,"data-appearance":a.modifiers.appearance,"data-radius":a.modifiers.radius},this.hasBg?{"data-has-bg":""}:{}),a.modifiers.hideHeader?{"data-hide-header":""}:{}),{style:Object.assign(Object.assign({},a.customProperties),a.inlineStyles)}):{class:"co-form-wizard"}}render(){var a;const r=this.activePages;if(0===r.length)return o(t,Object.assign({},this.hostProps()),o("div",{class:"co-form-wizard__empty"},"No pages to display."));if(this.finalScore&&(null===(a=this.paged.scoring)||void 0===a?void 0:a.showScore))return o(t,Object.assign({},this.hostProps()),this.renderScorePanel(this.finalScore));const i=r[this.currentIndex],e=0===this.currentIndex,c=this.currentIndex===r.length-1,s=Object.keys(i.fields),d={};for(const a of s)a in this.values&&(d[a]=this.values[a]);return o(t,Object.assign({},this.hostProps()),this.renderInner(r,i,e,c,d))}renderInner(a,r,t,i,e){var c;const s=null===(c=this.themeStyles)||void 0===c?void 0:c.customCss;return o("div",Object.assign({},this.wrapperProps()),s&&o("style",null,s),o("slot",{name:"header"},(this.paged.title||this.paged.description)&&o("header",{class:"co-form-wizard__title-block"},this.paged.title&&o("h1",{class:"co-form-wizard__title"},this.paged.title),this.paged.description&&o("p",{class:"co-form-wizard__title-desc"},this.paged.description))),a.length>1&&o("ol",{class:"co-form-wizard__stepper"},a.map(((a,r)=>o("li",{class:{"co-form-wizard__step":!0,"is-active":r===this.currentIndex,"is-done":r<this.currentIndex},key:a.name},o("button",{type:"button",class:"co-form-wizard__step-btn",onClick:()=>this.handleStepClick(r)},o("span",{class:"co-form-wizard__step-num"},r+1),o("span",{class:"co-form-wizard__step-label"},a.title||a.name)))))),o("section",{class:"co-form-wizard__page-card"},this.renderPageHead(r,a.length>1),o("co-form",{ref:a=>this.currentFormEl=a,schema:JSON.stringify(r.fields),"initial-values":JSON.stringify(e),locale:this.locale,layout:this.layout,columns:this.columns,theme:this.themeForChildren,"hide-footer":!0,onCoChange:this.handlePageChange}),o("div",{class:"co-form-wizard__nav"},o("co-button",{label:"Anterior",variant:"outlined",disabled:t,onClick:this.handlePrev}),o("co-button",i?{label:"Enviar",variant:"primary",onClick:this.handleSubmit}:{label:"Siguiente",variant:"primary",onClick:this.handleNext}))),o("slot",{name:"footer"}))}renderPageHead(a,r){const t=!a.title||/^Page \d+$/i.test(a.title),i=(!!a.title&&!t||r&&a.title)&&!a.hideTitle,e=!!a.description&&!a.hideDescription,c=r&&!a.hideTitle;return c||i||e?o("header",{class:"co-form-wizard__page-head"},c&&o("span",{class:"co-form-wizard__page-pill"},"PAGE ",this.currentIndex+1),i&&o("h2",{class:"co-form-wizard__page-title"},a.title),e&&o("p",{class:"co-form-wizard__page-desc"},a.description)):null}renderScorePanel(a){const r=!0===a.passed?"Aprobado":!1===a.passed?"No aprobado":null;return o("div",{class:"co-form-wizard co-form-wizard__score"},o("h2",{class:"co-form-wizard__score-title"},"Resultado"),o("div",{class:"co-form-wizard__score-num"},a.total," / ",a.max,o("span",{class:"co-form-wizard__score-pct"},"(",a.percent,"%)")),r&&o("div",{class:{"co-form-wizard__score-pass":!0,"is-pass":!0===a.passed,"is-fail":!1===a.passed}},r),a.feedback.length>0&&o("ul",{class:"co-form-wizard__score-feedback"},a.feedback.map((a=>o("li",null,a)))))}get host(){return i(this)}static get watchers(){return{schema:[{onSchemaChange:0}],theme:[{onThemeChange:0}]}}};p.style=':host{display:block;font-family:var(--co-font-family-primary, sans-serif)}.co-form-wizard{max-width:720px;margin:0 auto;padding:var(--co-spacing-2xl, 24px);display:flex;flex-direction:column;gap:var(--co-spacing-lg, 16px)}.co-form-wizard[data-has-bg]{padding:var(--co-spacing-3xl, 32px) var(--co-spacing-2xl, 24px);background-repeat:no-repeat}.co-form-wizard__title-block{background:var(--co-form-header-bg, var(--co-semantic-surface-page, #fff));border:1px solid var(--co-semantic-border-default, rgba(17, 24, 39, 0.08));border-radius:var(--co-border-radius-lg, 16px);padding:var(--co-spacing-2xl, 24px) var(--co-spacing-3xl, 28px);box-shadow:0 1px 2px rgba(0, 0, 0, 0.04);min-height:var(--co-form-header-height, auto)}.co-form-wizard[data-hide-header] .co-form-wizard__title-block{display:none}.co-form-wizard[data-density="compact"] .co-form-wizard{gap:var(--co-spacing-sm, 8px)}.co-form-wizard[data-density="compact"] .co-form-wizard__title-block{padding:var(--co-spacing-lg, 16px) var(--co-spacing-xl, 20px)}.co-form-wizard[data-density="compact"] .co-form-wizard__page-head,.co-form-wizard[data-density="compact"] .co-form-wizard__nav{padding-top:var(--co-spacing-sm, 8px);padding-bottom:var(--co-spacing-sm, 8px)}.co-form-wizard__title{margin:0;font-size:24px;font-weight:700;letter-spacing:-0.02em;line-height:1.2;color:var(--co-semantic-text-default, #111827)}.co-form-wizard__title-desc{margin:6px 0 0;font-size:var(--co-font-size-14, 14px);color:var(--co-semantic-text-secondary, #6b7280)}.co-form-wizard__stepper{display:flex;align-items:center;gap:var(--co-spacing-sm, 8px);list-style:none;padding:0;margin:0;flex-wrap:wrap}.co-form-wizard__step{display:flex;align-items:center;color:var(--co-semantic-text-secondary, #6b7280);font-size:var(--co-font-size-12, 12px)}.co-form-wizard__step-btn{display:inline-flex;align-items:center;gap:var(--co-spacing-xs, 4px);padding:4px 6px;border:0;background:transparent;border-radius:var(--co-border-radius-xxs, 4px);font:inherit;color:inherit;cursor:pointer}.co-form-wizard__step-btn:hover{background:var(--co-semantic-surface-hover, #f3f4f6);color:var(--co-semantic-text-default, #111827)}.co-form-wizard__step-num{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:var(--co-border-radius-full, 9999px);background:var(--co-semantic-surface-hover, #f3f4f6);font-weight:600}.co-form-wizard__step.is-active .co-form-wizard__step-num{background:var(--co-color-primary-azul, #2563eb);color:white}.co-form-wizard__step.is-done .co-form-wizard__step-num{background:var(--co-color-primary-verde, #02a270);color:white}.co-form-wizard__step.is-active{color:var(--co-semantic-text-default, #111827);font-weight:600}.co-form-wizard__page-card{background:var(--co-semantic-surface-page, #fff);border:1px solid var(--co-semantic-border-default, rgba(17, 24, 39, 0.08));border-radius:var(--co-border-radius-lg, 16px);box-shadow:0 1px 2px rgba(0, 0, 0, 0.04);overflow:hidden;display:flex;flex-direction:column}.co-form-wizard__page-head{padding:var(--co-spacing-xl, 20px) var(--co-spacing-2xl, 24px);border-bottom:1px solid var(--co-semantic-border-default, rgba(17, 24, 39, 0.08));background:var(--co-semantic-surface-hover, #f9fafb)}.co-form-wizard__page-pill{display:inline-flex;font-size:10px;font-weight:700;letter-spacing:0.08em;color:var(--co-color-primary-azul, #2563eb);background:color-mix(in srgb, var(--co-color-primary-azul) 10%, transparent);padding:3px 8px;border-radius:var(--co-border-radius-full, 9999px);margin-bottom:6px}.co-form-wizard__page-title{margin:0;font-size:var(--co-font-size-18, 18px);font-weight:600;line-height:1.3;letter-spacing:-0.01em;color:var(--co-semantic-text-default, #111827)}.co-form-wizard__page-desc{margin:4px 0 0;font-size:var(--co-font-size-13, 13px);color:var(--co-semantic-text-secondary, #6b7280)}.co-form-wizard__page-card>co-form{display:block;padding:var(--co-spacing-xl, 20px) var(--co-spacing-2xl, 24px)}.co-form-wizard__nav{display:flex;justify-content:space-between;gap:var(--co-spacing-sm, 8px);padding:var(--co-spacing-md, 12px) var(--co-spacing-2xl, 24px);border-top:1px solid var(--co-semantic-border-default, rgba(17, 24, 39, 0.08));background:var(--co-semantic-surface-hover, #f9fafb)}.co-form-wizard__empty{padding:var(--co-spacing-lg, 16px);text-align:center;color:var(--co-semantic-text-secondary, #6b7280)}.co-form-wizard__score{text-align:center;padding:var(--co-spacing-2xl, 24px);background:var(--co-semantic-surface-page, #fff);border:1px solid var(--co-semantic-border-default, rgba(17, 24, 39, 0.08));border-radius:var(--co-border-radius-lg, 16px);box-shadow:0 1px 2px rgba(0, 0, 0, 0.04)}.co-form-wizard__score-title{margin:0;font-size:var(--co-font-size-18, 18px)}.co-form-wizard__score-num{font-size:48px;font-weight:600;color:var(--co-color-primary-azul, #2563eb);margin:var(--co-spacing-md, 12px) 0}.co-form-wizard__score-pct{font-size:var(--co-font-size-16, 16px);color:var(--co-semantic-text-secondary, #6b7280);margin-left:var(--co-spacing-sm, 8px)}.co-form-wizard__score-pass{display:inline-block;padding:var(--co-spacing-xs, 4px) var(--co-spacing-md, 12px);border-radius:var(--co-border-radius-full, 9999px);font-weight:600;margin-bottom:var(--co-spacing-md, 12px)}.co-form-wizard__score-pass.is-pass{background:var(--co-color-status-success, #0a7724);color:white}.co-form-wizard__score-pass.is-fail{background:var(--co-color-status-error, #aa2e1b);color:white}.co-form-wizard__score-feedback{text-align:left;list-style:disc;padding-left:var(--co-spacing-2xl, 24px);color:var(--co-semantic-text-default, #111827)}.co-form-wizard[data-has-bg] .co-form-wizard__title-block,.co-form-wizard[data-has-bg] .co-form-wizard__page-card,.co-form-wizard[data-has-bg] .co-form-wizard__score{border:0;box-shadow:0 4px 24px rgba(0, 0, 0, 0.08)}.co-form-wizard[data-theme="dark"]{--co-semantic-surface-page:#1a1f2b;--co-semantic-surface-secondary:#1a1f2b;--co-semantic-surface-primary:#ffffff;--co-semantic-surface-muted:#2a3142;--co-semantic-surface-hover:rgba(255, 255, 255, 0.06);--co-semantic-surface-disabled:rgba(255, 255, 255, 0.04);--co-semantic-on-primary:#1a1f2b;--co-semantic-on-secondary:#f9fafb;--co-semantic-text-default:#f9fafb;--co-semantic-text-secondary:#9ca3af;--co-semantic-text-muted:#6b7280;--co-semantic-text-disabled:#4b5563;--co-semantic-border-default:rgba(255, 255, 255, 0.12);--co-semantic-border-subtle:rgba(255, 255, 255, 0.14);--co-semantic-border-strong:rgba(255, 255, 255, 0.25);--co-semantic-border-focus:rgba(255, 255, 255, 0.25);--co-semantic-border-focus-ring:rgba(255, 255, 255, 0.1);color:#f9fafb}.co-form-wizard[data-theme="dark"] .co-form-wizard__page-card,.co-form-wizard[data-theme="dark"] .co-form-wizard__score{background:var(--co-semantic-surface-page);border-color:var(--co-semantic-border-default);color:#f9fafb}.co-form-wizard[data-theme="dark"] .co-form-wizard__title-block{background:var(--co-form-header-bg, var(--co-semantic-surface-page));border-color:var(--co-semantic-border-default);color:#f9fafb}.co-form-wizard[data-theme="dark"] .co-form-wizard__title,.co-form-wizard[data-theme="dark"] .co-form-wizard__page-title{color:#f9fafb}.co-form-wizard[data-theme="dark"] .co-form-wizard__title-desc,.co-form-wizard[data-theme="dark"] .co-form-wizard__page-desc{color:#9ca3af}.co-form-wizard[data-theme="dark"] .co-form-wizard__page-head,.co-form-wizard[data-theme="dark"] .co-form-wizard__nav{background:rgba(255, 255, 255, 0.03);border-color:var(--co-semantic-border-default)}.co-form-wizard[data-theme="dark"] .co-form-wizard__step-num{background:rgba(255, 255, 255, 0.1);color:#f9fafb}.co-form-wizard[data-theme="dark"][data-has-bg] .co-form-wizard__title-block,.co-form-wizard[data-theme="dark"][data-has-bg] .co-form-wizard__page-card,.co-form-wizard[data-theme="dark"][data-has-bg] .co-form-wizard__score{box-shadow:0 4px 24px rgba(0, 0, 0, 0.4)}.co-form-wizard[data-appearance="flat"] .co-form-wizard__title-block,.co-form-wizard[data-appearance="flat"] .co-form-wizard__page-card{background:transparent !important;border:0 !important;box-shadow:none !important;padding:0 !important}.co-form-wizard[data-appearance="flat"] .co-form-wizard__page-head{background:transparent !important;border-bottom:0 !important;padding:0 0 var(--co-spacing-md, 12px) 0 !important}.co-form-wizard[data-appearance="flat"] .co-form-wizard__nav{background:transparent !important;border-top:0 !important;padding:var(--co-spacing-md, 12px) 0 0 !important}.co-form-wizard[data-appearance="flat"] .co-form-wizard__page-card>co-form{padding:0 !important}.co-form-wizard[data-appearance="flat"][data-theme="dark"] .co-form-wizard__title-block,.co-form-wizard[data-appearance="flat"][data-theme="dark"] .co-form-wizard__page-card{color:#f9fafb}';export{p as co_form_wizard}