@prolibu-suite/cobalt-form 0.1.1 → 0.2.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 (34) hide show
  1. package/dist/cjs/co-form-wizard.cjs.entry.js +307 -0
  2. package/dist/cjs/co-form.cjs.entry.js +2 -1
  3. package/dist/cjs/cobalt-form.cjs.js +2 -2
  4. package/dist/cjs/index-CLL7Ervz.js +8155 -0
  5. package/dist/cjs/{index-8raPCV5a.js → index-Mpsm3UE7.js} +8 -0
  6. package/dist/cjs/index.cjs.js +151 -8869
  7. package/dist/cjs/loader.cjs.js +2 -2
  8. package/dist/cobalt-form/cobalt-form.esm.js +1 -1
  9. package/dist/cobalt-form/index.esm.js +1 -7
  10. package/dist/cobalt-form/p-2168be6b.entry.js +1 -0
  11. package/dist/cobalt-form/p-7b8f67bc.entry.js +1 -0
  12. package/dist/cobalt-form/p-C1670_IO.js +2 -0
  13. package/dist/cobalt-form/p-CPE0t-C2.js +7 -0
  14. package/dist/collection/collection-manifest.json +2 -1
  15. package/dist/collection/components/co-form/co-form.css +167 -1
  16. package/dist/collection/components/co-form/co-form.js +278 -9
  17. package/dist/collection/components/co-form-wizard/co-form-wizard.css +363 -0
  18. package/dist/collection/components/co-form-wizard/co-form-wizard.js +502 -0
  19. package/dist/components/co-form-wizard.d.ts +11 -0
  20. package/dist/components/co-form-wizard.js +1 -0
  21. package/dist/components/index.js +5 -5
  22. package/dist/esm/co-form-wizard.entry.js +305 -0
  23. package/dist/esm/co-form.entry.js +2 -1
  24. package/dist/esm/cobalt-form.js +3 -3
  25. package/dist/esm/{index-X0Keifac.js → index-C1670_IO.js} +8 -1
  26. package/dist/esm/index-CPE0t-C2.js +8144 -0
  27. package/dist/esm/index.js +147 -8865
  28. package/dist/esm/loader.js +3 -3
  29. package/dist/types/components/co-form/co-form.d.ts +53 -1
  30. package/dist/types/components/co-form-wizard/co-form-wizard.d.ts +118 -0
  31. package/dist/types/components.d.ts +184 -2
  32. package/package.json +6 -3
  33. package/dist/cobalt-form/p-X0Keifac.js +0 -2
  34. package/dist/cobalt-form/p-ef70e055.entry.js +0 -1
