@kubex/zinc 1.1.27 → 1.1.29

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 (47) hide show
  1. package/custom-elements-manifest.config.js +2 -2
  2. package/dist/custom-elements.json +1556 -90
  3. package/dist/vscode.html-custom-data.json +51 -12
  4. package/dist/web-types.json +146 -25
  5. package/dist/zn.d.ts +670 -14
  6. package/dist/zn.min.js +1305 -925
  7. package/docs/eleventy.config.cjs +5 -0
  8. package/docs/pages/components/flow-builder-troubleshooter-demo.njk +106 -78
  9. package/docs/pages/components/flow-builder.md +422 -66
  10. package/docs/pages/components/page-builder.md +167 -0
  11. package/package.json +1 -1
  12. package/src/components/datepicker/datepicker.scss +0 -10
  13. package/src/components/flow-builder/flow-builder.component.ts +377 -16
  14. package/src/components/flow-builder/flow-builder.scss +398 -250
  15. package/src/components/flow-builder/flow-builder.test.ts +241 -4
  16. package/src/components/flow-builder/flow-layout.ts +42 -17
  17. package/src/components/flow-builder/flow.types.ts +168 -43
  18. package/src/components/flow-builder/modules/flow-branch-conditions/flow-branch-conditions.component.ts +300 -0
  19. package/src/components/flow-builder/modules/flow-branch-conditions/flow-branch-conditions.scss +222 -0
  20. package/src/components/flow-builder/modules/flow-branch-conditions/flow-branch-conditions.test.ts +125 -0
  21. package/src/components/flow-builder/modules/flow-branch-conditions/index.ts +12 -0
  22. package/src/components/flow-builder/modules/flow-canvas/flow-canvas.component.ts +184 -26
  23. package/src/components/flow-builder/modules/flow-canvas/flow-canvas.scss +170 -120
  24. package/src/components/flow-builder/modules/flow-node/flow-node.scss +42 -42
  25. package/src/components/flow-builder/modules/flow-step/flow-step.component.ts +2 -1
  26. package/src/components/flow-builder/modules/flow-step/flow-step.scss +25 -17
  27. package/src/components/icon-picker/icon-picker.component.ts +20 -37
  28. package/src/components/icon-picker/icon-picker.scss +5 -45
  29. package/src/components/page-builder/index.ts +14 -0
  30. package/src/components/page-builder/modules/page-palette-item/index.ts +12 -0
  31. package/src/components/page-builder/modules/page-palette-item/page-palette-item.component.ts +71 -0
  32. package/src/components/page-builder/modules/page-palette-item/page-palette-item.scss +70 -0
  33. package/src/components/page-builder/modules/page-palette-item/page-palette-item.test.ts +20 -0
  34. package/src/components/page-builder/modules/page-section-card/index.ts +12 -0
  35. package/src/components/page-builder/modules/page-section-card/page-section-card.component.ts +93 -0
  36. package/src/components/page-builder/modules/page-section-card/page-section-card.scss +92 -0
  37. package/src/components/page-builder/modules/page-section-card/page-section-card.test.ts +50 -0
  38. package/src/components/page-builder/page-builder.component.ts +1053 -0
  39. package/src/components/page-builder/page-builder.scss +494 -0
  40. package/src/components/page-builder/page-builder.test.ts +464 -0
  41. package/src/components/page-builder/page-registry.ts +48 -0
  42. package/src/components/page-builder/page.types.ts +75 -0
  43. package/src/events/events.ts +2 -0
  44. package/src/events/zn-page-change.ts +9 -0
  45. package/src/events/zn-page-selection-change.ts +7 -0
  46. package/src/zinc.ts +4 -0
  47. package/web-test-runner.config.js +6 -1
