@prolibu-suite/cobalt-form 0.1.0 → 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 (35) hide show
  1. package/README.md +106 -0
  2. package/dist/cjs/co-form-wizard.cjs.entry.js +307 -0
  3. package/dist/cjs/co-form.cjs.entry.js +2 -1
  4. package/dist/cjs/cobalt-form.cjs.js +2 -2
  5. package/dist/cjs/index-CLL7Ervz.js +8155 -0
  6. package/dist/cjs/{index-8raPCV5a.js → index-Mpsm3UE7.js} +8 -0
  7. package/dist/cjs/index.cjs.js +151 -8869
  8. package/dist/cjs/loader.cjs.js +2 -2
  9. package/dist/cobalt-form/cobalt-form.esm.js +1 -1
  10. package/dist/cobalt-form/index.esm.js +1 -7
  11. package/dist/cobalt-form/p-2168be6b.entry.js +1 -0
  12. package/dist/cobalt-form/p-7b8f67bc.entry.js +1 -0
  13. package/dist/cobalt-form/p-C1670_IO.js +2 -0
  14. package/dist/cobalt-form/p-CPE0t-C2.js +7 -0
  15. package/dist/collection/collection-manifest.json +2 -1
  16. package/dist/collection/components/co-form/co-form.css +167 -1
  17. package/dist/collection/components/co-form/co-form.js +278 -9
  18. package/dist/collection/components/co-form-wizard/co-form-wizard.css +363 -0
  19. package/dist/collection/components/co-form-wizard/co-form-wizard.js +502 -0
  20. package/dist/components/co-form-wizard.d.ts +11 -0
  21. package/dist/components/co-form-wizard.js +1 -0
  22. package/dist/components/index.js +5 -5
  23. package/dist/esm/co-form-wizard.entry.js +305 -0
  24. package/dist/esm/co-form.entry.js +2 -1
  25. package/dist/esm/cobalt-form.js +3 -3
  26. package/dist/esm/{index-X0Keifac.js → index-C1670_IO.js} +8 -1
  27. package/dist/esm/index-CPE0t-C2.js +8144 -0
  28. package/dist/esm/index.js +147 -8865
  29. package/dist/esm/loader.js +3 -3
  30. package/dist/types/components/co-form/co-form.d.ts +53 -1
  31. package/dist/types/components/co-form-wizard/co-form-wizard.d.ts +118 -0
  32. package/dist/types/components.d.ts +184 -2
  33. package/package.json +7 -4
  34. package/dist/cobalt-form/p-X0Keifac.js +0 -2
  35. package/dist/cobalt-form/p-ef70e055.entry.js +0 -1
