@kubex/zinc 1.1.68 → 1.1.70

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 (37) hide show
  1. package/dist/custom-elements.json +1719 -282
  2. package/dist/vscode.html-custom-data.json +160 -29
  3. package/dist/web-types.json +395 -70
  4. package/dist/zn.d.ts +395 -16
  5. package/dist/zn.min.js +580 -408
  6. package/docs/pages/components/collapsible.md +6 -2
  7. package/docs/pages/components/icon-picker.md +14 -0
  8. package/docs/pages/components/input.md +19 -1
  9. package/docs/pages/components/preview-frame-demo.njk +33 -4
  10. package/docs/pages/components/preview-frame.md +20 -0
  11. package/docs/pages/components/theme-editor.md +303 -0
  12. package/docs/superpowers/plans/2026-08-03-theme-editor.md +1536 -0
  13. package/docs/superpowers/specs/2026-08-03-theme-editor-design.md +327 -0
  14. package/package.json +1 -1
  15. package/src/components/collapsible/collapsible.component.ts +21 -23
  16. package/src/components/dropdown/dropdown.component.ts +9 -0
  17. package/src/components/editor/editor.component.ts +20 -21
  18. package/src/components/file/file.component.ts +15 -0
  19. package/src/components/icon-picker/icon-picker.component.ts +150 -16
  20. package/src/components/icon-picker/icon-picker.scss +32 -0
  21. package/src/components/input/input.component.ts +44 -21
  22. package/src/components/input/input.scss +134 -42
  23. package/src/components/input/input.test.ts +45 -0
  24. package/src/components/preview-frame/preview-frame.component.ts +126 -16
  25. package/src/components/preview-frame/preview-frame.scss +27 -0
  26. package/src/components/preview-frame/preview-frame.test.ts +253 -0
  27. package/src/components/theme-editor/index.ts +12 -0
  28. package/src/components/theme-editor/theme-editor.component.ts +918 -0
  29. package/src/components/theme-editor/theme-editor.scss +309 -0
  30. package/src/components/theme-editor/theme-editor.test.ts +1752 -0
  31. package/src/events/events.ts +2 -0
  32. package/src/events/zn-theme-change.ts +13 -0
  33. package/src/events/zn-theme-submit.ts +9 -0
  34. package/src/types/web-test-runner-commands.d.ts +6 -0
  35. package/src/zinc.ts +1 -0
  36. package/tsconfig.json +7 -1
  37. package/web-test-runner.config.js +3 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json",
3
3
  "name": "@kubex/zinc",
4
- "version": "1.1.68",
4
+ "version": "1.1.70",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
@@ -1663,7 +1663,7 @@
1663
1663
  },