@@ -0,0 +1,305 @@
1
+ import { r as registerInstance, c as createEvent, h, H as Host, g as getElement } from './index-C1670_IO.js';
2
+ import { c as collectQuizFields, a as computeScore, r as resolveTheme, t as themeToStyles, b as toPagedSchema, e as evaluateExpression } from './index-CPE0t-C2.js';
3
+
4
+ const coFormWizardCss = () => `: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-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}`;
5
+
6
+ var __rest = (undefined && undefined.__rest) || function (s, e) {
7
+ var t = {};
8
+ for (var p in s)
9
+ if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
10
+ t[p] = s[p];
11
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
12
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
13
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
14
+ t[p[i]] = s[p[i]];
15
+ }
16
+ return t;
17
+ };
18
+ function safeJsonParse(s) {
19
+ try {
20
+ return JSON.parse(s);
21
+ }
22
+ catch (_a) {
23
+ return null;
24
+ }
25
+ }
26
+ const CoFormWizard = class {
27
+ constructor(hostRef) {
28
+ registerInstance(this, hostRef);
29
+ this.coSubmit = createEvent(this, "coSubmit");
30
+ this.coPageChange = createEvent(this, "coPageChange");
31
+ /** Locale for AJV error messages. */
32
+ this.locale = 'es';
33
+ /** Layout passed to each page's <co-form>. */
34
+ this.layout = 'grid';
35
+ /** Number of columns per page. */
36
+ this.columns = 1;
37
+ this.currentIndex = 0;
38
+ this.values = {};
39
+ this.finalScore = null;
40
+ /**
41
+ * Resolved theme styles for the wizard. Stored as state so render() picks
42
+ * up changes — using `<Host>` to bind the data-attrs + inline styles
43
+ * dodges the `setAttribute()` timing issues we saw with shadow:false.
44
+ */
45
+ this.themeStyles = null;
46
+ this.hasBg = false;
47
+ this.paged = { pages: [] };
48
+ // Use `any` rather than HTMLCoFormElement: type generation happens at
49
+ // build time, and the wizard lives in the same package, so we can't
50
+ // depend on the generated type without a chicken-and-egg.
51
+ this.currentFormEl = null;
52
+ this.handleNext = async () => {
53
+ const ok = await this.commitCurrentPage();
54
+ if (!ok)
55
+ return;
56
+ if (this.currentIndex < this.activePages.length - 1) {
57
+ this.currentIndex += 1;
58
+ this.coPageChange.emit({ index: this.currentIndex, page: this.currentPage });
59
+ }
60
+ };
61
+ this.handlePrev = () => {
62
+ if (this.currentIndex > 0) {
63
+ this.currentIndex -= 1;
64
+ this.coPageChange.emit({ index: this.currentIndex, page: this.currentPage });
65
+ }
66
+ };
67
+ /**
68
+ * Click on a step in the stepper. Backwards navigation is unrestricted
69
+ * (the user already visited those pages). Forward jumps require the
70
+ * current page to validate first, then we hop one page at a time so we
71
+ * don't silently skip validation of intermediate pages.
72
+ */
73
+ this.handleStepClick = async (targetIndex) => {
74
+ if (targetIndex === this.currentIndex)
75
+ return;
76
+ if (targetIndex < this.currentIndex) {
77
+ this.currentIndex = targetIndex;
78
+ this.coPageChange.emit({ index: this.currentIndex, page: this.currentPage });
79
+ return;
80
+ }
81
+ // Forward jump — validate-and-advance one step at a time.
82
+ while (this.currentIndex < targetIndex) {
83
+ const ok = await this.commitCurrentPage();
84
+ if (!ok)
85
+ return;
86
+ this.currentIndex += 1;
87
+ }
88
+ this.coPageChange.emit({ index: this.currentIndex, page: this.currentPage });
89
+ };
90
+ this.handleSubmit = async () => {
91
+ const ok = await this.commitCurrentPage();
92
+ if (!ok)
93
+ return;
94
+ let score;
95
+ if (this.paged.mode === 'quiz') {
96
+ const allFields = collectQuizFields(this.paged.pages);
97
+ score = computeScore(this.values, allFields, this.paged.scoring);
98
+ this.finalScore = score;
99
+ }
100
+ this.coSubmit.emit({ values: this.values, score });
101
+ };
102
+ this.handlePageChange = (ev) => {
103
+ this.values = Object.assign(Object.assign({}, this.values), { [ev.detail.name]: ev.detail.value });
104
+ };
105
+ }
106
+ componentWillLoad() {
107
+ this.parseSchema();
108
+ this.values = this.parseInitialValues();
109
+ this.applyTheme();
110
+ }
111
+ onSchemaChange() {
112
+ this.parseSchema();
113
+ this.currentIndex = 0;
114
+ this.applyTheme();
115
+ }
116
+ onThemeChange() {
117
+ this.applyTheme();
118
+ }
119
+ /**
120
+ * Compute the resolved theme styles and store in `@State()` so render()
121
+ * picks them up via `<Host>`. Children `<co-form>` receive a theme with
122
+ * the background stripped (see `themeForChildren`) so only the wizard's
123
+ * outer surface carries it — avoids the image leaking into each page.
124
+ */
125
+ applyTheme() {
126
+ var _a;
127
+ const raw = this.theme
128
+ ? (typeof this.theme === 'string' ? safeJsonParse(this.theme) : this.theme)
129
+ : this.paged.theme;
130
+ console.log('[co-form-wizard] applyTheme called', {
131
+ themeProp: this.theme,
132
+ pagedTheme: (_a = this.paged) === null || _a === void 0 ? void 0 : _a.theme,
133
+ raw,
134
+ });
135
+ if (!raw) {
136
+ this.themeStyles = null;
137
+ this.hasBg = false;
138
+ console.log('[co-form-wizard] no theme — cleared');
139
+ return;
140
+ }
141
+ const resolved = resolveTheme(raw);
142
+ this.themeStyles = themeToStyles(resolved);
143
+ this.hasBg = !!(resolved.background.color || resolved.background.imageUrl);
144
+ console.log('[co-form-wizard] theme resolved', {
145
+ resolved,
146
+ modifiers: this.themeStyles.modifiers,
147
+ customProps: this.themeStyles.customProperties,
148
+ hasBg: this.hasBg,
149
+ });
150
+ }
151
+ parseSchema() {
152
+ try {
153
+ const parsed = JSON.parse(this.schema);
154
+ this.paged = toPagedSchema(parsed);
155
+ }
156
+ catch (err) {
157
+ console.error('[co-form-wizard] failed to parse schema:', err);
158
+ this.paged = { pages: [] };
159
+ }
160
+ }
161
+ parseInitialValues() {
162
+ if (!this.initialValues)
163
+ return {};
164
+ try {
165
+ return JSON.parse(this.initialValues) || {};
166
+ }
167
+ catch (err) {
168
+ console.error('[co-form-wizard] failed to parse initialValues:', err);
169
+ return {};
170
+ }
171
+ }
172
+ /**
173
+ * Theme JSON forwarded to each child <co-form>. Background is stripped
174
+ * here — the wizard's host paints the backdrop, the inner form sits on
175
+ * a solid "page surface" so inputs stay readable.
176
+ */
177
+ get themeForChildren() {
178
+ var _a;
179
+ const raw = this.theme
180
+ ? (typeof this.theme === 'string' ? safeJsonParse(this.theme) : this.theme)
181
+ : (_a = this.paged) === null || _a === void 0 ? void 0 : _a.theme;
182
+ if (!raw || typeof raw !== 'object')
183
+ return undefined;
184
+ // Shallow clone + drop the bg block.
185
+ const _b = raw, rest = __rest(_b, ["background"]);
186
+ return JSON.stringify(rest);
187
+ }
188
+ /**
189
+ * Pages the user should see in order. Filters out pages whose `visibleIf`
190
+ * evaluates to false against the current values.
191
+ */
192
+ get activePages() {
193
+ return this.paged.pages.filter((p) => p.visibleIf ? evaluateExpression(p.visibleIf, this.values) : true);
194
+ }
195
+ get currentPage() {
196
+ var _a;
197
+ return (_a = this.activePages[this.currentIndex]) !== null && _a !== void 0 ? _a : null;
198
+ }
199
+ async commitCurrentPage() {
200
+ var _a, _b;
201
+ if (!this.currentFormEl)
202
+ return true;
203
+ const isValid = await ((_b = (_a = this.currentFormEl).validateAndCollect) === null || _b === void 0 ? void 0 : _b.call(_a));
204
+ if (!(isValid === null || isValid === void 0 ? void 0 : isValid.valid))
205
+ return false;
206
+ this.values = Object.assign(Object.assign({}, this.values), isValid.values);
207
+ return true;
208
+ }
209
+ /**
210
+ * Host element gets nothing extra — Stencil's shadow:false doesn't
211
+ * reliably rewrite `:host([attr])` selectors, so we put everything on
212
+ * the inner wrapper instead.
213
+ */
214
+ hostProps() {
215
+ return {};
216
+ }
217
+ /**
218
+ * Data attributes + inline styles for the inner `.co-form-wizard`
219
+ * wrapper. Scoped CSS targets descendants of this wrapper via normal
220
+ * descendant selectors that work regardless of Stencil scoping.
221
+ * CSS custom properties (accent / radius / header) cascade from here
222
+ * down to children — no need to also put them on the host.
223
+ */
224
+ wrapperProps() {
225
+ const t = this.themeStyles;
226
+ if (!t)
227
+ return { class: 'co-form-wizard' };
228
+ return Object.assign(Object.assign(Object.assign({ class: 'co-form-wizard', 'data-theme': t.modifiers.colorScheme, 'data-density': t.modifiers.density, 'data-appearance': t.modifiers.appearance, 'data-radius': t.modifiers.radius }, (this.hasBg ? { 'data-has-bg': '' } : {})), (t.modifiers.hideHeader ? { 'data-hide-header': '' } : {})), { style: Object.assign(Object.assign({}, t.customProperties), t.inlineStyles) });
229
+ }
230
+ render() {
231
+ var _a;
232
+ const pages = this.activePages;
233
+ if (pages.length === 0) {
234
+ return (h(Host, Object.assign({}, this.hostProps()), h("div", { class: "co-form-wizard__empty" }, "No pages to display.")));
235
+ }
236
+ // Quiz finished — show the score panel.
237
+ if (this.finalScore && ((_a = this.paged.scoring) === null || _a === void 0 ? void 0 : _a.showScore)) {
238
+ return (h(Host, Object.assign({}, this.hostProps()), this.renderScorePanel(this.finalScore)));
239
+ }
240
+ const current = pages[this.currentIndex];
241
+ const isFirst = this.currentIndex === 0;
242
+ const isLast = this.currentIndex === pages.length - 1;
243
+ // Each page is a fresh <co-form> with just its own fields. We pass
244
+ // initial values filtered to that page's field names so AJV doesn't
245
+ // complain about unknown properties from other pages.
246
+ const pageFields = Object.keys(current.fields);
247
+ const pageInitial = {};
248
+ for (const k of pageFields) {
249
+ if (k in this.values)
250
+ pageInitial[k] = this.values[k];
251
+ }
252
+ return (h(Host, Object.assign({}, this.hostProps()), this.renderInner(pages, current, isFirst, isLast, pageInitial)));
253
+ }
254
+ renderInner(pages, current, isFirst, isLast, pageInitial) {
255
+ var _a;
256
+ const customCss = (_a = this.themeStyles) === null || _a === void 0 ? void 0 : _a.customCss;
257
+ return (h("div", Object.assign({}, this.wrapperProps()), customCss && h("style", null, customCss), h("slot", { name: "header" }, (this.paged.title || this.paged.description) && (h("header", { class: "co-form-wizard__title-block" }, this.paged.title && (h("h1", { class: "co-form-wizard__title" }, this.paged.title)), this.paged.description && (h("p", { class: "co-form-wizard__title-desc" }, this.paged.description))))), pages.length > 1 && (h("ol", { class: "co-form-wizard__stepper" }, pages.map((p, i) => (h("li", { class: {
258
+ 'co-form-wizard__step': true,
259
+ 'is-active': i === this.currentIndex,
260
+ 'is-done': i < this.currentIndex,
261
+ }, key: p.name }, h("button", { type: "button", class: "co-form-wizard__step-btn", onClick: () => this.handleStepClick(i) }, h("span", { class: "co-form-wizard__step-num" }, i + 1), h("span", { class: "co-form-wizard__step-label" }, p.title || p.name))))))), h("section", { class: "co-form-wizard__page-card" }, this.renderPageHead(current, pages.length > 1), h("co-form", { ref: (el) => (this.currentFormEl = el), schema: JSON.stringify(current.fields), "initial-values": JSON.stringify(pageInitial), locale: this.locale, layout: this.layout, columns: this.columns, theme: this.themeForChildren, "hide-footer": true, onCoChange: this.handlePageChange }), h("div", { class: "co-form-wizard__nav" }, h("co-button", { label: "Anterior", variant: "outlined", disabled: isFirst, onClick: this.handlePrev }), isLast ? (h("co-button", { label: "Enviar", variant: "primary", onClick: this.handleSubmit })) : (h("co-button", { label: "Siguiente", variant: "primary", onClick: this.handleNext })))), h("slot", { name: "footer" })));
262
+ }
263
+ /**
264
+ * Smart page-head visibility:
265
+ * - Multi-page → always show (pill + title for progress tracking),
266
+ * unless the page explicitly hides title/description.
267
+ * - Single-page with default title "Page N" and no description → hide
268
+ * entirely; the form title block above already provides the context.
269
+ * - Single-page with a custom title or a description → show the
270
+ * relevant parts only.
271
+ * - Explicit `hideTitle` / `hideDescription` overrides on the page
272
+ * always win.
273
+ */
274
+ renderPageHead(current, isMulti) {
275
+ const titleIsDefault = !current.title || /^Page \d+$/i.test(current.title);
276
+ const customTitle = !!current.title && !titleIsDefault;
277
+ const hasDesc = !!current.description;
278
+ const wantsTitle = (customTitle || (isMulti && current.title)) && !current.hideTitle;
279
+ const wantsDesc = hasDesc && !current.hideDescription;
280
+ const wantsPill = isMulti && !current.hideTitle;
281
+ if (!wantsPill && !wantsTitle && !wantsDesc)
282
+ return null;
283
+ return (h("header", { class: "co-form-wizard__page-head" }, wantsPill && (h("span", { class: "co-form-wizard__page-pill" }, "PAGE ", this.currentIndex + 1)), wantsTitle && (h("h2", { class: "co-form-wizard__page-title" }, current.title)), wantsDesc && (h("p", { class: "co-form-wizard__page-desc" }, current.description))));
284
+ }
285
+ renderScorePanel(score) {
286
+ const passText = score.passed === true ? 'Aprobado' : score.passed === false ? 'No aprobado' : null;
287
+ return (h("div", { class: "co-form-wizard co-form-wizard__score" }, h("h2", { class: "co-form-wizard__score-title" }, "Resultado"), h("div", { class: "co-form-wizard__score-num" }, score.total, " / ", score.max, h("span", { class: "co-form-wizard__score-pct" }, "(", score.percent, "%)")), passText && (h("div", { class: {
288
+ 'co-form-wizard__score-pass': true,
289
+ 'is-pass': score.passed === true,
290
+ 'is-fail': score.passed === false,
291
+ } }, passText)), score.feedback.length > 0 && (h("ul", { class: "co-form-wizard__score-feedback" }, score.feedback.map((m) => (h("li", null, m)))))));
292
+ }
293
+ get host() { return getElement(this); }
294
+ static get watchers() { return {
295
+ "schema": [{
296
+ "onSchemaChange": 0
297
+ }],
298
+ "theme": [{
299
+ "onThemeChange": 0
300
+ }]
301
+ }; }
302
+ };
303
+ CoFormWizard.style = coFormWizardCss();
304
+
305
+ export { CoFormWizard as co_form_wizard };
@@ -1,2 +1,3 @@
1
1
  export { CoForm as co_form } from './index.js';