@@ -0,0 +1,167 @@
1
+ ---
2
+ meta:
3
+ title: Page Builder
4
+ description: A config-driven page composer with a palette of predefined section types, a linear canvas of section cards, and an inspector for editing each section's content.
5
+ layout: component
6
+ fullWidth: true
7
+ ---
8
+
9
+ The Page Builder composes pages from **predefined section types** the host application provides.
10
+ Editors pick sections from the palette, order them on the canvas, and edit each section's content
11
+ in the inspector — the output is a plain JSON config (`PageState`) the host persists and
12
+ renders however it likes.
13
+
14
+ Section types are declared as `<template type slot="config">` children. The template's attributes
15
+ (`type`, `label`, `icon`, `icon-library`, `color`, `category`, `description`) define the palette
16
+ entry; its content is stamped into the inspector when a section of that type is selected. Controls
17
+ are bound by their `name` attribute: values prefill from the section's data and write back on
18
+ `change` / `zn-change`.
19
+
20
+ ```html:preview
21
+ <zn-page-builder id="kb-homepage-demo" heading="KB Homepage" subheading="Last updated 7th July 2026" auto-save style="height: 560px">
22
+ <zn-button slot="header-left" icon="refresh-cw@lu" panel-bg
23
+ onclick="this.closest('zn-page-builder').undo()">Undo</zn-button>
24
+ <zn-button slot="header-right" icon="check@lu" color="primary"
25
+ onclick="alert(JSON.stringify(this.closest('zn-page-builder').state, null, 2))">Save All Changes</zn-button>
26
+ <template type="hero" slot="config" label="Hero" icon="star" category="Headers"
27
+ description="Large banner with optional search">
28
+ <zn-input name="title" label="Title"></zn-input>
29
+ <zn-input name="subtitle" label="Subtitle"></zn-input>
30
+ </template>
31
+ <template type="article-list" slot="config" label="Article List" icon="list" category="Content"
32
+ description="A list of KB articles">
33
+ <zn-input name="limit" type="number" label="Max articles"></zn-input>
34
+ </template>
35
+ </zn-page-builder>
36
+ ```
37
+
38
+ Listen for `zn-page-change` to persist the config, or read/write the `state` property.
39
+ Types can also be registered programmatically via `sectionTypes` /
40
+ `registerSectionTypes()`, including a `renderConfig(section, update)` callback for
41
+ inspector bodies that need real logic.
42
+
43
+ ## JavaScript API
44
+
45
+ - `state` — get/set the current `PageState`. The getter returns a deep copy; the setter
46
+ replaces the state wholesale (like the `config` attribute, it does not emit `zn-page-change`).
47
+ - `addSection(type, index?)` — insert a new section of a registered type (default: at the end).
48
+ - `addSectionToSlot(type, containerId, slotIndex)` — insert into a container's empty slot,
49
+ honouring its `accepts` list. Returns the new section, or `null` if not allowed.
50
+ - `undo()` / `redo()` — step through edit history (bounded at 50 entries). There is no built-in
51
+ toolbar: wire these to your own header buttons or keyboard shortcuts.
52
+ - `registerSectionType(type)` / `registerSectionTypes(types)` — programmatic registration,
53
+ equivalent to slotting templates. Registration is additive — removing an entry from
54
+ `sectionTypes` later does not unregister it.
55
+ - `restoreAutoSave()` — load the auto-saved draft, if one exists within its 1-day TTL
56
+ (returns `false` otherwise). See Saving below.
57
+
58
+ ## Saving
59
+
60
+ Wire your own save action into the header slots (rendered only when filled, as in the
61
+ flow builder) and read `state` — or persist on every `zn-page-change`:
62
+
63
+ ```html
64
+ <zn-page-builder id="kb-home" heading="KB Homepage" auto-save>
65
+ <zn-button slot="header-right" color="primary" id="save-page">Save All Changes</zn-button>
66
+ <!-- templates… -->
67
+ </zn-page-builder>
68
+ <script>
69
+ const builder = document.querySelector('#kb-home');
70
+ document.querySelector('#save-page').addEventListener('click', () => {
71
+ fetch('/api/pages/home', {method: 'PUT', body: JSON.stringify(builder.state)});
72
+ });
73
+ </script>
74
+ ```
75
+
76
+ Add the `auto-save` attribute to also snapshot the page into localStorage, keyed by the
77
+ builder's `id` (falling back to its `heading`), with a **1-day TTL** — identical to the
78
+ flow builder's auto-save:
79
+
80
+ ```html
81
+ <zn-page-builder id="kb-home" auto-save></zn-page-builder> <!-- every 5 minutes -->
82
+ <zn-page-builder id="kb-home" auto-save="2"></zn-page-builder> <!-- every 2 minutes -->
83
+ ```
84
+
85
+ Without the attribute nothing is saved, and an empty page is never written. While auto-save
86
+ is on, a status pill in the canvas's bottom-left flashes "Auto-saved" as each snapshot lands
87
+ and otherwise shows how long ago the last one happened. When a page is loaded (`config` /
88
+ `state`) that differs from a fresh auto-saved draft, a banner offers to restore the draft —
89
+ or call `restoreAutoSave()` yourself.
90
+
91
+ ## The config
92
+
93
+ Every edit emits `zn-page-change` with the full page state (`event.detail.state`, also
94
+ readable via the `state` property) — plain JSON the host persists and later feeds back in
95
+ through the `config` attribute. Sections appear in page order; container sections carry a
96
+ `children` array sized to their slot count, with `null` for empty slots:
97
+
98
+ ```json
99
+ {
100
+ "sections": [
101
+ {
102
+ "id": "s-mc41z-0",
103
+ "type": "hero",
104
+ "data": {"title": "Help Centre", "showSearch": true}
105
+ },
106
+ {
107
+ "id": "s-mc42a-1",
108
+ "type": "article-grid",
109
+ "label": "Popular articles",
110
+ "data": {"title": "Popular"},
111
+ "children": [
112
+ {"id": "s-mc42h-2", "type": "article-tile", "data": {"article": "art_42"}},
113
+ {"id": "s-mc42p-3", "type": "article-tile", "data": {"article": "art_7"}},
114
+ null, null, null, null
115
+ ]
116
+ },
117
+ {
118
+ "id": "s-mc43b-4",
119
+ "type": "article-list",
120
+ "data": {"articles": ["art_1", "art_3"]}
121
+ }
122
+ ]
123
+ }
124
+ ```
125
+
126
+ ## Container tiles
127
+
128
+ A section type with a `slots` attribute becomes a full-row container: its card renders a
129
+ 3-column grid of that many child slots beneath it. Drag sections from the palette into empty
130
+ cells, drag children **between cells to reorder**, or out onto the page. `accepts` restricts
131
+ which types the slots take. Containers can't be placed inside other containers, and slot
132
+ contents persist as `children` on the section (empty slots are `null`).
133
+
134
+ ```html:preview
135
+ <zn-page-builder heading="KB Homepage" style="height: 560px"
136
+ config='{"sections":[{"id":"g1","type":"article-grid","data":{}}]}'>
137
+ <template type="article-grid" slot="config" label="Article Grid" icon="grid_view"
138
+ category="Layout" description="A 3x2 grid of article tiles"
139
+ slots="6" accepts="article-tile">
140
+ <zn-input name="title" label="Grid title"></zn-input>
141
+ </template>
142
+ <template type="article-tile" slot="config" label="Article" icon="article" category="Content"
143
+ description="A single article tile">
144
+ <zn-input name="article" label="Article id"></zn-input>
145
+ </template>
146
+ </zn-page-builder>
147
+ ```
148
+
149
+ ## List sections
150
+
151
+ Sections that show a set of existing items (categories, articles, …) reference them by id:
152
+ bind a multi-select by `name` and the chosen ids persist as an array in the section's data
153
+ (e.g. `"data": {"articles": ["art_42", "art_7"]}`). Options can be inlined as below, or loaded
154
+ from a backend with `<zn-data-select multiple>`.
155
+
156
+ ```html:preview
157
+ <zn-page-builder heading="KB Category Page" style="height: 420px">
158
+ <template type="article-list" slot="config" label="Article List" icon="list"
159
+ description="Shows a chosen set of KB articles">
160
+ <zn-select multiple name="articles" label="Articles to show">
161
+ <zn-option value="art_1">How to reset your password</zn-option>
162
+ <zn-option value="art_2">Billing FAQ</zn-option>
163
+ <zn-option value="art_3">Getting started guide</zn-option>
164
+ </zn-select>
165
+ </template>
166
+ </zn-page-builder>
167
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubex/zinc",
3
- "version": "1.1.27",
3
+ "version": "1.1.29",
4
4
  "description": "A collection of web components for building web applications based off of @shoelace-style/Shoelace",
5
5
  "keywords": [
6
6
  "web components",
@@ -187,11 +187,6 @@
187
187
  width: calc(1em + var(--zn-input-spacing-medium) * 2);
188
188
  }
189
189
 
190
- .input--medium .input__prefix ::slotted(*),
191
- .input__prefix-default {
192
- margin-inline-start: var(--zn-input-spacing-medium);
193
- }
194
-
195
190
  .input--medium .input__suffix ::slotted(*),
196
191
  .input__suffix-default {
197
192
  margin-inline-end: var(--zn-input-spacing-medium);
@@ -219,11 +214,6 @@
219
214
  width: calc(1em + var(--zn-input-spacing-large) * 2);
220
215
  }
221
216
 
222
- .input--large .input__prefix ::slotted(*),
223
- .input__prefix-default {
224
- margin-inline-start: var(--zn-input-spacing-large);
225
- }
226
-
227
217
  .input--large .input__suffix ::slotted(*),
228
218
  .input__suffix-default {
229
219
  margin-inline-end: var(--zn-input-spacing-large);