1664
1664
  {
1665
1665
  "name": "zn-collapsible",
1666
- "description": "Toggles between showing and hiding content when clicked\n---\n\n\n### **Slots:**\n - **header** - Clicking will toggle the show state of the data\n\n### **CSS Parts:**\n - **header** - The header row (toggle).\n- **caption** - The caption text.",
1666
+ "description": "Toggles between showing and hiding content when clicked\n---\n\n\n### **Slots:**\n - **header** - Clicking will toggle the show state of the data\n\n### **CSS Parts:**\n - **header** - The header row (toggle).\n- **caption** - The caption text.\n- **content** - The expandable content wrapper.",
1667
1667
  "doc-url": "",
1668
1668
  "attributes": [
1669
1669
  {
@@ -3663,7 +3663,7 @@
3663
3663
  },
3664
3664
  {
3665
3665
  "name": "zn-file",
3666
- "description": "File controls allow selecting an arbitrary number of files for uploading.\n---\n\n\n### **Events:**\n - **zn-blur** - Emitted when the control loses focus.\n- **zn-change** - Emitted when an alteration to the control's value is committed by the user.\n- **zn-clear** - Emitted when the user confirms clearing the selected file or `src`.\n- **zn-error** - Emitted when multiple files are selected via drag and drop, without the `multiple` property being set.\n- **zn-focus** - Emitted when the control gains focus.\n- **zn-input** - Emitted when the control receives input.\n\n### **Methods:**\n - **checkValidity()** - Checks for validity but does not show a validation message.\nReturns `true` when valid and `false` when invalid.\n- **getForm(): _HTMLFormElement | null_** - Gets the associated form, if one exists.\n- **reportValidity()** - Checks for validity and shows the browser's validation message if the control is invalid.\n- **setCustomValidity(message: _string_)** - Sets a custom validation message. Pass an empty string to restore validity.\n- **focus(options: _FocusOptions_)** - Sets focus on the button or droparea.\n- **blur()** - Removes focus from the button or droparea.\n\n### **Slots:**\n - **label** - The file control's label. Alternatively, you can use the `label` attribute.\n- **help-text** - Text that describes how to use the file control. Alternatively, you can use the `help-text` attribute.\n- **trigger** - Optional content to be used as trigger instead of the default content. Opening the file dialog on click and as well as drag and drop will work for this content. Following attributes will no longer work: *label*, *droparea*, *help-text*, *size*, *hide-value*. Also if using the disabled attribute, the disabled styling will not be applied and must be taken care of yourself.\n\n### **CSS Parts:**\n - **form-control** - The form control that wraps the label, input, and help text.\n- **form-control-label** - The label's wrapper.\n- **form-control-input** - The input's wrapper.\n- **form-control-help-text** - The help text's wrapper.\n- **button-wrapper** - The wrapper around the button and text value.\n- **button** - The zn-button acting as a file input.\n- **button__base** - The zn-button's exported `base` part.\n- **value** - The chosen files or placeholder text for the file input.\n- **droparea** - The element wrapping the drop zone.\n- **droparea-background** - The background of the drop zone.\n- **upload** - The upload button shown in the droparea when no file is selected.\n- **preview** - The image preview rendered in the droparea for previewable files.\n- **filename** - The filename label rendered in the droparea for non-previewable files.\n- **clear** - The clear button rendered in the droparea when a file is present.\n- **clear-confirm** - The confirmation dialog shown before clearing the file.\n- **link** - The current link anchor rendered when `show-link` is enabled.\n- **trigger** - The container that wraps the trigger.",
3666
+ "description": "File controls allow selecting an arbitrary number of files for uploading.\n---\n\n\n### **Events:**\n - **zn-blur** - Emitted when the control loses focus.\n- **zn-change** - Emitted when an alteration to the control's value is committed by the user.\n- **zn-clear** - Emitted when the user confirms clearing the selected file or `src`.\n- **zn-error** - Emitted when multiple files are selected via drag and drop, without the `multiple` property being set.\n- **zn-focus** - Emitted when the control gains focus.\n- **zn-input** - Emitted when the control receives input.\n\n### **Methods:**\n - **checkValidity()** - Checks for validity but does not show a validation message.\nReturns `true` when valid and `false` when invalid.\n- **getForm(): _HTMLFormElement | null_** - Gets the associated form, if one exists.\n- **reportValidity()** - Checks for validity and shows the browser's validation message if the control is invalid.\n- **setCustomValidity(message: _string_)** - Sets a custom validation message. Pass an empty string to restore validity.\n- **focus(options: _FocusOptions_)** - Sets focus on the button or droparea.\n- **blur()** - Removes focus from the button or droparea.\n- **clear()** - Programmatically clears the selected file and any external `src` without\nconfirmation. Unlike a user-initiated clear, this does not flag the control\nto submit an empty value.\n\n### **Slots:**\n - **label** - The file control's label. Alternatively, you can use the `label` attribute.\n- **help-text** - Text that describes how to use the file control. Alternatively, you can use the `help-text` attribute.\n- **trigger** - Optional content to be used as trigger instead of the default content. Opening the file dialog on click and as well as drag and drop will work for this content. Following attributes will no longer work: *label*, *droparea*, *help-text*, *size*, *hide-value*. Also if using the disabled attribute, the disabled styling will not be applied and must be taken care of yourself.\n\n### **CSS Parts:**\n - **form-control** - The form control that wraps the label, input, and help text.\n- **form-control-label** - The label's wrapper.\n- **form-control-input** - The input's wrapper.\n- **form-control-help-text** - The help text's wrapper.\n- **button-wrapper** - The wrapper around the button and text value.\n- **button** - The zn-button acting as a file input.\n- **button__base** - The zn-button's exported `base` part.\n- **value** - The chosen files or placeholder text for the file input.\n- **droparea** - The element wrapping the drop zone.\n- **droparea-background** - The background of the drop zone.\n- **upload** - The upload button shown in the droparea when no file is selected.\n- **preview** - The image preview rendered in the droparea for previewable files.\n- **filename** - The filename label rendered in the droparea for non-previewable files.\n- **clear** - The clear button rendered in the droparea when a file is present.\n- **clear-confirm** - The confirmation dialog shown before clearing the file.\n- **link** - The current link anchor rendered when `show-link` is enabled.\n- **trigger** - The container that wraps the trigger.",
3667
3667
  "doc-url": "",
3668
3668
  "attributes": [
3669
3669
  {
@@ -4207,6 +4207,63 @@
4207
4207
  "events": []
4208
4208
  }
4209
4209
  },
4210
+ {
4211
+ "name": "zn-header",
4212
+ "description": "Short summary of the component's intended use.\n---\n\n\n### **Events:**\n - **zn-event-name** - Emitted as an example.\n\n### **Slots:**\n - _default_ - The default slot.\n- **example** - An example slot.\n\n### **CSS Properties:**\n - **--example** - An example CSS custom property. _(default: undefined)_\n\n### **CSS Parts:**\n - **base** - The component's base wrapper.",
4213
+ "doc-url": "",
4214
+ "attributes": [
4215
+ { "name": "full-location", "value": { "type": "string" } },
4216
+ { "name": "entity-id", "value": { "type": "string" } },
4217
+ { "name": "entity-id-show", "value": { "type": "boolean" } },
4218
+ {
4219
+ "name": "transparent",
4220
+ "value": { "type": "boolean", "default": "false" }
4221
+ },
4222
+ { "name": "caption", "value": { "type": "string" } },
4223
+ { "name": "icon", "value": { "type": "string" } },
4224
+ {
4225
+ "name": "navigation",
4226
+ "value": { "type": "array", "default": "[]" }
4227
+ },
4228
+ { "name": "full-width", "value": { "type": "boolean" } },
4229
+ { "name": "previous-path", "value": { "type": "string" } },
4230
+ { "name": "previous-target", "value": { "type": "string" } },
4231
+ {
4232
+ "name": "hide-breadcrumb",
4233
+ "value": { "type": "boolean", "default": "false" }
4234
+ }
4235
+ ],
4236
+ "slots": [
4237
+ { "name": "", "description": "The default slot." },
4238
+ { "name": "example", "description": "An example slot." }
4239
+ ],
4240
+ "events": [
4241
+ { "name": "zn-event-name", "description": "Emitted as an example." }
4242
+ ],
4243
+ "js": {
4244
+ "properties": [
4245
+ { "name": "fullLocation", "type": "string" },
4246
+ { "name": "entityId", "type": "string" },
4247
+ { "name": "entityIdShow", "type": "boolean" },
4248
+ { "name": "transparent", "type": "boolean" },
4249
+ { "name": "caption", "type": "string" },
4250
+ { "name": "icon", "type": "string" },
4251
+ { "name": "navigation", "type": "array" },
4252
+ { "name": "fullWidth", "type": "boolean" },
4253
+ { "name": "previousPath", "type": "string" },
4254
+ { "name": "previousTarget", "type": "string" },
4255
+ { "name": "hideBreadcrumb", "type": "boolean" },
4256
+ { "name": "handleAltPress" },
4257
+ { "name": "handleAltUp" }
4258
+ ],
4259
+ "events": [
4260
+ {
4261
+ "name": "zn-event-name",
4262
+ "description": "Emitted as an example."
4263
+ }
4264
+ ]
4265
+ }
4266
+ },
4210
4267
  {
4211
4268
  "name": "zn-hover-container",
4212
4269
  "description": "The HoverContainer component is used to display additional information when a user hovers over or clicks\non an element.\n---\n\n\n### **Events:**\n - **zn-show** - Emitted when the hover-container is shown.\n- **zn-after-show** - Emitted after the hover-container is shown.\n- **zn-hide** - Emitted when the hover-container is hidden.\n- **zn-after-hide** - Emitted after the hover-container is hidden.\n\n### **Slots:**\n - _default_ - The content of the hover-container\n- **anchor** - The anchor the hover-container is attached to.",
@@ -4310,63 +4367,6 @@
4310
4367
  ]
4311
4368
  }
4312
4369
  },
4313
- {
4314
- "name": "zn-header",
4315
- "description": "Short summary of the component's intended use.\n---\n\n\n### **Events:**\n - **zn-event-name** - Emitted as an example.\n\n### **Slots:**\n - _default_ - The default slot.\n- **example** - An example slot.\n\n### **CSS Properties:**\n - **--example** - An example CSS custom property. _(default: undefined)_\n\n### **CSS Parts:**\n - **base** - The component's base wrapper.",
4316
- "doc-url": "",
4317
- "attributes": [
4318
- { "name": "full-location", "value": { "type": "string" } },
4319
- { "name": "entity-id", "value": { "type": "string" } },
4320
- { "name": "entity-id-show", "value": { "type": "boolean" } },
4321
- {
4322
- "name": "transparent",
4323
- "value": { "type": "boolean", "default": "false" }
4324
- },
4325
- { "name": "caption", "value": { "type": "string" } },
4326
- { "name": "icon", "value": { "type": "string" } },
4327
- {
4328
- "name": "navigation",
4329
- "value": { "type": "array", "default": "[]" }
4330
- },
4331
- { "name": "full-width", "value": { "type": "boolean" } },
4332
- { "name": "previous-path", "value": { "type": "string" } },
4333
- { "name": "previous-target", "value": { "type": "string" } },
4334
- {
4335
- "name": "hide-breadcrumb",
4336
- "value": { "type": "boolean", "default": "false" }
4337
- }
4338
- ],
4339
- "slots": [
4340
- { "name": "", "description": "The default slot." },
4341
- { "name": "example", "description": "An example slot." }
4342
- ],
4343
- "events": [
4344
- { "name": "zn-event-name", "description": "Emitted as an example." }
4345
- ],
4346
- "js": {
4347
- "properties": [
4348
- { "name": "fullLocation", "type": "string" },
4349
- { "name": "entityId", "type": "string" },
4350
- { "name": "entityIdShow", "type": "boolean" },
4351
- { "name": "transparent", "type": "boolean" },
4352
- { "name": "caption", "type": "string" },
4353
- { "name": "icon", "type": "string" },
4354
- { "name": "navigation", "type": "array" },
4355
- { "name": "fullWidth", "type": "boolean" },
4356
- { "name": "previousPath", "type": "string" },
4357
- { "name": "previousTarget", "type": "string" },
4358
- { "name": "hideBreadcrumb", "type": "boolean" },
4359
- { "name": "handleAltPress" },
4360
- { "name": "handleAltUp" }
4361
- ],
4362
- "events": [
4363
- {
4364
- "name": "zn-event-name",
4365
- "description": "Emitted as an example."
4366
- }
4367
- ]
4368
- }
4369
- },
4370
4370
  {
4371
4371
  "name": "zn-icon",
4372
4372
  "description": "Short summary of the component's intended use.\n---\n\n\n### **Events:**\n - **zn-event-name** - Emitted as an example.\n\n### **Slots:**\n - _default_ - The default slot.\n- **example** - An example slot.\n\n### **CSS Properties:**\n - **--example** - An example CSS custom property. _(default: undefined)_\n\n### **CSS Parts:**\n - **base** - The component's base wrapper.",
@@ -4445,7 +4445,10 @@
4445
4445
  { "name": "label", "value": { "type": "string", "default": "''" } },
4446
4446
  {
4447
4447
  "name": "library",
4448
- "value": { "type": "string", "default": "'material'" }
4448
+ "value": {
4449
+ "type": "string",
4450
+ "default": "'material-symbols-outlined'"
4451
+ }
4449
4452
  },
4450
4453
  { "name": "color", "value": { "type": "string", "default": "''" } },
4451
4454
  {
@@ -4468,6 +4471,18 @@
4468
4471
  "name": "required",
4469
4472
  "value": { "type": "boolean", "default": "false" }
4470
4473
  },
4474
+ {
4475
+ "name": "trigger-submit",
4476
+ "value": { "type": "boolean", "default": "false" }
4477
+ },
4478
+ {
4479
+ "name": "allow-upload",
4480
+ "value": { "type": "boolean", "default": "false" }
4481
+ },
4482
+ {
4483
+ "name": "accept",
4484
+ "value": { "type": "string", "default": "'image/*'" }
4485
+ },
4471
4486
  { "name": "form", "value": { "type": "string" } }
4472
4487
  ],
4473
4488
  "events": [],
@@ -4483,9 +4498,22 @@
4483
4498
  { "name": "helpText", "type": "string" },
4484
4499
  { "name": "disabled", "type": "boolean" },
4485
4500
  { "name": "required", "type": "boolean" },
4501
+ { "name": "triggerSubmit", "type": "boolean" },
4502
+ { "name": "allowUpload", "type": "boolean" },
4503
+ { "name": "accept", "type": "string" },
4486
4504
  { "name": "form", "type": "string" },
4487
4505
  { "name": "defaultValue", "type": "string" },
4488
4506
  { "name": "value", "type": "string" },
4507
+ {
4508
+ "name": "file",
4509
+ "description": "The chosen file when the user uploaded an image instead of picking an icon.",
4510
+ "type": "File | null"
4511
+ },
4512
+ {
4513
+ "name": "isImageValue",
4514
+ "description": "True when the current value renders as an image (an uploaded file or a URL) rather than a library icon.",
4515
+ "type": "boolean"
4516
+ },
4489
4517
  { "name": "validity", "type": "ValidityState" },
4490
4518
  { "name": "validationMessage", "type": "string" }
4491
4519
  ],