2
- import './index-X0Keifac.js';
2
+ import './index-C1670_IO.js';
3
+ import './index-CPE0t-C2.js';
@@ -1,5 +1,5 @@
1
- import { p as promiseResolve, b as bootstrapLazy } from './index-X0Keifac.js';
2
- export { s as setNonce } from './index-X0Keifac.js';
1
+ import { p as promiseResolve, b as bootstrapLazy } from './index-C1670_IO.js';
2
+ export { s as setNonce } from './index-C1670_IO.js';
3
3
  import { g as globalScripts } from './app-globals-DQuL1Twl.js';
4
4
 
5
5
  /*
@@ -17,5 +17,5 @@ var patchBrowser = () => {
17
17
 
18
18
  patchBrowser().then(async (options) => {
19
19
  await globalScripts();
20
- 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"],"snapshot":[32],"refStates":[32],"setValue":[64],"getValue":[64],"touch":[64]},null,{"schema":[{"onSchemaChange":0}],"schemaInstance":[{"onSchemaChange":0}],"locale":[{"onSchemaChange":0}]}]]]], options);
20
+ 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);
21
21
  });
@@ -108,6 +108,10 @@ var loadModule = (cmpMeta, hostRef, hmrVersionId) => {
108
108
  }
109
109
  switch(bundleId) {
110
110
 
111
+ case 'co-form-wizard':
112
+ return import(
113
+ /* webpackMode: "lazy" */
114
+ './co-form-wizard.entry.js').then(processMod, consoleError);
111
115
  case 'co-form':
112
116
  return import(
113
117
  /* webpackMode: "lazy" */
@@ -571,6 +575,9 @@ var parsePropertyValue = (propValue, propType, isFormAssociated) => {
571
575
  return propValue === "false" ? false : propValue === "" || !!propValue;
572
576
  }
573
577
  }
578
+ if (propType & 2 /* Number */) {
579
+ return typeof propValue === "string" ? parseFloat(propValue) : typeof propValue === "number" ? propValue : NaN;
580
+ }
574
581
  if (propType & 1 /* String */) {
575
582
  return String(propValue);
576
583
  }
@@ -1990,4 +1997,4 @@ function transformTag(tag) {
1990
1997
  return tag;
1991
1998
  }
1992
1999
 
1993
- export { bootstrapLazy as b, createEvent as c, getElement as g, h, promiseResolve as p, registerInstance as r, setNonce as s };
2000
+ export { Host as H, bootstrapLazy as b, createEvent as c, getElement as g, h, promiseResolve as p, registerInstance as r, setNonce as s };