@@ -0,0 +1,502 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s)
4
+ if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ import { h, Host } from "@stencil/core";
14
+ import { collectQuizFields, computeScore, evaluateExpression, resolveTheme, themeToStyles, toPagedSchema, } from "@prolibu-suite/cobalt-form-core";
15
+ function safeJsonParse(s) {
16
+ try {
17
+ return JSON.parse(s);
18
+ }
19
+ catch (_a) {
20
+ return null;
21
+ }
22
+ }
23
+ /**
24
+ * Multi-page wrapper around `<co-form>`. Consumes a paged schema (or a flat
25
+ * one, which it auto-wraps as a single page) and renders one page at a time
26
+ * with prev/next/submit navigation.
27
+ *
28
+ * The wizard owns the aggregate `values` and merges per-page updates as the
29
+ * user advances. Pages with `visibleIf` are skipped when their expression
30
+ * evaluates to false against the current values.
31
+ *
32
+ * @slot header - Above the stepper.
33
+ * @slot footer - Below the navigation buttons.
34
+ */
35
+ export class CoFormWizard {
36
+ constructor() {
37
+ /** Locale for AJV error messages. */
38
+ this.locale = 'es';
39
+ /** Layout passed to each page's <co-form>. */
40
+ this.layout = 'grid';
41
+ /** Number of columns per page. */
42
+ this.columns = 1;
43
+ this.currentIndex = 0;
44
+ this.values = {};
45
+ this.finalScore = null;
46
+ /**
47
+ * Resolved theme styles for the wizard. Stored as state so render() picks
48
+ * up changes — using `<Host>` to bind the data-attrs + inline styles
49
+ * dodges the `setAttribute()` timing issues we saw with shadow:false.
50
+ */
51
+ this.themeStyles = null;
52
+ this.hasBg = false;
53
+ this.paged = { pages: [] };
54
+ // Use `any` rather than HTMLCoFormElement: type generation happens at
55
+ // build time, and the wizard lives in the same package, so we can't
56
+ // depend on the generated type without a chicken-and-egg.
57
+ this.currentFormEl = null;
58
+ this.handleNext = async () => {
59
+ const ok = await this.commitCurrentPage();
60
+ if (!ok)
61
+ return;
62
+ if (this.currentIndex < this.activePages.length - 1) {
63
+ this.currentIndex += 1;
64
+ this.coPageChange.emit({ index: this.currentIndex, page: this.currentPage });
65
+ }
66
+ };
67
+ this.handlePrev = () => {
68
+ if (this.currentIndex > 0) {
69
+ this.currentIndex -= 1;
70
+ this.coPageChange.emit({ index: this.currentIndex, page: this.currentPage });
71
+ }
72
+ };
73
+ /**
74
+ * Click on a step in the stepper. Backwards navigation is unrestricted
75
+ * (the user already visited those pages). Forward jumps require the
76
+ * current page to validate first, then we hop one page at a time so we
77
+ * don't silently skip validation of intermediate pages.
78
+ */
79
+ this.handleStepClick = async (targetIndex) => {
80
+ if (targetIndex === this.currentIndex)
81
+ return;
82
+ if (targetIndex < this.currentIndex) {
83
+ this.currentIndex = targetIndex;
84
+ this.coPageChange.emit({ index: this.currentIndex, page: this.currentPage });
85
+ return;
86
+ }
87
+ // Forward jump — validate-and-advance one step at a time.
88
+ while (this.currentIndex < targetIndex) {
89
+ const ok = await this.commitCurrentPage();
90
+ if (!ok)
91
+ return;
92
+ this.currentIndex += 1;
93
+ }
94
+ this.coPageChange.emit({ index: this.currentIndex, page: this.currentPage });
95
+ };
96
+ this.handleSubmit = async () => {
97
+ const ok = await this.commitCurrentPage();
98
+ if (!ok)
99
+ return;
100
+ let score;
101
+ if (this.paged.mode === 'quiz') {
102
+ const allFields = collectQuizFields(this.paged.pages);
103
+ score = computeScore(this.values, allFields, this.paged.scoring);
104
+ this.finalScore = score;
105
+ }
106
+ this.coSubmit.emit({ values: this.values, score });
107
+ };
108
+ this.handlePageChange = (ev) => {
109
+ this.values = Object.assign(Object.assign({}, this.values), { [ev.detail.name]: ev.detail.value });
110
+ };
111
+ }
112
+ componentWillLoad() {
113
+ this.parseSchema();
114
+ this.values = this.parseInitialValues();
115
+ this.applyTheme();
116
+ }
117
+ onSchemaChange() {
118
+ this.parseSchema();
119
+ this.currentIndex = 0;
120
+ this.applyTheme();
121
+ }
122
+ onThemeChange() {
123
+ this.applyTheme();
124
+ }
125
+ /**
126
+ * Compute the resolved theme styles and store in `@State()` so render()
127
+ * picks them up via `<Host>`. Children `<co-form>` receive a theme with
128
+ * the background stripped (see `themeForChildren`) so only the wizard's
129
+ * outer surface carries it — avoids the image leaking into each page.
130
+ */
131
+ applyTheme() {
132
+ var _a;
133
+ const raw = this.theme
134
+ ? (typeof this.theme === 'string' ? safeJsonParse(this.theme) : this.theme)
135
+ : this.paged.theme;
136
+ console.log('[co-form-wizard] applyTheme called', {
137
+ themeProp: this.theme,
138
+ pagedTheme: (_a = this.paged) === null || _a === void 0 ? void 0 : _a.theme,
139
+ raw,
140
+ });
141
+ if (!raw) {
142
+ this.themeStyles = null;
143
+ this.hasBg = false;
144
+ console.log('[co-form-wizard] no theme — cleared');
145
+ return;
146
+ }
147
+ const resolved = resolveTheme(raw);
148
+ this.themeStyles = themeToStyles(resolved);
149
+ this.hasBg = !!(resolved.background.color || resolved.background.imageUrl);
150
+ console.log('[co-form-wizard] theme resolved', {
151
+ resolved,
152
+ modifiers: this.themeStyles.modifiers,
153
+ customProps: this.themeStyles.customProperties,
154
+ hasBg: this.hasBg,
155
+ });
156
+ }
157
+ parseSchema() {
158
+ try {
159
+ const parsed = JSON.parse(this.schema);
160
+ this.paged = toPagedSchema(parsed);
161
+ }
162
+ catch (err) {
163
+ console.error('[co-form-wizard] failed to parse schema:', err);
164
+ this.paged = { pages: [] };
165
+ }
166
+ }
167
+ parseInitialValues() {
168
+ if (!this.initialValues)
169
+ return {};
170
+ try {
171
+ return JSON.parse(this.initialValues) || {};
172
+ }
173
+ catch (err) {
174
+ console.error('[co-form-wizard] failed to parse initialValues:', err);
175
+ return {};
176
+ }
177
+ }
178
+ /**
179
+ * Theme JSON forwarded to each child <co-form>. Background is stripped
180
+ * here — the wizard's host paints the backdrop, the inner form sits on
181
+ * a solid "page surface" so inputs stay readable.
182
+ */
183
+ get themeForChildren() {
184
+ var _a;
185
+ const raw = this.theme
186
+ ? (typeof this.theme === 'string' ? safeJsonParse(this.theme) : this.theme)
187
+ : (_a = this.paged) === null || _a === void 0 ? void 0 : _a.theme;
188
+ if (!raw || typeof raw !== 'object')
189
+ return undefined;
190
+ // Shallow clone + drop the bg block.
191
+ const _b = raw, { background } = _b, rest = __rest(_b, ["background"]);
192
+ void background;
193
+ return JSON.stringify(rest);
194
+ }
195
+ /**
196
+ * Pages the user should see in order. Filters out pages whose `visibleIf`
197
+ * evaluates to false against the current values.
198
+ */
199
+ get activePages() {
200
+ return this.paged.pages.filter((p) => p.visibleIf ? evaluateExpression(p.visibleIf, this.values) : true);
201
+ }
202
+ get currentPage() {
203
+ var _a;
204
+ return (_a = this.activePages[this.currentIndex]) !== null && _a !== void 0 ? _a : null;
205
+ }
206
+ async commitCurrentPage() {
207
+ var _a, _b;
208
+ if (!this.currentFormEl)
209
+ return true;
210
+ const isValid = await ((_b = (_a = this.currentFormEl).validateAndCollect) === null || _b === void 0 ? void 0 : _b.call(_a));
211
+ if (!(isValid === null || isValid === void 0 ? void 0 : isValid.valid))
212
+ return false;
213
+ this.values = Object.assign(Object.assign({}, this.values), isValid.values);
214
+ return true;
215
+ }
216
+ /**
217
+ * Host element gets nothing extra — Stencil's shadow:false doesn't
218
+ * reliably rewrite `:host([attr])` selectors, so we put everything on
219
+ * the inner wrapper instead.
220
+ */
221
+ hostProps() {
222
+ return {};
223
+ }
224
+ /**
225
+ * Data attributes + inline styles for the inner `.co-form-wizard`
226
+ * wrapper. Scoped CSS targets descendants of this wrapper via normal
227
+ * descendant selectors that work regardless of Stencil scoping.
228
+ * CSS custom properties (accent / radius / header) cascade from here
229
+ * down to children — no need to also put them on the host.
230
+ */
231
+ wrapperProps() {
232
+ const t = this.themeStyles;
233
+ if (!t)
234
+ return { class: 'co-form-wizard' };
235
+ 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) });
236
+ }
237
+ render() {
238
+ var _a;
239
+ const pages = this.activePages;
240
+ if (pages.length === 0) {
241
+ return (h(Host, Object.assign({}, this.hostProps()), h("div", { class: "co-form-wizard__empty" }, "No pages to display.")));
242
+ }
243
+ // Quiz finished — show the score panel.
244
+ if (this.finalScore && ((_a = this.paged.scoring) === null || _a === void 0 ? void 0 : _a.showScore)) {
245
+ return (h(Host, Object.assign({}, this.hostProps()), this.renderScorePanel(this.finalScore)));
246
+ }
247
+ const current = pages[this.currentIndex];
248
+ const isFirst = this.currentIndex === 0;
249
+ const isLast = this.currentIndex === pages.length - 1;
250
+ // Each page is a fresh <co-form> with just its own fields. We pass
251
+ // initial values filtered to that page's field names so AJV doesn't
252
+ // complain about unknown properties from other pages.
253
+ const pageFields = Object.keys(current.fields);
254
+ const pageInitial = {};
255
+ for (const k of pageFields) {
256
+ if (k in this.values)
257
+ pageInitial[k] = this.values[k];
258
+ }
259
+ return (h(Host, Object.assign({}, this.hostProps()), this.renderInner(pages, current, isFirst, isLast, pageInitial)));
260
+ }
261
+ renderInner(pages, current, isFirst, isLast, pageInitial) {
262
+ var _a;
263
+ const customCss = (_a = this.themeStyles) === null || _a === void 0 ? void 0 : _a.customCss;
264
+ 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: {
265
+ 'co-form-wizard__step': true,
266
+ 'is-active': i === this.currentIndex,
267
+ 'is-done': i < this.currentIndex,
268
+ }, 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" })));
269
+ }
270
+ /**
271
+ * Smart page-head visibility:
272
+ * - Multi-page → always show (pill + title for progress tracking),
273
+ * unless the page explicitly hides title/description.
274
+ * - Single-page with default title "Page N" and no description → hide
275
+ * entirely; the form title block above already provides the context.
276
+ * - Single-page with a custom title or a description → show the
277
+ * relevant parts only.
278
+ * - Explicit `hideTitle` / `hideDescription` overrides on the page
279
+ * always win.
280
+ */
281
+ renderPageHead(current, isMulti) {
282
+ const titleIsDefault = !current.title || /^Page \d+$/i.test(current.title);
283
+ const customTitle = !!current.title && !titleIsDefault;
284
+ const hasDesc = !!current.description;
285
+ const wantsTitle = (customTitle || (isMulti && current.title)) && !current.hideTitle;
286
+ const wantsDesc = hasDesc && !current.hideDescription;
287
+ const wantsPill = isMulti && !current.hideTitle;
288
+ if (!wantsPill && !wantsTitle && !wantsDesc)
289
+ return null;
290
+ 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))));
291
+ }
292
+ renderScorePanel(score) {
293
+ const passText = score.passed === true ? 'Aprobado' : score.passed === false ? 'No aprobado' : null;
294
+ 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: {
295
+ 'co-form-wizard__score-pass': true,
296
+ 'is-pass': score.passed === true,
297
+ 'is-fail': score.passed === false,
298
+ } }, passText)), score.feedback.length > 0 && (h("ul", { class: "co-form-wizard__score-feedback" }, score.feedback.map((m) => (h("li", null, m)))))));
299
+ }
300
+ static get is() { return "co-form-wizard"; }
301
+ static get originalStyleUrls() {
302
+ return {
303
+ "$": ["co-form-wizard.css"]
304
+ };
305
+ }
306
+ static get styleUrls() {
307
+ return {
308
+ "$": ["co-form-wizard.css"]
309
+ };
310
+ }
311
+ static get properties() {
312
+ return {
313
+ "schema": {
314
+ "type": "string",
315
+ "mutable": false,
316
+ "complexType": {
317
+ "original": "string",
318
+ "resolved": "string",
319
+ "references": {}
320
+ },
321
+ "required": true,
322
+ "optional": false,
323
+ "docs": {
324
+ "tags": [],
325
+ "text": "JSON schema string. Can be paged or flat."
326
+ },
327
+ "getter": false,
328
+ "setter": false,
329
+ "reflect": false,
330
+ "attribute": "schema"
331
+ },
332
+ "initialValues": {
333
+ "type": "string",
334
+ "mutable": false,
335
+ "complexType": {
336
+ "original": "string",
337
+ "resolved": "string | undefined",
338
+ "references": {}
339
+ },
340
+ "required": false,
341
+ "optional": true,
342
+ "docs": {
343
+ "tags": [],
344
+ "text": "Initial values across all pages, JSON-encoded."
345
+ },
346
+ "getter": false,
347
+ "setter": false,
348
+ "reflect": false,
349
+ "attribute": "initial-values"
350
+ },
351
+ "locale": {
352
+ "type": "string",
353
+ "mutable": false,
354
+ "complexType": {
355
+ "original": "'en' | 'es' | 'pt'",
356
+ "resolved": "\"en\" | \"es\" | \"pt\"",
357
+ "references": {}
358
+ },
359
+ "required": false,
360
+ "optional": false,
361
+ "docs": {
362
+ "tags": [],
363
+ "text": "Locale for AJV error messages."
364
+ },
365
+ "getter": false,
366
+ "setter": false,
367
+ "reflect": false,
368
+ "attribute": "locale",
369
+ "defaultValue": "'es'"
370
+ },
371
+ "layout": {
372
+ "type": "string",
373
+ "mutable": false,
374
+ "complexType": {
375
+ "original": "'grid' | 'stack'",
376
+ "resolved": "\"grid\" | \"stack\"",
377
+ "references": {}
378
+ },
379
+ "required": false,
380
+ "optional": false,
381
+ "docs": {
382
+ "tags": [],
383
+ "text": "Layout passed to each page's <co-form>."
384
+ },
385
+ "getter": false,
386
+ "setter": false,
387
+ "reflect": false,
388
+ "attribute": "layout",
389
+ "defaultValue": "'grid'"
390
+ },
391
+ "columns": {
392
+ "type": "number",
393
+ "mutable": false,
394
+ "complexType": {
395
+ "original": "1 | 2 | 3 | 4",
396
+ "resolved": "1 | 2 | 3 | 4",
397
+ "references": {}
398
+ },
399
+ "required": false,
400
+ "optional": false,
401
+ "docs": {
402
+ "tags": [],
403
+ "text": "Number of columns per page."
404
+ },
405
+ "getter": false,
406
+ "setter": false,
407
+ "reflect": false,
408
+ "attribute": "columns",
409
+ "defaultValue": "1"
410
+ },
411
+ "theme": {
412
+ "type": "string",
413
+ "mutable": false,
414
+ "complexType": {
415
+ "original": "string",
416
+ "resolved": "string | undefined",
417
+ "references": {}
418
+ },
419
+ "required": false,
420
+ "optional": true,
421
+ "docs": {
422
+ "tags": [],
423
+ "text": "Theme overrides. Forwarded to each page's `<co-form>`. The wizard\nitself reads `theme` from the parsed paged schema if not supplied\nhere so authors can ship a single bundled schema."
424
+ },
425
+ "getter": false,
426
+ "setter": false,
427
+ "reflect": false,
428
+ "attribute": "theme"
429
+ }
430
+ };
431
+ }
432
+ static get states() {
433
+ return {
434
+ "currentIndex": {},
435
+ "values": {},
436
+ "finalScore": {},
437
+ "themeStyles": {},
438
+ "hasBg": {}
439
+ };
440
+ }
441
+ static get events() {
442
+ return [{
443
+ "method": "coSubmit",
444
+ "name": "coSubmit",
445
+ "bubbles": true,
446
+ "cancelable": true,
447
+ "composed": true,
448
+ "docs": {
449
+ "tags": [],
450
+ "text": ""
451
+ },
452
+ "complexType": {
453
+ "original": "{ values: Record<string, any>; score?: ScoreResult }",
454
+ "resolved": "{ values: Record<string, any>; score?: ScoreResult | undefined; }",
455
+ "references": {
456
+ "Record": {
457
+ "location": "global",
458
+ "id": "global::Record"
459
+ },
460
+ "ScoreResult": {
461
+ "location": "import",
462
+ "path": "@prolibu-suite/cobalt-form-core",
463
+ "id": "../form-core/dist/index.d.ts::ScoreResult",
464
+ "referenceLocation": "ScoreResult"
465
+ }
466
+ }
467
+ }
468
+ }, {
469
+ "method": "coPageChange",
470
+ "name": "coPageChange",
471
+ "bubbles": true,
472
+ "cancelable": true,
473
+ "composed": true,
474
+ "docs": {
475
+ "tags": [],
476
+ "text": ""
477
+ },
478
+ "complexType": {
479
+ "original": "{ index: number; page: PageDefinition }",
480
+ "resolved": "{ index: number; page: PageDefinition; }",
481
+ "references": {
482
+ "PageDefinition": {
483
+ "location": "import",
484
+ "path": "@prolibu-suite/cobalt-form-core",
485
+ "id": "../form-core/dist/index.d.ts::PageDefinition",
486
+ "referenceLocation": "PageDefinition"
487
+ }
488
+ }
489
+ }
490
+ }];
491
+ }
492
+ static get elementRef() { return "host"; }
493
+ static get watchers() {
494
+ return [{
495
+ "propName": "schema",
496
+ "methodName": "onSchemaChange"
497
+ }, {
498
+ "propName": "theme",
499
+ "methodName": "onThemeChange"
500
+ }];
501
+ }
502
+ }
@@ -0,0 +1,11 @@
1
+ import type { Components, JSX } from "../types/components";
2
+
3
+ interface CoFormWizard extends Components.CoFormWizard, HTMLElement {}
4
+ export const CoFormWizard: {
5
+ prototype: CoFormWizard;
6
+ new (): CoFormWizard;
7
+ };
8
+ /**
9
+ * Used to define this component and all nested components recursively.
10
+ */
11
+ export const defineCustomElement: () => void;
@@ -0,0 +1 @@
1
+ import{t as a,d as r,p as o,H as t,c as e,a as i,b as c,r as s,e as d,f as n,g as l,h as m,i as f}from"./index.js";function p(a){try{return JSON.parse(a)}catch(a){return null}}const h=o(class extends t{constructor(a){super(),!1!==a&&this.__registerHost(),this.coSubmit=e(this,"coSubmit"),this.coPageChange=e(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=i(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?p(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?p(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 e=0;for(t=Object.getOwnPropertySymbols(a);e<t.length;e++)r.indexOf(t[e])<0&&Object.prototype.propertyIsEnumerable.call(a,t[e])&&(o[t[e]]=a[t[e]])}return o}(r,["background"]);return JSON.stringify(o)}get activePages(){return this.paged.pages.filter((a=>!a.visibleIf||l(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 m(f,Object.assign({},this.hostProps()),m("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 m(f,Object.assign({},this.hostProps()),this.renderScorePanel(this.finalScore));const o=r[this.currentIndex],t=0===this.currentIndex,e=this.currentIndex===r.length-1,i=Object.keys(o.fields),c={};for(const a of i)a in this.values&&(c[a]=this.values[a]);return m(f,Object.assign({},this.hostProps()),this.renderInner(r,o,t,e,c))}renderInner(a,r,o,t,e){var i;const c=null===(i=this.themeStyles)||void 0===i?void 0:i.customCss;return m("div",Object.assign({},this.wrapperProps()),c&&m("style",null,c),m("slot",{name:"header"},(this.paged.title||this.paged.description)&&m("header",{class:"co-form-wizard__title-block"},this.paged.title&&m("h1",{class:"co-form-wizard__title"},this.paged.title),this.paged.description&&m("p",{class:"co-form-wizard__title-desc"},this.paged.description))),a.length>1&&m("ol",{class:"co-form-wizard__stepper"},a.map(((a,r)=>m("li",{class:{"co-form-wizard__step":!0,"is-active":r===this.currentIndex,"is-done":r<this.currentIndex},key:a.name},m("button",{type:"button",class:"co-form-wizard__step-btn",onClick:()=>this.handleStepClick(r)},m("span",{class:"co-form-wizard__step-num"},r+1),m("span",{class:"co-form-wizard__step-label"},a.title||a.name)))))),m("section",{class:"co-form-wizard__page-card"},this.renderPageHead(r,a.length>1),m("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}),m("div",{class:"co-form-wizard__nav"},m("co-button",{label:"Anterior",variant:"outlined",disabled:o,onClick:this.handlePrev}),m("co-button",t?{label:"Enviar",variant:"primary",onClick:this.handleSubmit}:{label:"Siguiente",variant:"primary",onClick:this.handleNext}))),m("slot",{name:"footer"}))}renderPageHead(a,r){const o=(!!a.title&&!(!a.title||/^Page \d+$/i.test(a.title))||r&&a.title)&&!a.hideTitle,t=!!a.description&&!a.hideDescription,e=r&&!a.hideTitle;return e||o||t?m("header",{class:"co-form-wizard__page-head"},e&&m("span",{class:"co-form-wizard__page-pill"},"PAGE ",this.currentIndex+1),o&&m("h2",{class:"co-form-wizard__page-title"},a.title),t&&m("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 m("div",{class:"co-form-wizard co-form-wizard__score"},m("h2",{class:"co-form-wizard__score-title"},"Resultado"),m("div",{class:"co-form-wizard__score-num"},a.total," / ",a.max,m("span",{class:"co-form-wizard__score-pct"},"(",a.percent,"%)")),r&&m("div",{class:{"co-form-wizard__score-pass":!0,"is-pass":!0===a.passed,"is-fail":!1===a.passed}},r),a.feedback.length>0&&m("ul",{class:"co-form-wizard__score-feedback"},a.feedback.map((a=>m("li",null,a)))))}get host(){return this}static get watchers(){return{schema:[{onSchemaChange:0}],theme:[{onThemeChange:0}]}}static get style(){return':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}'}},[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]},void 0,{schema:[{onSchemaChange:0}],theme:[{onThemeChange:0}]}]);function g(){"undefined"!=typeof customElements&&["co-form-wizard","co-form"].forEach((o=>{switch(o){case"co-form-wizard":customElements.get(a(o))||customElements.define(a(o),h);break;case"co-form":customElements.get(a(o))||r()}}))}g();const b=h,u=g;export{b as CoFormWizard,u as defineCustomElement}