@@ -4702,7 +4730,7 @@
4702
4730
  },
4703
4731
  {
4704
4732
  "name": "zn-input",
4705
- "description": "Short summary of the component's intended use.\n---\n\n\n### **Events:**\n - **zn-blur** - Emitted when the control loses focus.\n- **zn-change** - Emitted when an alteration to the control's value is committed by the user.\n- **zn-clear** - Emitted when the clear button is activated.\n- **zn-focus** - Emitted when the control gains focus.\n- **zn-input** - Emitted when the control receives input.\n- **zn-invalid** - Emitted when the form control has been checked for validity and its constraints aren't satisfied.\n\n### **Methods:**\n - **focus(options: _FocusOptions_)** - Sets focus on the input.\n- **blur()** - Removes focus from the input.\n- **select()** - Selects all the text in the input.\n- **setSelectionRange(selectionStart: _number_, selectionEnd: _number_, selectionDirection: _'forward' | 'backward' | 'none'_)** - Sets the start and end positions of the text selection (0-based).\n- **setRangeText(replacement: _string_, start: _number_, end: _number_, selectMode: _'select' | 'start' | 'end' | 'preserve'_)** - Replaces a range of text with a new string.\n- **showPicker()** - Displays the browser picker for an input element (only works if the browser supports it for the input type).\n- **stepUp()** - Increments the value of a numeric input type by the value of the step attribute.\n- **stepDown()** - Decrements the value of a numeric input type by the value of the step attribute.\n- **checkValidity(): _boolean_** - Checks the validity but does not show a validation message. Returns `true` when valid and `false` when invalid.\n- **getForm(): _HTMLFormElement | null_** - Gets the associated form, if one exists.\n- **reportValidity()** - Checks for validity and shows the browser's validation message if the control is invalid.\n- **setCustomValidity(message: _string_)** - Sets a custom validation message. Pass an empty string to restore validity.\n\n### **Slots:**\n - **label** - The input's label. Alternatively, you can use the `label` attribute.\n- **label-tooltip** - Used to add text that is displayed in a tooltip next to the label. Alternatively, you can use the `label-tooltip` attribute.\n- **context-note** - Used to add contextual text that is displayed above the input, on the right. Alternatively, you can use the `context-note` attribute.\n- **prefix** - Used to prepend a presentational icon or similar element to the input.\n- **suffix** - Used to append a presentational icon or similar element to the input.\n- **clear-icon** - An icon to use in lieu of the default clear icon.\n- **show-password-icon** - An icon to use in lieu of the default show password icon.\n- **hide-password-icon** - An icon to use in lieu of the default hide password icon.\n- **help-text** - Text that describes how to use the input. Alternatively, you can use the `help-text` attribute.\n\n### **CSS Parts:**\n - **form-control** - The form control that wraps the label, input, and help text.\n- **form-control-label** - The label's wrapper.\n- **form-control-input** - The input's wrapper.\n- **form-control-help-text** - The help text's wrapper.\n- **base** - The component's base wrapper.\n- **input** - The internal `<input>` control.\n- **prefix** - The container that wraps the prefix.\n- **clear-button** - The clear button.\n- **password-toggle-button** - The password toggle button.\n- **suffix** - The container that wraps the suffix.",
4733
+ "description": "Short summary of the component's intended use.\n---\n\n\n### **Events:**\n - **zn-blur** - Emitted when the control loses focus.\n- **zn-change** - Emitted when an alteration to the control's value is committed by the user.\n- **zn-clear** - Emitted when the clear button is activated.\n- **zn-focus** - Emitted when the control gains focus.\n- **zn-input** - Emitted when the control receives input.\n- **zn-invalid** - Emitted when the form control has been checked for validity and its constraints aren't satisfied.\n\n### **Methods:**\n - **focus(options: _FocusOptions_)** - Sets focus on the input.\n- **blur()** - Removes focus from the input.\n- **select()** - Selects all the text in the input.\n- **setSelectionRange(selectionStart: _number_, selectionEnd: _number_, selectionDirection: _'forward' | 'backward' | 'none'_)** - Sets the start and end positions of the text selection (0-based).\n- **setRangeText(replacement: _string_, start: _number_, end: _number_, selectMode: _'select' | 'start' | 'end' | 'preserve'_)** - Replaces a range of text with a new string.\n- **showPicker()** - Displays the browser picker for an input element (only works if the browser supports it for the input type).\n- **stepUp()** - Increments the value of a numeric input type by the value of the step attribute.\n- **stepDown()** - Decrements the value of a numeric input type by the value of the step attribute.\n- **checkValidity(): _boolean_** - Checks the validity but does not show a validation message. Returns `true` when valid and `false` when invalid.\n- **getForm(): _HTMLFormElement | null_** - Gets the associated form, if one exists.\n- **reportValidity()** - Checks for validity and shows the browser's validation message if the control is invalid.\n- **setCustomValidity(message: _string_)** - Sets a custom validation message. Pass an empty string to restore validity.\n\n### **Slots:**\n - **label** - The input's label. Alternatively, you can use the `label` attribute.\n- **label-tooltip** - Used to add text that is displayed in a tooltip next to the label. Alternatively, you can use the `label-tooltip` attribute.\n- **context-note** - Used to add contextual text that is displayed above the input, on the right. Alternatively, you can use the `context-note` attribute. Range inputs display their live value here unless this is set.\n- **prefix** - Used to prepend a presentational icon or similar element to the input.\n- **suffix** - Used to append a presentational icon or similar element to the input.\n- **clear-icon** - An icon to use in lieu of the default clear icon.\n- **show-password-icon** - An icon to use in lieu of the default show password icon.\n- **hide-password-icon** - An icon to use in lieu of the default hide password icon.\n- **help-text** - Text that describes how to use the input. Alternatively, you can use the `help-text` attribute.\n\n### **CSS Properties:**\n - **--zn-range-track-height** - The height of a range input's track. _(default: undefined)_\n- **--zn-range-track-color** - The color of a range input's track. _(default: undefined)_\n- **--zn-range-thumb-size** - The diameter of a range input's thumb. _(default: undefined)_\n- **--zn-range-thumb-color** - The color of a range input's thumb. _(default: undefined)_\n- **--zn-range-thumb-ring-width** - The width of the ring drawn around a range input's thumb. _(default: undefined)_\n\n### **CSS Parts:**\n - **form-control** - The form control that wraps the label, input, and help text.\n- **form-control-label** - The label's wrapper.\n- **form-control-input** - The input's wrapper.\n- **form-control-help-text** - The help text's wrapper.\n- **base** - The component's base wrapper.\n- **input** - The internal `<input>` control.\n- **prefix** - The container that wraps the prefix.\n- **clear-button** - The clear button.\n- **password-toggle-button** - The password toggle button.\n- **suffix** - The container that wraps the suffix.",
4706
4734
  "doc-url": "",
4707
4735
  "attributes": [
4708
4736
  {
@@ -4713,7 +4741,7 @@
4713
4741
  "name": "type",
4714
4742
  "description": "The type of input. Works the same as native `<input>` element. But only a subset of types is supported. Defaults\nto `text`",
4715
4743
  "value": {
4716
- "type": "'color' | 'currency' | 'date' | 'datetime-local' | 'email' | 'number' | 'password' |\n 'search' | 'tel' | 'text' | 'time' | 'url'",
4744
+ "type": "'color' | 'currency' | 'date' | 'datetime-local' | 'email' | 'number' | 'password' |\n 'range' | 'search' | 'tel' | 'text' | 'time' | 'url'",
4717
4745
  "default": "'text'"
4718
4746
  }
4719
4747
  },
@@ -4813,6 +4841,11 @@
4813
4841
  "default": "'hex'"
4814
4842
  }
4815
4843
  },
4844
+ {
4845
+ "name": "value-suffix",
4846
+ "description": "Appended to the value that range inputs display above the track, on the right, e.g. `rem`. Only applies when type\nis 'range' and no `context-note` is set.",
4847
+ "value": { "type": "string", "default": "''" }
4848
+ },
4816
4849
  {
4817
4850
  "name": "form",
4818
4851
  "description": "By default, form-controls are associated with the nearest containing `<form>` element. This attribute allows you\nto place the form control outside a form and associate it with the form that has this `id`. The form must be\nin the same document or shadow root for this to work.",
@@ -4911,7 +4944,7 @@
4911
4944
  },
4912
4945
  {
4913
4946
  "name": "context-note",
4914
- "description": "Used to add contextual text that is displayed above the input, on the right. Alternatively, you can use the `context-note` attribute."
4947
+ "description": "Used to add contextual text that is displayed above the input, on the right. Alternatively, you can use the `context-note` attribute. Range inputs display their live value here unless this is set."
4915
4948
  },
4916
4949
  {
4917
4950
  "name": "prefix",
@@ -4972,7 +5005,7 @@
4972
5005
  {
4973
5006
  "name": "type",
4974
5007
  "description": "The type of input. Works the same as native `<input>` element. But only a subset of types is supported. Defaults\nto `text`",
4975
- "type": "'color' | 'currency' | 'date' | 'datetime-local' | 'email' | 'number' | 'password' |\n 'search' | 'tel' | 'text' | 'time' | 'url'"
5008
+ "type": "'color' | 'currency' | 'date' | 'datetime-local' | 'email' | 'number' | 'password' |\n 'range' | 'search' | 'tel' | 'text' | 'time' | 'url'"
4976
5009
  },
4977
5010
  {
4978
5011
  "name": "name",
@@ -5069,6 +5102,11 @@
5069
5102
  "description": "The color format to display for color inputs. Only applies when type is 'color'. *",
5070
5103
  "type": "'hex' | 'rgb' | 'hsl' | 'oklch'"
5071
5104
  },
5105
+ {
5106
+ "name": "valueSuffix",
5107
+ "description": "Appended to the value that range inputs display above the track, on the right, e.g. `rem`. Only applies when type\nis 'range' and no `context-note` is set.",
5108
+ "type": "string"
5109
+ },
5072
5110
  {
5073
5111
  "name": "form",
5074
5112
  "description": "By default, form-controls are associated with the nearest containing `<form>` element. This attribute allows you\nto place the form control outside a form and associate it with the form that has this `id`. The form must be\nin the same document or shadow root for this to work.",
@@ -6901,7 +6939,7 @@
6901
6939
  },
6902
6940
  {
6903
6941
  "name": "zn-preview-frame",
6904
- "description": "Embeds a live preview iframe and drives the hp-preview postMessage\nprotocol: answers the frame's ready handshake with a config payload fetched\nfrom data-uri, auto-saves watched forms on change, and refreshes the\npreview after each save.\n---\n\n\n### **Events:**\n - **zn-error** - Emitted when the preview reports a render error or a save fails.\n\n### **Methods:**\n - **refresh()** - Re-fetches the payload and pushes a fresh config to the preview.\n\n### **CSS Parts:**\n - **base** - The component's base wrapper.\n- **iframe** - The preview iframe.\n- **error** - The error overlay.",
6942
+ "description": "Embeds a live preview iframe and drives the hp-preview postMessage\nprotocol: answers the frame's ready handshake with a config payload fetched\nfrom data-uri, auto-saves watched forms on change, refreshes the preview\nafter each save (its own, or a shell-driven save of a `refresh-on` form),\nand accepts a theme payload via setTheme() that is retained and replayed\nafter every ready handshake.\n---\n\n\n### **Events:**\n - **zn-error** - Emitted when the preview reports a render error or a save fails.\n\n### **Methods:**\n - **refresh()** - Re-fetches the payload and pushes a fresh config to the preview.\n- **setTheme(theme: _Record<string, unknown>_)** - Pushes a theme payload into the preview. The payload is retained and\nre-posted after every ready handshake, so a frame reload doesn't drop an\nin-progress theme.\n\n### **CSS Properties:**\n - **--zn-preview-frame-dot-spacing** - Spacing of the backdrop dot grid (`backdrop=\"dots\"`). Defaults to 20px. _(default: undefined)_\n- **--zn-preview-frame-dot-opacity** - Opacity of the backdrop dots (`backdrop=\"dots\"`). Defaults to 0.08. _(default: undefined)_\n\n### **CSS Parts:**\n - **base** - The component's base wrapper.\n- **stage** - The device-width wrapper around the iframe.\n- **iframe** - The preview iframe.\n- **error** - The error overlay.",
6905
6943
  "doc-url": "",
6906
6944
  "attributes": [
6907
6945
  {
@@ -6924,6 +6962,11 @@
6924
6962
  "description": "Selector (resolved against the component's root node) for the forms to watch.\nDefaults to only forms explicitly opted in via a `data-auto-save` attribute —\nunmarked forms keep normal submit behavior and are never intercepted,\nauto-saved, or used to trigger a preview refresh. Override to widen the scope.",
6925
6963
  "value": { "type": "string", "default": "'form[data-auto-save]'" }
6926
6964
  },
6965
+ {
6966
+ "name": "refresh-on",
6967
+ "description": "Selector for forms whose saves are left to the shell but should still\nrefresh the preview. These are never intercepted: the shell submits them\n(so its own response handling — alerts, refreshes — runs as normal) and the\npreview re-fetches its config once the shell reports the save complete.\nSet empty to disable.",
6968
+ "value": { "type": "string", "default": "'form'" }
6969
+ },
6927
6970
  {
6928
6971
  "name": "debounce",
6929
6972
  "description": "Debounce in ms between a form change and its auto-save.",
@@ -6931,13 +6974,28 @@
6931
6974
  },
6932
6975
  {
6933
6976
  "name": "zoom",
6934
- "description": "Zooms the previewed page out (0–1]. The frame always fills the panel;\nzoom shrinks the content browser-style, so 0.4 shows the page at 40%\nsize with correspondingly more of it visible. 1 = natural size.",
6977
+ "description": "Zooms the previewed page out (0–1]. The frame always fills the panel;\nzoom shrinks the content browser-style, so 0.4 shows the page at 40%\nsize with correspondingly more of it visible. 1 = natural size.\nIgnored when `fill` is set.",
6935
6978
  "value": { "type": "number", "default": "1" }
6936
6979
  },
6937
6980
  {
6938
6981
  "name": "min-height",
6939
- "description": "The visible height (in CSS pixels) of the preview panel. Fixed rather\nthan measured, because a measured height would feed back into the\nscaled iframe's layout box and grow unbounded.",
6982
+ "description": "The visible height (in CSS pixels) of the preview panel. Fixed rather\nthan measured, because a measured height would feed back into the\nscaled iframe's layout box and grow unbounded. With `fill` set, this\nbecomes a `min-height` floor instead of the height.",
6940
6983
  "value": { "type": "number", "default": "480" }
6984
+ },
6985
+ {
6986
+ "name": "fill",
6987
+ "description": "Fills the panel's own column height instead of using a fixed\n`min-height` pixel height — for hosts (like zn-theme-editor) whose\nlayout already stretches the column to match a taller sibling.\n`zoom` is ignored when set: its oversize maths depends on a known\npixel height, which `fill` deliberately doesn't have.",
6988
+ "value": { "type": "boolean", "default": "false" }
6989
+ },
6990
+ {
6991
+ "name": "device",
6992
+ "description": "Constrains and centres the preview to a device width: `desktop` (100%),\n`tablet` (768px) or `mobile` (390px). The iframe element itself is\nnarrowed, so the embedded page's own media queries fire.",
6993
+ "value": { "type": "PreviewFrameDevice", "default": "'desktop'" }
6994
+ },
6995
+ {
6996
+ "name": "backdrop",
6997
+ "description": "Backdrop behind the stage: `dots` (default) is the canvas dot grid; `panel` is a plain `rgb(var(--zn-panel))` fill.",
6998
+ "value": { "type": "'dots' | 'panel'", "default": "'dots'" }
6941
6999
  }
6942
7000
  ],
6943
7001
  "events": [
@@ -6968,6 +7026,11 @@
6968
7026
  "description": "Selector (resolved against the component's root node) for the forms to watch.\nDefaults to only forms explicitly opted in via a `data-auto-save` attribute —\nunmarked forms keep normal submit behavior and are never intercepted,\nauto-saved, or used to trigger a preview refresh. Override to widen the scope.",
6969
7027
  "type": "string"
6970
7028
  },
7029
+ {
7030
+ "name": "refreshOn",
7031
+ "description": "Selector for forms whose saves are left to the shell but should still\nrefresh the preview. These are never intercepted: the shell submits them\n(so its own response handling — alerts, refreshes — runs as normal) and the\npreview re-fetches its config once the shell reports the save complete.\nSet empty to disable.",
7032
+ "type": "string"
7033
+ },
6971
7034
  {
6972
7035
  "name": "debounce",
6973
7036
  "description": "Debounce in ms between a form change and its auto-save.",
@@ -6975,14 +7038,29 @@
6975
7038
  },
6976
7039
  {
6977
7040
  "name": "zoom",
6978
- "description": "Zooms the previewed page out (0–1]. The frame always fills the panel;\nzoom shrinks the content browser-style, so 0.4 shows the page at 40%\nsize with correspondingly more of it visible. 1 = natural size.",
7041
+ "description": "Zooms the previewed page out (0–1]. The frame always fills the panel;\nzoom shrinks the content browser-style, so 0.4 shows the page at 40%\nsize with correspondingly more of it visible. 1 = natural size.\nIgnored when `fill` is set.",
6979
7042
  "type": "number"
6980
7043
  },
6981
7044
  {
6982
7045
  "name": "minHeight",
6983
- "description": "The visible height (in CSS pixels) of the preview panel. Fixed rather\nthan measured, because a measured height would feed back into the\nscaled iframe's layout box and grow unbounded.",
7046
+ "description": "The visible height (in CSS pixels) of the preview panel. Fixed rather\nthan measured, because a measured height would feed back into the\nscaled iframe's layout box and grow unbounded. With `fill` set, this\nbecomes a `min-height` floor instead of the height.",
6984
7047
  "type": "number"
6985
7048
  },
7049
+ {
7050
+ "name": "fill",
7051
+ "description": "Fills the panel's own column height instead of using a fixed\n`min-height` pixel height — for hosts (like zn-theme-editor) whose\nlayout already stretches the column to match a taller sibling.\n`zoom` is ignored when set: its oversize maths depends on a known\npixel height, which `fill` deliberately doesn't have.",
7052
+ "type": "boolean"
7053
+ },
7054
+ {
7055
+ "name": "device",
7056
+ "description": "Constrains and centres the preview to a device width: `desktop` (100%),\n`tablet` (768px) or `mobile` (390px). The iframe element itself is\nnarrowed, so the embedded page's own media queries fire.",
7057
+ "type": "PreviewFrameDevice"
7058
+ },
7059
+ {
7060
+ "name": "backdrop",
7061
+ "description": "Backdrop behind the stage: `dots` (default) is the canvas dot grid; `panel` is a plain `rgb(var(--zn-panel))` fill.",
7062
+ "type": "'dots' | 'panel'"
7063
+ },
6986
7064
  { "name": "frame", "type": "HTMLIFrameElement" }
6987
7065
  ],
6988
7066
  "events": [
@@ -9723,6 +9801,253 @@
9723
9801
  ]
9724
9802
  }
9725
9803
  },
9804
+ {
9805
+ "name": "zn-theme-editor",
9806
+ "description": "A theme editor: slotted form controls drive a live preview frame,\nwith a toolbar for the preview's light/dark mode and device width.\n---\n\n\n### **Events:**\n - **zn-theme-change** - Emitted when the values, mode or device change.\n- **zn-theme-submit** - Emitted on submit (button click), carrying the current values. With `action` set, only fires after a successful save.\n- **zn-error** - Emitted when a save fails. Also seen for preview render failures: the frame's zn-error is composed and not stopped, so it bubbles out through the editor too.\n\n### **Slots:**\n - _default_ - Ungrouped theme controls, rendered above any sections. Controls assigned `slot=\"<name>\"` matching a `sections` entry (or, when nested, a `groups` entry) render inside that section/group instead. Harvesting and change detection walk every slot's full assigned subtree, not just direct children. With `sections` left unset, the structure is instead derived from the controls' own attributes: `group=\"<label>\"` becomes a tab and `category=\"<label>\"` a collapsible within it, and the control is slotted into that collapsible automatically. Either attribute works alone - a control with only `group` sits directly in its tab, and one with only `category` becomes its own top-level section. Setting `sections` explicitly disables the derivation entirely.\n- **toolbar** - Actions in the toolbar, right-aligned beside the device controls. Where a save button belongs.\n- **footer** - Actions pinned beneath the controls. The built-in submit button lives in the toolbar, not here.\n\n### **CSS Properties:**\n - **--zn-theme-editor-controls-width** - Width of the controls column. _(default: undefined)_\n\n### **CSS Parts:**\n - **base** - The component's base wrapper.\n- **controls** - The left-hand controls column, full height.\n- **controls-header** - The controls column's header row: `controls-caption` on the left, the light/dark mode toggle on the right.\n- **toolbar** - The preview column's header row: `preview-caption` on the left, the device switcher (and sources/submit) on the right. Spans the preview column only.\n- **section** - A rendered section's or group's collapsible (`section-layout=\"collapsible\"`, or any nested group).\n- **footer** - The footer wrapper beneath the controls.\n- **preview** - The preview column.\n- **error** - The inline error strip.\n- **preview__base** - The frame's base wrapper (forwarded from zn-preview-frame).\n- **preview__stage** - The frame's device-width wrapper (forwarded from zn-preview-frame).\n- **preview__iframe** - The frame's iframe (forwarded from zn-preview-frame).\n- **preview__error** - The frame's own error overlay (forwarded from zn-preview-frame).",
9807
+ "doc-url": "",
9808
+ "attributes": [
9809
+ {
9810
+ "name": "src",
9811
+ "description": "URL of the preview shell page; forwarded to the frame.",
9812
+ "value": { "type": "string", "default": "''" }
9813
+ },
9814
+ {
9815
+ "name": "frame-origin",
9816
+ "description": "Expected origin of the iframe; forwarded to the frame.",
9817
+ "value": { "type": "string", "default": "''" }
9818
+ },
9819
+ {
9820
+ "name": "data-uri",
9821
+ "description": "Optional endpoint returning the base hp-preview:config payload.",
9822
+ "value": { "type": "string", "default": "''" }
9823
+ },
9824
+ {
9825
+ "name": "mode",
9826
+ "description": "Which mode the preview renders in. Travels in the theme payload.",
9827
+ "value": { "type": "ThemeEditorMode", "default": "'light'" }
9828
+ },
9829
+ {
9830
+ "name": "device",
9831
+ "description": "Preview viewport width. Resizes the frame only; not part of the payload.",
9832
+ "value": { "type": "ThemeEditorDevice", "default": "'desktop'" }
9833
+ },
9834
+ {
9835
+ "name": "min-height",
9836
+ "description": "Minimum height of the preview row, in pixels; forwarded to the frame as its own floor.",
9837
+ "value": { "type": "number", "default": "480" }
9838
+ },
9839
+ {
9840
+ "name": "debounce",
9841
+ "description": "Debounce in ms between a control change and the push to the preview.",
9842
+ "value": { "type": "number", "default": "150" }
9843
+ },
9844
+ {
9845
+ "name": "action",
9846
+ "description": "Optional endpoint the values are POSTed to. Empty = no persistence.",
9847
+ "value": { "type": "string", "default": "''" }
9848
+ },
9849
+ {
9850
+ "name": "save-debounce",
9851
+ "description": "Debounce in ms between a control change and the save POST.",
9852
+ "value": { "type": "number", "default": "1000" }
9853
+ },
9854
+ {
9855
+ "name": "sections",
9856
+ "description": "Groups controls into named sections. Empty/unset falls back to deriving the\nstructure from the controls' own `group`/`category` attributes, and renders\none ungrouped column when they carry neither. A section with a non-empty\n`groups` nests a collapsible per group inside a `zn-tabs` tab for that\nsection - see `groups` on `ThemeEditorSection`.",
9857
+ "value": { "type": "ThemeEditorSection[]", "default": "[]" }
9858
+ },
9859
+ {
9860
+ "name": "section-layout",
9861
+ "description": "Presentation for flat, group-less `sections`: stacked `zn-collapsible`s\n(default) or a `zn-tabs` strip. Ignored once any section has `groups` -\nnested sections always render as tabs.",
9862
+ "value": {
9863
+ "type": "'collapsible' | 'tabs'",
9864
+ "default": "'collapsible'"
9865
+ }
9866
+ },
9867
+ {
9868
+ "name": "sources",
9869
+ "description": "Dropdown of preview sources, `{label, src}`, rendered in the toolbar. Empty/unset renders no dropdown; the first entry wins over an explicit `src` when non-empty.",
9870
+ "value": { "type": "ThemeEditorSource[]", "default": "[]" }
9871
+ },
9872
+ {
9873
+ "name": "controls-collapsed",
9874
+ "description": "Collapses the controls column.",
9875
+ "value": { "type": "boolean", "default": "false" }
9876
+ },
9877
+ {
9878
+ "name": "standalone",
9879
+ "description": "Presents the editor as its own bordered, rounded panel with a plain preview backdrop, rather than embedded in a dotted canvas.",
9880
+ "value": { "type": "boolean", "default": "false" }
9881
+ },
9882
+ {
9883
+ "name": "controls-caption",
9884
+ "description": "Caption in the controls column's header row. Empty (default) renders no text; the row itself always renders.",
9885
+ "value": { "type": "string", "default": "''" }
9886
+ },
9887
+ {
9888
+ "name": "preview-caption",
9889
+ "description": "Caption at the left of the toolbar, opposite the device and mode controls. Empty (default) renders no text.",
9890
+ "value": { "type": "string", "default": "''" }
9891
+ },
9892
+ {
9893
+ "name": "submit-label",
9894
+ "description": "Label for the built-in submit button. Empty (default) renders no button.",
9895
+ "value": { "type": "string", "default": "''" }
9896
+ },
9897
+ {
9898
+ "name": "manual",
9899
+ "description": "Disables the debounced auto-save; saving then happens only via submit. Preview pushes are unaffected.",
9900
+ "value": { "type": "boolean", "default": "false" }
9901
+ }
9902
+ ],
9903
+ "slots": [
9904
+ {
9905
+ "name": "",
9906
+ "description": "Ungrouped theme controls, rendered above any sections. Controls assigned `slot=\"<name>\"` matching a `sections` entry (or, when nested, a `groups` entry) render inside that section/group instead. Harvesting and change detection walk every slot's full assigned subtree, not just direct children. With `sections` left unset, the structure is instead derived from the controls' own attributes: `group=\"<label>\"` becomes a tab and `category=\"<label>\"` a collapsible within it, and the control is slotted into that collapsible automatically. Either attribute works alone - a control with only `group` sits directly in its tab, and one with only `category` becomes its own top-level section. Setting `sections` explicitly disables the derivation entirely."
9907
+ },
9908
+ {
9909
+ "name": "toolbar",
9910
+ "description": "Actions in the toolbar, right-aligned beside the device controls. Where a save button belongs."
9911
+ },
9912
+ {
9913
+ "name": "footer",
9914
+ "description": "Actions pinned beneath the controls. The built-in submit button lives in the toolbar, not here."
9915
+ }
9916
+ ],
9917
+ "events": [
9918
+ {
9919
+ "name": "zn-theme-change",
9920
+ "description": "Emitted when the values, mode or device change."
9921
+ },
9922
+ {
9923
+ "name": "zn-theme-submit",
9924
+ "description": "Emitted on submit (button click), carrying the current values. With `action` set, only fires after a successful save."
9925
+ },
9926
+ {
9927
+ "name": "zn-error",
9928
+ "description": "Emitted when a save fails. Also seen for preview render failures: the frame's zn-error is composed and not stopped, so it bubbles out through the editor too."
9929
+ }
9930
+ ],
9931
+ "js": {
9932
+ "properties": [
9933
+ {
9934
+ "name": "src",
9935
+ "description": "URL of the preview shell page; forwarded to the frame.",
9936
+ "type": "string"
9937
+ },
9938
+ {
9939
+ "name": "frameOrigin",
9940
+ "description": "Expected origin of the iframe; forwarded to the frame.",
9941
+ "type": "string"
9942
+ },
9943
+ {
9944
+ "name": "dataUri",
9945
+ "description": "Optional endpoint returning the base hp-preview:config payload.",
9946
+ "type": "string"
9947
+ },
9948
+ {
9949
+ "name": "mode",
9950
+ "description": "Which mode the preview renders in. Travels in the theme payload.",
9951
+ "type": "ThemeEditorMode"
9952
+ },
9953
+ {
9954
+ "name": "device",
9955
+ "description": "Preview viewport width. Resizes the frame only; not part of the payload.",
9956
+ "type": "ThemeEditorDevice"
9957
+ },
9958
+ {
9959
+ "name": "minHeight",
9960
+ "description": "Minimum height of the preview row, in pixels; forwarded to the frame as its own floor.",
9961
+ "type": "number"
9962
+ },
9963
+ {
9964
+ "name": "debounce",
9965
+ "description": "Debounce in ms between a control change and the push to the preview.",
9966
+ "type": "number"
9967
+ },
9968
+ {
9969
+ "name": "action",
9970
+ "description": "Optional endpoint the values are POSTed to. Empty = no persistence.",
9971
+ "type": "string"
9972
+ },
9973
+ {
9974
+ "name": "saveDebounce",
9975
+ "description": "Debounce in ms between a control change and the save POST.",
9976
+ "type": "number"
9977
+ },
9978
+ {
9979
+ "name": "sections",
9980
+ "description": "Groups controls into named sections. Empty/unset falls back to deriving the\nstructure from the controls' own `group`/`category` attributes, and renders\none ungrouped column when they carry neither. A section with a non-empty\n`groups` nests a collapsible per group inside a `zn-tabs` tab for that\nsection - see `groups` on `ThemeEditorSection`.",
9981
+ "type": "ThemeEditorSection[]"
9982
+ },
9983
+ {
9984
+ "name": "sectionLayout",
9985
+ "description": "Presentation for flat, group-less `sections`: stacked `zn-collapsible`s\n(default) or a `zn-tabs` strip. Ignored once any section has `groups` -\nnested sections always render as tabs.",
9986
+ "type": "'collapsible' | 'tabs'"
9987
+ },
9988
+ {
9989
+ "name": "sources",
9990
+ "description": "Dropdown of preview sources, `{label, src}`, rendered in the toolbar. Empty/unset renders no dropdown; the first entry wins over an explicit `src` when non-empty.",
9991
+ "type": "ThemeEditorSource[]"
9992
+ },
9993
+ {
9994
+ "name": "controlsCollapsed",
9995
+ "description": "Collapses the controls column.",
9996
+ "type": "boolean"
9997
+ },
9998
+ {
9999
+ "name": "standalone",
10000
+ "description": "Presents the editor as its own bordered, rounded panel with a plain preview backdrop, rather than embedded in a dotted canvas.",
10001
+ "type": "boolean"
10002
+ },
10003
+ {
10004
+ "name": "controlsCaption",
10005
+ "description": "Caption in the controls column's header row. Empty (default) renders no text; the row itself always renders.",
10006
+ "type": "string"
10007
+ },
10008
+ {
10009
+ "name": "previewCaption",
10010
+ "description": "Caption at the left of the toolbar, opposite the device and mode controls. Empty (default) renders no text.",
10011
+ "type": "string"
10012
+ },
10013
+ {
10014
+ "name": "submitLabel",
10015
+ "description": "Label for the built-in submit button. Empty (default) renders no button.",
10016
+ "type": "string"
10017
+ },
10018
+ {
10019
+ "name": "manual",
10020
+ "description": "Disables the debounced auto-save; saving then happens only via submit. Preview pushes are unaffected.",
10021
+ "type": "boolean"
10022
+ },
10023
+ { "name": "frame", "type": "ZnPreviewFrame" },
10024
+ {
10025
+ "name": "values",
10026
+ "description": "The current per-mode value sets. Returns copies.",
10027
+ "type": "{ light: Record<string, unknown>; dark: Record<string, unknown> }"
10028
+ },
10029
+ {
10030
+ "name": "activeValues",
10031
+ "description": "The active mode's values - what gets pushed to the preview frame.",
10032
+ "type": "Record<string, unknown>"
10033
+ }
10034
+ ],
10035
+ "events": [
10036
+ {
10037
+ "name": "zn-theme-change",
10038
+ "description": "Emitted when the values, mode or device change."
10039
+ },
10040
+ {
10041
+ "name": "zn-theme-submit",
10042
+ "description": "Emitted on submit (button click), carrying the current values. With `action` set, only fires after a successful save."
10043
+ },
10044
+ {
10045
+ "name": "zn-error",
10046
+ "description": "Emitted when a save fails. Also seen for preview render failures: the frame's zn-error is composed and not stopped, so it bubbles out through the editor too."
10047
+ }
10048
+ ]
10049
+ }
10050
+ },
9726
10051
  {
9727
10052
  "name": "zn-tile",
9728
10053
  "description": "Short summary of the component's intended use.\n---\n\n\n### **Events:**\n - **zn-event-name** - Emitted as an example.\n\n### **Slots:**\n - _default_ - The default slot.\n- **example** - An example slot.\n\n### **CSS Properties:**\n - **--example** - An example CSS custom property. _(default: undefined)_\n\n### **CSS Parts:**\n - **base** - The component's base wrapper.",