@kubex/zinc 1.1.67 → 1.1.69

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 +1288 -20
  2. package/dist/vscode.html-custom-data.json +167 -11
  3. package/dist/web-types.json +360 -17
  4. package/dist/zn.d.ts +368 -20
  5. package/dist/zn.min.js +764 -645
  6. package/docs/pages/components/collapsible.md +6 -2
  7. package/docs/pages/components/preview-frame-demo.njk +33 -4
  8. package/docs/pages/components/preview-frame.md +20 -0
  9. package/docs/pages/components/theme-editor.md +269 -0
  10. package/docs/superpowers/plans/2026-08-03-theme-editor.md +1536 -0
  11. package/docs/superpowers/specs/2026-08-03-theme-editor-design.md +327 -0
  12. package/package.json +1 -1
  13. package/src/components/collapsible/collapsible.component.ts +21 -23
  14. package/src/components/collapsible/collapsible.scss +10 -0
  15. package/src/components/data-table/data-table.component.ts +49 -44
  16. package/src/components/data-table/data-table.scss +4 -0
  17. package/src/components/data-table/data-table.test.ts +42 -0
  18. package/src/components/defined-label/defined-label.component.ts +118 -95
  19. package/src/components/defined-label/defined-label.scss +40 -28
  20. package/src/components/dropdown/dropdown.component.ts +9 -0
  21. package/src/components/editor/editor.component.ts +20 -21
  22. package/src/components/file/file.component.ts +70 -0
  23. package/src/components/page-builder/page-builder.scss +1 -1
  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 +761 -0
  29. package/src/components/theme-editor/theme-editor.scss +309 -0
  30. package/src/components/theme-editor/theme-editor.test.ts +1584 -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
@@ -5419,6 +5419,10 @@
5419
5419
  {
5420
5420
  "description": "The caption text.",
5421
5421
  "name": "caption"
5422
+ },
5423
+ {
5424
+ "description": "The expandable content wrapper.",
5425
+ "name": "content"
5422
5426
  }
5423
5427
  ],
5424
5428
  "slots": [
@@ -5561,7 +5565,7 @@
5561
5565
  "name": "observer",
5562
5566
  "privacy": "private",
5563
5567
  "readonly": true,
5564
- "default": "new MutationController(this, { target: null, config: {childList: true, subtree: true}, callback: () => this.recalculateNumberOfItems(), })"
5568
+ "default": "new MutationController(this, { target: null, config: { childList: true, subtree: true }, callback: () => this.recalculateNumberOfItems(), })"
5565
5569
  },
5566
5570
  {
5567
5571
  "kind": "field",
@@ -5682,7 +5686,7 @@
5682
5686
  "tagNameWithoutPrefix": "collapsible",
5683
5687
  "tagName": "zn-collapsible",
5684
5688
  "customElement": true,
5685
- "jsDoc": "/**\n * @summary Toggles between showing and hiding content when clicked\n * @documentation https://zinc.style/components/collapsible\n * @status experimental\n * @since 1.0\n *\n * @dependency zn-icon - The icon element\n *\n * @slot header - Clicking will toggle the show state of the data\n *\n * @csspart header - The header row (toggle).\n * @csspart caption - The caption text.\n */",
5689
+ "jsDoc": "/**\n * @summary Toggles between showing and hiding content when clicked\n * @documentation https://zinc.style/components/collapsible\n * @status experimental\n * @since 1.0\n *\n * @dependency zn-icon - The icon element\n *\n * @slot header - Clicking will toggle the show state of the data\n *\n * @csspart header - The header row (toggle).\n * @csspart caption - The caption text.\n * @csspart content - The expandable content wrapper.\n */",
5686
5690
  "documentation": "https://zinc.style/components/collapsible",
5687
5691
  "status": "experimental",
5688
5692
  "since": "1.0",
@@ -8267,7 +8271,7 @@
8267
8271
  "text": "Record<string, DisplayTemplate>"
8268
8272
  },
8269
8273
  "privacy": "private",
8270
- "default": "{ dateTime: ((cell) => { const t = cell.text || ''; return html` <div class=\"table__collum--datetime\"> <span><strong>${t.slice(0, 10)}</strong></span> <zn-style size=\"s\" muted>${t.slice(11)}</zn-style> </div>` }) satisfies DisplayTemplate }"
8274
+ "default": "{ dateTime: ((cell) => { const t = cell.text || ''; return html` <div class=\"table__collum--datetime\" title=\"${ifDefined(cell.title)}\"> <span><strong>${t.slice(0, 10)}</strong></span> <zn-style size=\"s\" muted>${t.slice(11)}</zn-style> </div>` }) satisfies DisplayTemplate }"
8271
8275
  },
8272
8276
  {
8273
8277
  "kind": "field",
@@ -10529,6 +10533,15 @@
10529
10533
  }
10530
10534
  ],
10531
10535
  "members": [
10536
+ {
10537
+ "kind": "field",
10538
+ "name": "dependencies",
10539
+ "type": {
10540
+ "text": "object"
10541
+ },
10542
+ "static": true,
10543
+ "default": "{ 'zn-button': ZnButton, 'zn-dropdown': ZnDropdown, 'zn-input': ZnInput, 'zn-option': ZnOption, 'zn-select': ZnSelect }"
10544
+ },
10532
10545
  {
10533
10546
  "kind": "field",
10534
10547
  "name": "formControlController",
@@ -10557,6 +10570,7 @@
10557
10570
  "text": "string"
10558
10571
  },
10559
10572
  "default": "''",
10573
+ "description": "The selected label key. Also acts as the filter while typing.",
10560
10574
  "attribute": "value"
10561
10575
  },
10562
10576
  {
@@ -10566,6 +10580,7 @@
10566
10580
  "text": "string"
10567
10581
  },
10568
10582
  "default": "''",
10583
+ "description": "The value entered for the selected label. Submitted as `label:value` when present.",
10569
10584
  "attribute": "inputValue"
10570
10585
  },
10571
10586
  {
@@ -10575,6 +10590,7 @@
10575
10590
  "text": "'x-small' | 'small' | 'medium' | 'large'"
10576
10591
  },
10577
10592
  "default": "'medium'",
10593
+ "description": "The size of the main input.",
10578
10594
  "attribute": "input-size",
10579
10595
  "reflects": true
10580
10596
  },
@@ -10585,6 +10601,7 @@
10585
10601
  "text": "string"
10586
10602
  },
10587
10603
  "default": "'label'",
10604
+ "description": "The name of the control. Used for form submission.",
10588
10605
  "attribute": "name"
10589
10606
  },
10590
10607
  {
@@ -10593,6 +10610,7 @@
10593
10610
  "type": {
10594
10611
  "text": "string"
10595
10612
  },
10613
+ "description": "The title of the main input.",
10596
10614
  "attribute": "title"
10597
10615
  },
10598
10616
  {
@@ -10602,6 +10620,7 @@
10602
10620
  "text": "boolean"
10603
10621
  },
10604
10622
  "default": "false",
10623
+ "description": "Disables the control.",
10605
10624
  "attribute": "disabled"
10606
10625
  },
10607
10626
  {
@@ -10611,15 +10630,17 @@
10611
10630
  "text": "boolean"
10612
10631
  },
10613
10632
  "default": "false",
10633
+ "description": "Allows labels that aren't in the predefined list.",
10614
10634
  "attribute": "allow-custom"
10615
10635
  },
10616
10636
  {
10617
10637
  "kind": "field",
10618
10638
  "name": "predefinedLabels",
10619
10639
  "type": {
10620
- "text": "array"
10640
+ "text": "(PredefinedLabel | string)[]"
10621
10641
  },
10622
10642
  "default": "[]",
10643
+ "description": "The predefined labels. Entries are either a string or `{name, options}`.",
10623
10644
  "attribute": "predefined-labels"
10624
10645
  },
10625
10646
  {
@@ -10680,6 +10701,16 @@
10680
10701
  "kind": "method",
10681
10702
  "name": "handleValueChange"
10682
10703
  },
10704
+ {
10705
+ "kind": "method",
10706
+ "name": "getFilteredLabels",
10707
+ "privacy": "private",
10708
+ "return": {
10709
+ "type": {
10710
+ "text": "PredefinedLabel[]"
10711
+ }
10712
+ }
10713
+ },
10683
10714
  {
10684
10715
  "kind": "method",
10685
10716
  "name": "handleChange",
@@ -10718,7 +10749,7 @@
10718
10749
  },
10719
10750
  {
10720
10751
  "kind": "method",
10721
- "name": "handleInputValueInput",
10752
+ "name": "handleFormSubmit",
10722
10753
  "privacy": "private",
10723
10754
  "parameters": [
10724
10755
  {
@@ -10726,13 +10757,64 @@
10726
10757
  "type": {
10727
10758
  "text": "Event"
10728
10759
  }
10760
+ },
10761
+ {
10762
+ "name": "label",
10763
+ "optional": true,
10764
+ "type": {
10765
+ "text": "string"
10766
+ }
10729
10767
  }
10730
10768
  ]
10731
10769
  },
10732
10770
  {
10733
10771
  "kind": "method",
10734
- "name": "handleFormSubmit",
10735
- "privacy": "private"
10772
+ "name": "renderValueControl",
10773
+ "privacy": "private",
10774
+ "return": {
10775
+ "type": {
10776
+ "text": "TemplateResult"
10777
+ }
10778
+ },
10779
+ "parameters": [
10780
+ {
10781
+ "name": "label",
10782
+ "type": {
10783
+ "text": "PredefinedLabel"
10784
+ }
10785
+ }
10786
+ ]
10787
+ },
10788
+ {
10789
+ "kind": "method",
10790
+ "name": "renderRow",
10791
+ "privacy": "private",
10792
+ "return": {
10793
+ "type": {
10794
+ "text": "TemplateResult"
10795
+ }
10796
+ },
10797
+ "parameters": [
10798
+ {
10799
+ "name": "name",
10800
+ "type": {
10801
+ "text": "string"
10802
+ }
10803
+ },
10804
+ {
10805
+ "name": "control",
10806
+ "type": {
10807
+ "text": "TemplateResult"
10808
+ }
10809
+ },
10810
+ {
10811
+ "name": "label",
10812
+ "optional": true,
10813
+ "type": {
10814
+ "text": "string"
10815
+ }
10816
+ }
10817
+ ]
10736
10818
  }
10737
10819
  ],
10738
10820
  "attributes": [
@@ -10742,6 +10824,7 @@
10742
10824
  "text": "string"
10743
10825
  },
10744
10826
  "default": "''",
10827
+ "description": "The selected label key. Also acts as the filter while typing.",
10745
10828
  "fieldName": "value"
10746
10829
  },
10747
10830
  {
@@ -10750,6 +10833,7 @@
10750
10833
  "text": "string"
10751
10834
  },
10752
10835
  "default": "''",
10836
+ "description": "The value entered for the selected label. Submitted as `label:value` when present.",
10753
10837
  "fieldName": "inputValue"
10754
10838
  },
10755
10839
  {
@@ -10758,6 +10842,7 @@
10758
10842
  "text": "'x-small' | 'small' | 'medium' | 'large'"
10759
10843
  },
10760
10844
  "default": "'medium'",
10845
+ "description": "The size of the main input.",
10761
10846
  "fieldName": "inputSize"
10762
10847
  },
10763
10848
  {
@@ -10766,6 +10851,7 @@
10766
10851
  "text": "string"
10767
10852
  },
10768
10853
  "default": "'label'",
10854
+ "description": "The name of the control. Used for form submission.",
10769
10855
  "fieldName": "name"
10770
10856
  },
10771
10857
  {
@@ -10773,6 +10859,7 @@
10773
10859
  "type": {
10774
10860
  "text": "string"
10775
10861
  },
10862
+ "description": "The title of the main input.",
10776
10863
  "fieldName": "title"
10777
10864
  },
10778
10865
  {
@@ -10781,6 +10868,7 @@
10781
10868
  "text": "boolean"
10782
10869
  },
10783
10870
  "default": "false",
10871
+ "description": "Disables the control.",
10784
10872
  "fieldName": "disabled"
10785
10873
  },
10786
10874
  {
@@ -10789,14 +10877,16 @@
10789
10877
  "text": "boolean"
10790
10878
  },
10791
10879
  "default": "false",
10880
+ "description": "Allows labels that aren't in the predefined list.",
10792
10881
  "fieldName": "allowCustom"
10793
10882
  },
10794
10883
  {
10795
10884
  "name": "predefined-labels",
10796
10885
  "type": {
10797
- "text": "array"
10886
+ "text": "(PredefinedLabel | string)[]"
10798
10887
  },
10799
10888
  "default": "[]",
10889
+ "description": "The predefined labels. Entries are either a string or `{name, options}`.",
10800
10890
  "fieldName": "predefinedLabels"
10801
10891
  }
10802
10892
  ],
@@ -10808,7 +10898,7 @@
10808
10898
  "tagNameWithoutPrefix": "defined-label",
10809
10899
  "tagName": "zn-defined-label",
10810
10900
  "customElement": true,
10811
- "jsDoc": "/**\n * @summary This component provides a labeled input with support for predefined and custom labels,\n * allowing users to select or enter label-value pairs within a dropdown interface.\n * @documentation https://zinc.style/components/defined-label\n * @status experimental\n * @since 1.0\n *\n * @dependency zn-button\n * @dependency zn-dropdown\n * @dependency zn-input\n * @dependency zn-option\n * @dependency zn-panel\n * @dependency zn-select\n * @dependency zn-sp\n *\n * @csspart input - The component's main input.\n * @csspart input-value - The label's value inputs.\n */",
10901
+ "jsDoc": "/**\n * @summary This component provides a labeled input with support for predefined and custom labels,\n * allowing users to select or enter label-value pairs within a dropdown interface.\n * @documentation https://zinc.style/components/defined-label\n * @status experimental\n * @since 1.0\n *\n * @dependency zn-button\n * @dependency zn-dropdown\n * @dependency zn-input\n * @dependency zn-option\n * @dependency zn-select\n *\n * @csspart input - The component's main input.\n * @csspart input-value - The label's value inputs.\n */",
10812
10902
  "documentation": "https://zinc.style/components/defined-label",
10813
10903
  "status": "experimental",
10814
10904
  "since": "1.0",
@@ -10817,9 +10907,7 @@
10817
10907
  "zn-dropdown",
10818
10908
  "zn-input",
10819
10909
  "zn-option",
10820
- "zn-panel",
10821
- "zn-select",
10822
- "zn-sp"
10910
+ "zn-select"
10823
10911
  ]
10824
10912
  }
10825
10913
  ],
@@ -12962,7 +13050,7 @@
12962
13050
  "name": "formControlController",
12963
13051
  "privacy": "private",
12964
13052
  "readonly": true,
12965
- "default": "new FormControlController(this, { assumeInteractionOn: ['zn-change'], // An explicitly cleared control submits an empty value so the server can // remove the stored upload; an untouched empty control submits nothing. value: (el: ZnFile) => { if (el.files?.length) return el.files; return el.clearedByUser ? '' : undefined; } })"
13053
+ "default": "new FormControlController(this, { assumeInteractionOn: ['zn-change'], // An explicitly cleared control submits an empty value so the server can // remove the stored upload; an untouched empty control submits nothing. // In upload-url mode the control submits the uploaded file's URL string // instead of the file bytes. value: (el: ZnFile) => { if (el.uploadUrl) { if (el.src) return el.src; return el.clearedByUser ? '' : undefined; } if (el.files?.length) return el.files; return el.clearedByUser ? '' : undefined; } })"
12966
13054
  },
12967
13055
  {
12968
13056
  "kind": "field",
@@ -13244,6 +13332,25 @@
13244
13332
  "description": "When enabled, render the current link (`previewSrc`) as a clickable URL below the control.\nUseful for showing the existing CDN link alongside the preview.",
13245
13333
  "attribute": "show-link"
13246
13334
  },
13335
+ {
13336
+ "kind": "field",
13337
+ "name": "uploadUrl",
13338
+ "type": {
13339
+ "text": "string"
13340
+ },
13341
+ "default": "''",
13342
+ "description": "When set, a chosen file is immediately POSTed (multipart, field `file`) to this URL.\nThe endpoint must respond with JSON `{\"url\": \"...\"}`; that URL becomes the control's\nvalue (and `src` preview) in place of the file bytes, so the control works inside\nJSON-serialising hosts such as `zn-page-builder`. Emits `zn-error` when the upload fails.",
13343
+ "attribute": "upload-url"
13344
+ },
13345
+ {
13346
+ "kind": "field",
13347
+ "name": "uploading",
13348
+ "type": {
13349
+ "text": "boolean"
13350
+ },
13351
+ "privacy": "private",
13352
+ "default": "false"
13353
+ },
13247
13354
  {
13248
13355
  "kind": "field",
13249
13356
  "name": "validity",
@@ -13397,6 +13504,20 @@
13397
13504
  ],
13398
13505
  "description": "Handles the change event of the native input"
13399
13506
  },
13507
+ {
13508
+ "kind": "method",
13509
+ "name": "uploadFile",
13510
+ "privacy": "private",
13511
+ "parameters": [
13512
+ {
13513
+ "name": "file",
13514
+ "type": {
13515
+ "text": "File"
13516
+ }
13517
+ }
13518
+ ],
13519
+ "description": "Uploads the chosen file to `uploadUrl` and adopts the returned URL as the\ncontrol's value. The local file preview stays visible while the upload runs."
13520
+ },
13400
13521
  {
13401
13522
  "kind": "field",
13402
13523
  "name": "handleDragOver",
@@ -13675,6 +13796,15 @@
13675
13796
  "default": "false",
13676
13797
  "description": "When enabled, render the current link (`previewSrc`) as a clickable URL below the control.\nUseful for showing the existing CDN link alongside the preview.",
13677
13798
  "fieldName": "showLink"
13799
+ },
13800
+ {
13801
+ "name": "upload-url",
13802
+ "type": {
13803
+ "text": "string"
13804
+ },
13805
+ "default": "''",
13806
+ "description": "When set, a chosen file is immediately POSTed (multipart, field `file`) to this URL.\nThe endpoint must respond with JSON `{\"url\": \"...\"}`; that URL becomes the control's\nvalue (and `src` preview) in place of the file bytes, so the control works inside\nJSON-serialising hosts such as `zn-page-builder`. Emits `zn-error` when the upload fails.",
13807
+ "fieldName": "uploadUrl"
13678
13808
  }
13679
13809
  ],
13680
13810
  "superclass": {
@@ -28272,11 +28402,25 @@
28272
28402
  "kind": "class",
28273
28403
  "description": "",
28274
28404
  "name": "ZnPreviewFrame",
28405
+ "cssProperties": [
28406
+ {
28407
+ "description": "Spacing of the backdrop dot grid (`backdrop=\"dots\"`). Defaults to 20px.",
28408
+ "name": "--zn-preview-frame-dot-spacing"
28409
+ },
28410
+ {
28411
+ "description": "Opacity of the backdrop dots (`backdrop=\"dots\"`). Defaults to 0.08.",
28412
+ "name": "--zn-preview-frame-dot-opacity"
28413
+ }
28414
+ ],
28275
28415
  "cssParts": [
28276
28416
  {
28277
28417
  "description": "The component's base wrapper.",
28278
28418
  "name": "base"
28279
28419
  },
28420
+ {
28421
+ "description": "The device-width wrapper around the iframe.",
28422
+ "name": "stage"
28423
+ },
28280
28424
  {
28281
28425
  "description": "The preview iframe.",
28282
28426
  "name": "iframe"
@@ -28327,6 +28471,16 @@
28327
28471
  "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.",
28328
28472
  "attribute": "watch"
28329
28473
  },
28474
+ {
28475
+ "kind": "field",
28476
+ "name": "refreshOn",
28477
+ "type": {
28478
+ "text": "string"
28479
+ },
28480
+ "default": "'form'",
28481
+ "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.",
28482
+ "attribute": "refresh-on"
28483
+ },
28330
28484
  {
28331
28485
  "kind": "field",
28332
28486
  "name": "debounce",
@@ -28344,7 +28498,7 @@
28344
28498
  "text": "number"
28345
28499
  },
28346
28500
  "default": "1",
28347
- "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.",
28501
+ "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.",
28348
28502
  "attribute": "zoom"
28349
28503
  },
28350
28504
  {
@@ -28354,9 +28508,41 @@
28354
28508
  "text": "number"
28355
28509
  },
28356
28510
  "default": "480",
28357
- "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.",
28511
+ "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.",
28358
28512
  "attribute": "min-height"
28359
28513
  },
28514
+ {
28515
+ "kind": "field",
28516
+ "name": "fill",
28517
+ "type": {
28518
+ "text": "boolean"
28519
+ },
28520
+ "default": "false",
28521
+ "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.",
28522
+ "attribute": "fill"
28523
+ },
28524
+ {
28525
+ "kind": "field",
28526
+ "name": "device",
28527
+ "type": {
28528
+ "text": "PreviewFrameDevice"
28529
+ },
28530
+ "default": "'desktop'",
28531
+ "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.",
28532
+ "attribute": "device",
28533
+ "reflects": true
28534
+ },
28535
+ {
28536
+ "kind": "field",
28537
+ "name": "backdrop",
28538
+ "type": {
28539
+ "text": "'dots' | 'panel'"
28540
+ },
28541
+ "default": "'dots'",
28542
+ "description": "Backdrop behind the stage: `dots` (default) is the canvas dot grid; `panel` is a plain `rgb(var(--zn-panel))` fill.",
28543
+ "attribute": "backdrop",
28544
+ "reflects": true
28545
+ },
28360
28546
  {
28361
28547
  "kind": "field",
28362
28548
  "name": "frame",
@@ -28382,6 +28568,14 @@
28382
28568
  "privacy": "private",
28383
28569
  "default": "0"
28384
28570
  },
28571
+ {
28572
+ "kind": "field",
28573
+ "name": "_theme",
28574
+ "type": {
28575
+ "text": "Record<string, unknown> | undefined"
28576
+ },
28577
+ "privacy": "private"
28578
+ },
28385
28579
  {
28386
28580
  "kind": "field",
28387
28581
  "name": "_watchedForms",
@@ -28389,6 +28583,13 @@
28389
28583
  "readonly": true,
28390
28584
  "default": "new Set<HTMLFormElement>()"
28391
28585
  },
28586
+ {
28587
+ "kind": "field",
28588
+ "name": "_refreshForms",
28589
+ "privacy": "private",
28590
+ "readonly": true,
28591
+ "default": "new Set<HTMLFormElement>()"
28592
+ },
28392
28593
  {
28393
28594
  "kind": "field",
28394
28595
  "name": "_debounceTimers",
@@ -28414,6 +28615,24 @@
28414
28615
  "name": "refresh",
28415
28616
  "description": "Re-fetches the payload and pushes a fresh config to the preview."
28416
28617
  },
28618
+ {
28619
+ "kind": "method",
28620
+ "name": "setTheme",
28621
+ "parameters": [
28622
+ {
28623
+ "name": "theme",
28624
+ "type": {
28625
+ "text": "Record<string, unknown>"
28626
+ }
28627
+ }
28628
+ ],
28629
+ "description": "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."
28630
+ },
28631
+ {
28632
+ "kind": "method",
28633
+ "name": "_postTheme",
28634
+ "privacy": "private"
28635
+ },
28417
28636
  {
28418
28637
  "kind": "method",
28419
28638
  "name": "_sendConfig",
@@ -28424,6 +28643,12 @@
28424
28643
  "name": "_attachForms",
28425
28644
  "privacy": "private"
28426
28645
  },
28646
+ {
28647
+ "kind": "field",
28648
+ "name": "_onShellSave",
28649
+ "privacy": "private",
28650
+ "readonly": true
28651
+ },
28427
28652
  {
28428
28653
  "kind": "method",
28429
28654
  "name": "_detachForm",
@@ -28519,6 +28744,15 @@
28519
28744
  "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.",
28520
28745
  "fieldName": "watch"
28521
28746
  },
28747
+ {
28748
+ "name": "refresh-on",
28749
+ "type": {
28750
+ "text": "string"
28751
+ },
28752
+ "default": "'form'",
28753
+ "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.",
28754
+ "fieldName": "refreshOn"
28755
+ },
28522
28756
  {
28523
28757
  "name": "debounce",
28524
28758
  "type": {
@@ -28534,7 +28768,7 @@
28534
28768
  "text": "number"
28535
28769
  },
28536
28770
  "default": "1",
28537
- "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.",
28771
+ "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.",
28538
28772
  "fieldName": "zoom"
28539
28773
  },
28540
28774
  {
@@ -28543,19 +28777,46 @@
28543
28777
  "text": "number"
28544
28778
  },
28545
28779
  "default": "480",
28546
- "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.",
28780
+ "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.",
28547
28781
  "fieldName": "minHeight"
28782
+ },
28783
+ {
28784
+ "name": "fill",
28785
+ "type": {
28786
+ "text": "boolean"
28787
+ },
28788
+ "default": "false",
28789
+ "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.",
28790
+ "fieldName": "fill"
28791
+ },
28792
+ {
28793
+ "name": "device",
28794
+ "type": {
28795
+ "text": "PreviewFrameDevice"
28796
+ },
28797
+ "default": "'desktop'",
28798
+ "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.",
28799
+ "fieldName": "device"
28800
+ },
28801
+ {
28802
+ "name": "backdrop",
28803
+ "type": {
28804
+ "text": "'dots' | 'panel'"
28805
+ },
28806
+ "default": "'dots'",
28807
+ "description": "Backdrop behind the stage: `dots` (default) is the canvas dot grid; `panel` is a plain `rgb(var(--zn-panel))` fill.",
28808
+ "fieldName": "backdrop"
28548
28809
  }
28549
28810
  ],
28550
28811
  "superclass": {
28551
28812
  "name": "ZincElement",
28552
28813
  "module": "/src/internal/zinc-element"
28553
28814
  },
28554
- "summary": "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.",
28815
+ "summary": "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.",
28555
28816
  "tagNameWithoutPrefix": "preview-frame",
28556
28817
  "tagName": "zn-preview-frame",
28557
28818
  "customElement": true,
28558
- "jsDoc": "/**\n * @summary Embeds a live preview iframe and drives the hp-preview postMessage\n * protocol: answers the frame's ready handshake with a config payload fetched\n * from data-uri, auto-saves watched forms on change, and refreshes the\n * preview after each save.\n * @documentation https://zinc.style/components/preview-frame\n * @status experimental\n * @since 1.0\n *\n * @event zn-error - Emitted when the preview reports a render error or a save fails.\n *\n * @csspart base - The component's base wrapper.\n * @csspart iframe - The preview iframe.\n * @csspart error - The error overlay.\n */",
28819
+ "jsDoc": "/**\n * @summary Embeds a live preview iframe and drives the hp-preview postMessage\n * protocol: answers the frame's ready handshake with a config payload fetched\n * from data-uri, auto-saves watched forms on change, refreshes the preview\n * after each save (its own, or a shell-driven save of a `refresh-on` form),\n * and accepts a theme payload via setTheme() that is retained and replayed\n * after every ready handshake.\n * @documentation https://zinc.style/components/preview-frame\n * @status experimental\n * @since 1.0\n *\n * @event zn-error - Emitted when the preview reports a render error or a save fails.\n *\n * @csspart base - The component's base wrapper.\n * @csspart stage - The device-width wrapper around the iframe.\n * @csspart iframe - The preview iframe.\n * @csspart error - The error overlay.\n *\n * @cssproperty --zn-preview-frame-dot-spacing - Spacing of the backdrop dot grid (`backdrop=\"dots\"`). Defaults to 20px.\n * @cssproperty --zn-preview-frame-dot-opacity - Opacity of the backdrop dots (`backdrop=\"dots\"`). Defaults to 0.08.\n */",
28559
28820
  "documentation": "https://zinc.style/components/preview-frame",
28560
28821
  "status": "experimental",
28561
28822
  "since": "1.0"
@@ -39661,6 +39922,1013 @@
39661
39922
  }
39662
39923
  ]
39663
39924
  },
39925
+ {
39926
+ "kind": "javascript-module",
39927
+ "path": "components/theme-editor/theme-editor.js",
39928
+ "declarations": [
39929
+ {
39930
+ "kind": "class",
39931
+ "description": "",
39932
+ "name": "ZnThemeEditor",
39933
+ "cssProperties": [
39934
+ {
39935
+ "description": "Width of the controls column.",
39936
+ "name": "--zn-theme-editor-controls-width"
39937
+ }
39938
+ ],
39939
+ "cssParts": [
39940
+ {
39941
+ "description": "The component's base wrapper.",
39942
+ "name": "base"
39943
+ },
39944
+ {
39945
+ "description": "The left-hand controls column, full height.",
39946
+ "name": "controls"
39947
+ },
39948
+ {
39949
+ "description": "The controls column's header row: `controls-caption` on the left, the light/dark mode toggle on the right.",
39950
+ "name": "controls-header"
39951
+ },
39952
+ {
39953
+ "description": "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.",
39954
+ "name": "toolbar"
39955
+ },
39956
+ {
39957
+ "description": "A rendered section's or group's collapsible (`section-layout=\"collapsible\"`, or any nested group).",
39958
+ "name": "section"
39959
+ },
39960
+ {
39961
+ "description": "The footer wrapper beneath the controls.",
39962
+ "name": "footer"
39963
+ },
39964
+ {
39965
+ "description": "The preview column.",
39966
+ "name": "preview"
39967
+ },
39968
+ {
39969
+ "description": "The inline error strip.",
39970
+ "name": "error"
39971
+ },
39972
+ {
39973
+ "description": "The frame's base wrapper (forwarded from zn-preview-frame).",
39974
+ "name": "preview__base"
39975
+ },
39976
+ {
39977
+ "description": "The frame's device-width wrapper (forwarded from zn-preview-frame).",
39978
+ "name": "preview__stage"
39979
+ },
39980
+ {
39981
+ "description": "The frame's iframe (forwarded from zn-preview-frame).",
39982
+ "name": "preview__iframe"
39983
+ },
39984
+ {
39985
+ "description": "The frame's own error overlay (forwarded from zn-preview-frame).",
39986
+ "name": "preview__error"
39987
+ }
39988
+ ],
39989
+ "slots": [
39990
+ {
39991
+ "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.",
39992
+ "name": ""
39993
+ },
39994
+ {
39995
+ "description": "Actions in the toolbar, right-aligned beside the device controls. Where a save button belongs.",
39996
+ "name": "toolbar"
39997
+ },
39998
+ {
39999
+ "description": "Actions pinned beneath the controls. The built-in submit button lives in the toolbar, not here.",
40000
+ "name": "footer"
40001
+ }
40002
+ ],
40003
+ "members": [
40004
+ {
40005
+ "kind": "field",
40006
+ "name": "dependencies",
40007
+ "type": {
40008
+ "text": "object"
40009
+ },
40010
+ "static": true,
40011
+ "default": "{ 'zn-collapsible': ZnCollapsible, 'zn-preview-frame': ZnPreviewFrame, 'zn-icon': ZnIcon, 'zn-button': ZnButton, 'zn-tabs': ZnTabs, 'zn-navbar': ZnNavbar, 'zn-select': ZnSelect, 'zn-option': ZnOption, }"
40012
+ },
40013
+ {
40014
+ "kind": "field",
40015
+ "name": "src",
40016
+ "type": {
40017
+ "text": "string"
40018
+ },
40019
+ "default": "''",
40020
+ "description": "URL of the preview shell page; forwarded to the frame.",
40021
+ "attribute": "src"
40022
+ },
40023
+ {
40024
+ "kind": "field",
40025
+ "name": "frameOrigin",
40026
+ "type": {
40027
+ "text": "string"
40028
+ },
40029
+ "default": "''",
40030
+ "description": "Expected origin of the iframe; forwarded to the frame.",
40031
+ "attribute": "frame-origin"
40032
+ },
40033
+ {
40034
+ "kind": "field",
40035
+ "name": "dataUri",
40036
+ "type": {
40037
+ "text": "string"
40038
+ },
40039
+ "default": "''",
40040
+ "description": "Optional endpoint returning the base hp-preview:config payload.",
40041
+ "attribute": "data-uri"
40042
+ },
40043
+ {
40044
+ "kind": "field",
40045
+ "name": "mode",
40046
+ "type": {
40047
+ "text": "ThemeEditorMode"
40048
+ },
40049
+ "default": "'light'",
40050
+ "description": "Which mode the preview renders in. Travels in the theme payload.",
40051
+ "attribute": "mode",
40052
+ "reflects": true
40053
+ },
40054
+ {
40055
+ "kind": "field",
40056
+ "name": "device",
40057
+ "type": {
40058
+ "text": "ThemeEditorDevice"
40059
+ },
40060
+ "default": "'desktop'",
40061
+ "description": "Preview viewport width. Resizes the frame only; not part of the payload.",
40062
+ "attribute": "device",
40063
+ "reflects": true
40064
+ },
40065
+ {
40066
+ "kind": "field",
40067
+ "name": "minHeight",
40068
+ "type": {
40069
+ "text": "number"
40070
+ },
40071
+ "default": "480",
40072
+ "description": "Minimum height of the preview row, in pixels; forwarded to the frame as its own floor.",
40073
+ "attribute": "min-height"
40074
+ },
40075
+ {
40076
+ "kind": "field",
40077
+ "name": "debounce",
40078
+ "type": {
40079
+ "text": "number"
40080
+ },
40081
+ "default": "150",
40082
+ "description": "Debounce in ms between a control change and the push to the preview.",
40083
+ "attribute": "debounce"
40084
+ },
40085
+ {
40086
+ "kind": "field",
40087
+ "name": "action",
40088
+ "type": {
40089
+ "text": "string"
40090
+ },
40091
+ "default": "''",
40092
+ "description": "Optional endpoint the values are POSTed to. Empty = no persistence.",
40093
+ "attribute": "action"
40094
+ },
40095
+ {
40096
+ "kind": "field",
40097
+ "name": "saveDebounce",
40098
+ "type": {
40099
+ "text": "number"
40100
+ },
40101
+ "default": "1000",
40102
+ "description": "Debounce in ms between a control change and the save POST.",
40103
+ "attribute": "save-debounce"
40104
+ },
40105
+ {
40106
+ "kind": "field",
40107
+ "name": "sections",
40108
+ "type": {
40109
+ "text": "ThemeEditorSection[]"
40110
+ },
40111
+ "default": "[]",
40112
+ "description": "Groups controls into named sections. Empty/unset renders one ungrouped\ncolumn. A section with a non-empty `groups` nests a collapsible per\ngroup inside a `zn-tabs` tab for that section - see `groups` on\n`ThemeEditorSection`.",
40113
+ "attribute": "sections"
40114
+ },
40115
+ {
40116
+ "kind": "field",
40117
+ "name": "sectionLayout",
40118
+ "type": {
40119
+ "text": "'collapsible' | 'tabs'"
40120
+ },
40121
+ "default": "'collapsible'",
40122
+ "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.",
40123
+ "attribute": "section-layout"
40124
+ },
40125
+ {
40126
+ "kind": "field",
40127
+ "name": "sources",
40128
+ "type": {
40129
+ "text": "ThemeEditorSource[]"
40130
+ },
40131
+ "default": "[]",
40132
+ "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.",
40133
+ "attribute": "sources"
40134
+ },
40135
+ {
40136
+ "kind": "field",
40137
+ "name": "controlsCollapsed",
40138
+ "type": {
40139
+ "text": "boolean"
40140
+ },
40141
+ "default": "false",
40142
+ "description": "Collapses the controls column.",
40143
+ "attribute": "controls-collapsed",
40144
+ "reflects": true
40145
+ },
40146
+ {
40147
+ "kind": "field",
40148
+ "name": "standalone",
40149
+ "type": {
40150
+ "text": "boolean"
40151
+ },
40152
+ "default": "false",
40153
+ "description": "Presents the editor as its own bordered, rounded panel with a plain preview backdrop, rather than embedded in a dotted canvas.",
40154
+ "attribute": "standalone",
40155
+ "reflects": true
40156
+ },
40157
+ {
40158
+ "kind": "field",
40159
+ "name": "controlsCaption",
40160
+ "type": {
40161
+ "text": "string"
40162
+ },
40163
+ "default": "''",
40164
+ "description": "Caption in the controls column's header row. Empty (default) renders no text; the row itself always renders.",
40165
+ "attribute": "controls-caption"
40166
+ },
40167
+ {
40168
+ "kind": "field",
40169
+ "name": "previewCaption",
40170
+ "type": {
40171
+ "text": "string"
40172
+ },
40173
+ "default": "''",
40174
+ "description": "Caption at the left of the toolbar, opposite the device and mode controls. Empty (default) renders no text.",
40175
+ "attribute": "preview-caption"
40176
+ },
40177
+ {
40178
+ "kind": "field",
40179
+ "name": "submitLabel",
40180
+ "type": {
40181
+ "text": "string"
40182
+ },
40183
+ "default": "''",
40184
+ "description": "Label for the built-in submit button. Empty (default) renders no button.",
40185
+ "attribute": "submit-label"
40186
+ },
40187
+ {
40188
+ "kind": "field",
40189
+ "name": "manual",
40190
+ "type": {
40191
+ "text": "boolean"
40192
+ },
40193
+ "default": "false",
40194
+ "description": "Disables the debounced auto-save; saving then happens only via submit. Preview pushes are unaffected.",
40195
+ "attribute": "manual"
40196
+ },
40197
+ {
40198
+ "kind": "field",
40199
+ "name": "frame",
40200
+ "type": {
40201
+ "text": "ZnPreviewFrame"
40202
+ }
40203
+ },
40204
+ {
40205
+ "kind": "field",
40206
+ "name": "controlsSlot",
40207
+ "type": {
40208
+ "text": "HTMLSlotElement"
40209
+ },
40210
+ "privacy": "private"
40211
+ },
40212
+ {
40213
+ "kind": "field",
40214
+ "name": "sectionSlots",
40215
+ "type": {
40216
+ "text": "NodeListOf<HTMLSlotElement>"
40217
+ },
40218
+ "privacy": "private"
40219
+ },
40220
+ {
40221
+ "kind": "field",
40222
+ "name": "error",
40223
+ "type": {
40224
+ "text": "string"
40225
+ },
40226
+ "privacy": "protected",
40227
+ "default": "''"
40228
+ },
40229
+ {
40230
+ "kind": "field",
40231
+ "name": "_submitting",
40232
+ "type": {
40233
+ "text": "boolean"
40234
+ },
40235
+ "privacy": "private",
40236
+ "default": "false"
40237
+ },
40238
+ {
40239
+ "kind": "field",
40240
+ "name": "_sourceIndex",
40241
+ "type": {
40242
+ "text": "number"
40243
+ },
40244
+ "privacy": "private",
40245
+ "default": "0"
40246
+ },
40247
+ {
40248
+ "kind": "field",
40249
+ "name": "hasSlotController",
40250
+ "privacy": "private",
40251
+ "readonly": true,
40252
+ "default": "new HasSlotController(this, 'footer', '[default]')"
40253
+ },
40254
+ {
40255
+ "kind": "field",
40256
+ "name": "_pushTimer",
40257
+ "type": {
40258
+ "text": "number | undefined"
40259
+ },
40260
+ "privacy": "private"
40261
+ },
40262
+ {
40263
+ "kind": "field",
40264
+ "name": "_saveTimer",
40265
+ "type": {
40266
+ "text": "number | undefined"
40267
+ },
40268
+ "privacy": "private"
40269
+ },
40270
+ {
40271
+ "kind": "field",
40272
+ "name": "_saving",
40273
+ "type": {
40274
+ "text": "boolean"
40275
+ },
40276
+ "privacy": "private",
40277
+ "default": "false"
40278
+ },
40279
+ {
40280
+ "kind": "field",
40281
+ "name": "_saveQueued",
40282
+ "type": {
40283
+ "text": "boolean"
40284
+ },
40285
+ "privacy": "private",
40286
+ "default": "false"
40287
+ },
40288
+ {
40289
+ "kind": "field",
40290
+ "name": "_saveWaiters",
40291
+ "type": {
40292
+ "text": "((ok: boolean) => void)[]"
40293
+ },
40294
+ "privacy": "private",
40295
+ "default": "[]"
40296
+ },
40297
+ {
40298
+ "kind": "field",
40299
+ "name": "_narrowQuery",
40300
+ "privacy": "private",
40301
+ "readonly": true
40302
+ },
40303
+ {
40304
+ "kind": "field",
40305
+ "name": "_wasNarrow",
40306
+ "type": {
40307
+ "text": "boolean"
40308
+ },
40309
+ "privacy": "private",
40310
+ "default": "false"
40311
+ },
40312
+ {
40313
+ "kind": "field",
40314
+ "name": "_mounted",
40315
+ "type": {
40316
+ "text": "boolean"
40317
+ },
40318
+ "privacy": "private",
40319
+ "default": "false"
40320
+ },
40321
+ {
40322
+ "kind": "field",
40323
+ "name": "_lastControls",
40324
+ "type": {
40325
+ "text": "HarvestableControl[]"
40326
+ },
40327
+ "privacy": "private",
40328
+ "default": "[]"
40329
+ },
40330
+ {
40331
+ "kind": "field",
40332
+ "name": "_controlsObserverConfig",
40333
+ "type": {
40334
+ "text": "MutationObserverInit"
40335
+ },
40336
+ "privacy": "private",
40337
+ "readonly": true,
40338
+ "default": "{ childList: true, subtree: true }"
40339
+ },
40340
+ {
40341
+ "kind": "field",
40342
+ "name": "_controlsObserver",
40343
+ "privacy": "private",
40344
+ "readonly": true,
40345
+ "default": "new MutationController(this, { target: null, config: this._controlsObserverConfig, callback: () => this._pushIfControlsChanged(), })"
40346
+ },
40347
+ {
40348
+ "kind": "field",
40349
+ "name": "_modeValues",
40350
+ "type": {
40351
+ "text": "Record<ThemeEditorMode, Record<string, unknown>>"
40352
+ },
40353
+ "privacy": "private",
40354
+ "default": "{ light: {}, dark: {} }"
40355
+ },
40356
+ {
40357
+ "kind": "field",
40358
+ "name": "_suppressDepth",
40359
+ "type": {
40360
+ "text": "number"
40361
+ },
40362
+ "privacy": "private",
40363
+ "default": "0"
40364
+ },
40365
+ {
40366
+ "kind": "field",
40367
+ "name": "values",
40368
+ "type": {
40369
+ "text": "{ light: Record<string, unknown>; dark: Record<string, unknown> }"
40370
+ },
40371
+ "description": "The current per-mode value sets. Returns copies.",
40372
+ "readonly": true
40373
+ },
40374
+ {
40375
+ "kind": "field",
40376
+ "name": "activeValues",
40377
+ "type": {
40378
+ "text": "Record<string, unknown>"
40379
+ },
40380
+ "description": "The active mode's values - what gets pushed to the preview frame.",
40381
+ "readonly": true
40382
+ },
40383
+ {
40384
+ "kind": "method",
40385
+ "name": "_controlSlots",
40386
+ "privacy": "private",
40387
+ "return": {
40388
+ "type": {
40389
+ "text": "HTMLSlotElement[]"
40390
+ }
40391
+ },
40392
+ "description": "The default slot plus every rendered section slot."
40393
+ },
40394
+ {
40395
+ "kind": "method",
40396
+ "name": "_harvestNamed",
40397
+ "privacy": "private",
40398
+ "return": {
40399
+ "type": {
40400
+ "text": "{ name: string; control: HarvestableControl }[]"
40401
+ }
40402
+ },
40403
+ "description": "Walks every control slot (default and sections) for every enabled, named control."
40404
+ },
40405
+ {
40406
+ "kind": "method",
40407
+ "name": "_hasAssignedControls",
40408
+ "privacy": "private",
40409
+ "return": {
40410
+ "type": {
40411
+ "text": "boolean"
40412
+ }
40413
+ },
40414
+ "parameters": [
40415
+ {
40416
+ "name": "slotName",
40417
+ "type": {
40418
+ "text": "string"
40419
+ }
40420
+ }
40421
+ ],
40422
+ "description": "Whether a direct child is assigned to the named slot — an empty section renders no chrome."
40423
+ },
40424
+ {
40425
+ "kind": "method",
40426
+ "name": "_isBooleanControl",
40427
+ "privacy": "private",
40428
+ "return": {
40429
+ "type": {
40430
+ "text": "boolean"
40431
+ }
40432
+ },
40433
+ "parameters": [
40434
+ {
40435
+ "name": "control",
40436
+ "type": {
40437
+ "text": "HarvestableControl"
40438
+ }
40439
+ }
40440
+ ]
40441
+ },
40442
+ {
40443
+ "kind": "method",
40444
+ "name": "_readControlValue",
40445
+ "privacy": "private",
40446
+ "return": {
40447
+ "type": {
40448
+ "text": "unknown"
40449
+ }
40450
+ },
40451
+ "parameters": [
40452
+ {
40453
+ "name": "control",
40454
+ "type": {
40455
+ "text": "HarvestableControl"
40456
+ }
40457
+ }
40458
+ ]
40459
+ },
40460
+ {
40461
+ "kind": "method",
40462
+ "name": "_seed",
40463
+ "privacy": "private",
40464
+ "description": "Seeds light/dark entries for any control name not already present."
40465
+ },
40466
+ {
40467
+ "kind": "method",
40468
+ "name": "_writeBack",
40469
+ "privacy": "private",
40470
+ "parameters": [
40471
+ {
40472
+ "name": "mode",
40473
+ "default": "this.mode",
40474
+ "type": {
40475
+ "text": "ThemeEditorMode"
40476
+ }
40477
+ }
40478
+ ],
40479
+ "description": "Writes a mode's value set back into the controls so they display it."
40480
+ },
40481
+ {
40482
+ "kind": "method",
40483
+ "name": "_harvestInto",
40484
+ "privacy": "private",
40485
+ "parameters": [
40486
+ {
40487
+ "name": "mode",
40488
+ "type": {
40489
+ "text": "ThemeEditorMode"
40490
+ }
40491
+ }
40492
+ ],
40493
+ "description": "Harvests the controls' current displayed values into a mode's set."
40494
+ },
40495
+ {
40496
+ "kind": "field",
40497
+ "name": "_onNarrowChange",
40498
+ "privacy": "private",
40499
+ "readonly": true
40500
+ },
40501
+ {
40502
+ "kind": "method",
40503
+ "name": "_push",
40504
+ "privacy": "private",
40505
+ "description": "Pushes the active mode's values into the preview and announces it."
40506
+ },
40507
+ {
40508
+ "kind": "method",
40509
+ "name": "_queueSave",
40510
+ "privacy": "private"
40511
+ },
40512
+ {
40513
+ "kind": "method",
40514
+ "name": "_save",
40515
+ "privacy": "private"
40516
+ },
40517
+ {
40518
+ "kind": "method",
40519
+ "name": "_awaitSave",
40520
+ "privacy": "private",
40521
+ "return": {
40522
+ "type": {
40523
+ "text": "Promise<boolean>"
40524
+ }
40525
+ },
40526
+ "description": "Resolves once a save actually carrying the current values has settled."
40527
+ },
40528
+ {
40529
+ "kind": "method",
40530
+ "name": "_pushIfControlsChanged",
40531
+ "privacy": "private",
40532
+ "description": "Pushes only if the deep set of named controls (the same set harvesting\nwalks, so it includes controls nested inside sections) has changed since\nthe last push. Comparison is by element identity only, never by value."
40533
+ },
40534
+ {
40535
+ "kind": "method",
40536
+ "name": "_flushPendingEdit",
40537
+ "privacy": "private",
40538
+ "description": "Harvests and queues a save for a pending debounced edit, then cancels its timer."
40539
+ },
40540
+ {
40541
+ "kind": "field",
40542
+ "name": "_onSubmit",
40543
+ "privacy": "private",
40544
+ "readonly": true
40545
+ },
40546
+ {
40547
+ "kind": "method",
40548
+ "name": "_announce",
40549
+ "privacy": "private"
40550
+ },
40551
+ {
40552
+ "kind": "method",
40553
+ "name": "_fail",
40554
+ "privacy": "private",
40555
+ "parameters": [
40556
+ {
40557
+ "name": "message",
40558
+ "type": {
40559
+ "text": "string"
40560
+ }
40561
+ }
40562
+ ]
40563
+ },
40564
+ {
40565
+ "kind": "field",
40566
+ "name": "_onControlChange",
40567
+ "privacy": "private",
40568
+ "readonly": true
40569
+ },
40570
+ {
40571
+ "kind": "field",
40572
+ "name": "_onSlotChange",
40573
+ "privacy": "private",
40574
+ "readonly": true
40575
+ },
40576
+ {
40577
+ "kind": "field",
40578
+ "name": "_setDevice",
40579
+ "privacy": "private",
40580
+ "readonly": true
40581
+ },
40582
+ {
40583
+ "kind": "field",
40584
+ "name": "_toggleMode",
40585
+ "privacy": "private",
40586
+ "readonly": true
40587
+ },
40588
+ {
40589
+ "kind": "field",
40590
+ "name": "_onFrameError",
40591
+ "privacy": "private",
40592
+ "readonly": true
40593
+ },
40594
+ {
40595
+ "kind": "method",
40596
+ "name": "_sourcesSafe",
40597
+ "privacy": "private",
40598
+ "return": {
40599
+ "type": {
40600
+ "text": "ThemeEditorSource[]"
40601
+ }
40602
+ }
40603
+ },
40604
+ {
40605
+ "kind": "method",
40606
+ "name": "_frameSrc",
40607
+ "privacy": "private",
40608
+ "return": {
40609
+ "type": {
40610
+ "text": "string"
40611
+ }
40612
+ }
40613
+ },
40614
+ {
40615
+ "kind": "field",
40616
+ "name": "_onSourceChange",
40617
+ "privacy": "private",
40618
+ "readonly": true
40619
+ },
40620
+ {
40621
+ "kind": "method",
40622
+ "name": "_sectionsSafe",
40623
+ "privacy": "private",
40624
+ "return": {
40625
+ "type": {
40626
+ "text": "ThemeEditorSection[]"
40627
+ }
40628
+ }
40629
+ },
40630
+ {
40631
+ "kind": "method",
40632
+ "name": "_groupsFor",
40633
+ "privacy": "private",
40634
+ "return": {
40635
+ "type": {
40636
+ "text": "ThemeEditorGroup[]"
40637
+ }
40638
+ },
40639
+ "parameters": [
40640
+ {
40641
+ "name": "section",
40642
+ "type": {
40643
+ "text": "ThemeEditorSection"
40644
+ }
40645
+ }
40646
+ ]
40647
+ },
40648
+ {
40649
+ "kind": "method",
40650
+ "name": "_hasNestedGroups",
40651
+ "privacy": "private",
40652
+ "return": {
40653
+ "type": {
40654
+ "text": "boolean"
40655
+ }
40656
+ },
40657
+ "description": "Whether any section has a populated `groups` - the switch to nested tabs+collapsibles."
40658
+ },
40659
+ {
40660
+ "kind": "method",
40661
+ "name": "_visibleGroups",
40662
+ "privacy": "private",
40663
+ "return": {
40664
+ "type": {
40665
+ "text": "ThemeEditorGroup[]"
40666
+ }
40667
+ },
40668
+ "parameters": [
40669
+ {
40670
+ "name": "section",
40671
+ "type": {
40672
+ "text": "ThemeEditorSection"
40673
+ }
40674
+ }
40675
+ ]
40676
+ },
40677
+ {
40678
+ "kind": "method",
40679
+ "name": "_visibleSections",
40680
+ "privacy": "private",
40681
+ "return": {
40682
+ "type": {
40683
+ "text": "ThemeEditorSection[]"
40684
+ }
40685
+ },
40686
+ "description": "Configured sections that have an assigned control, or (nested) a populated group - shared by every presentation."
40687
+ },
40688
+ {
40689
+ "kind": "method",
40690
+ "name": "_renderSections",
40691
+ "privacy": "private"
40692
+ },
40693
+ {
40694
+ "kind": "method",
40695
+ "name": "_renderGroups",
40696
+ "privacy": "private",
40697
+ "parameters": [
40698
+ {
40699
+ "name": "section",
40700
+ "type": {
40701
+ "text": "ThemeEditorSection"
40702
+ }
40703
+ }
40704
+ ]
40705
+ },
40706
+ {
40707
+ "kind": "method",
40708
+ "name": "_renderTabs",
40709
+ "privacy": "private",
40710
+ "parameters": [
40711
+ {
40712
+ "name": "panel",
40713
+ "type": {
40714
+ "text": "(section: ThemeEditorSection) => unknown"
40715
+ }
40716
+ }
40717
+ ]
40718
+ }
40719
+ ],
40720
+ "events": [
40721
+ {
40722
+ "description": "Emitted when the values, mode or device change.",
40723
+ "name": "zn-theme-change"
40724
+ },
40725
+ {
40726
+ "description": "Emitted on submit (button click), carrying the current values. With `action` set, only fires after a successful save.",
40727
+ "name": "zn-theme-submit"
40728
+ },
40729
+ {
40730
+ "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.",
40731
+ "name": "zn-error"
40732
+ }
40733
+ ],
40734
+ "attributes": [
40735
+ {
40736
+ "name": "src",
40737
+ "type": {
40738
+ "text": "string"
40739
+ },
40740
+ "default": "''",
40741
+ "description": "URL of the preview shell page; forwarded to the frame.",
40742
+ "fieldName": "src"
40743
+ },
40744
+ {
40745
+ "name": "frame-origin",
40746
+ "type": {
40747
+ "text": "string"
40748
+ },
40749
+ "default": "''",
40750
+ "description": "Expected origin of the iframe; forwarded to the frame.",
40751
+ "fieldName": "frameOrigin"
40752
+ },
40753
+ {
40754
+ "name": "data-uri",
40755
+ "type": {
40756
+ "text": "string"
40757
+ },
40758
+ "default": "''",
40759
+ "description": "Optional endpoint returning the base hp-preview:config payload.",
40760
+ "fieldName": "dataUri"
40761
+ },
40762
+ {
40763
+ "name": "mode",
40764
+ "type": {
40765
+ "text": "ThemeEditorMode"
40766
+ },
40767
+ "default": "'light'",
40768
+ "description": "Which mode the preview renders in. Travels in the theme payload.",
40769
+ "fieldName": "mode"
40770
+ },
40771
+ {
40772
+ "name": "device",
40773
+ "type": {
40774
+ "text": "ThemeEditorDevice"
40775
+ },
40776
+ "default": "'desktop'",
40777
+ "description": "Preview viewport width. Resizes the frame only; not part of the payload.",
40778
+ "fieldName": "device"
40779
+ },
40780
+ {
40781
+ "name": "min-height",
40782
+ "type": {
40783
+ "text": "number"
40784
+ },
40785
+ "default": "480",
40786
+ "description": "Minimum height of the preview row, in pixels; forwarded to the frame as its own floor.",
40787
+ "fieldName": "minHeight"
40788
+ },
40789
+ {
40790
+ "name": "debounce",
40791
+ "type": {
40792
+ "text": "number"
40793
+ },
40794
+ "default": "150",
40795
+ "description": "Debounce in ms between a control change and the push to the preview.",
40796
+ "fieldName": "debounce"
40797
+ },
40798
+ {
40799
+ "name": "action",
40800
+ "type": {
40801
+ "text": "string"
40802
+ },
40803
+ "default": "''",
40804
+ "description": "Optional endpoint the values are POSTed to. Empty = no persistence.",
40805
+ "fieldName": "action"
40806
+ },
40807
+ {
40808
+ "name": "save-debounce",
40809
+ "type": {
40810
+ "text": "number"
40811
+ },
40812
+ "default": "1000",
40813
+ "description": "Debounce in ms between a control change and the save POST.",
40814
+ "fieldName": "saveDebounce"
40815
+ },
40816
+ {
40817
+ "name": "sections",
40818
+ "type": {
40819
+ "text": "ThemeEditorSection[]"
40820
+ },
40821
+ "default": "[]",
40822
+ "description": "Groups controls into named sections. Empty/unset renders one ungrouped\ncolumn. A section with a non-empty `groups` nests a collapsible per\ngroup inside a `zn-tabs` tab for that section - see `groups` on\n`ThemeEditorSection`.",
40823
+ "fieldName": "sections"
40824
+ },
40825
+ {
40826
+ "name": "section-layout",
40827
+ "type": {
40828
+ "text": "'collapsible' | 'tabs'"
40829
+ },
40830
+ "default": "'collapsible'",
40831
+ "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.",
40832
+ "fieldName": "sectionLayout"
40833
+ },
40834
+ {
40835
+ "name": "sources",
40836
+ "type": {
40837
+ "text": "ThemeEditorSource[]"
40838
+ },
40839
+ "default": "[]",
40840
+ "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.",
40841
+ "fieldName": "sources"
40842
+ },
40843
+ {
40844
+ "name": "controls-collapsed",
40845
+ "type": {
40846
+ "text": "boolean"
40847
+ },
40848
+ "default": "false",
40849
+ "description": "Collapses the controls column.",
40850
+ "fieldName": "controlsCollapsed"
40851
+ },
40852
+ {
40853
+ "name": "standalone",
40854
+ "type": {
40855
+ "text": "boolean"
40856
+ },
40857
+ "default": "false",
40858
+ "description": "Presents the editor as its own bordered, rounded panel with a plain preview backdrop, rather than embedded in a dotted canvas.",
40859
+ "fieldName": "standalone"
40860
+ },
40861
+ {
40862
+ "name": "controls-caption",
40863
+ "type": {
40864
+ "text": "string"
40865
+ },
40866
+ "default": "''",
40867
+ "description": "Caption in the controls column's header row. Empty (default) renders no text; the row itself always renders.",
40868
+ "fieldName": "controlsCaption"
40869
+ },
40870
+ {
40871
+ "name": "preview-caption",
40872
+ "type": {
40873
+ "text": "string"
40874
+ },
40875
+ "default": "''",
40876
+ "description": "Caption at the left of the toolbar, opposite the device and mode controls. Empty (default) renders no text.",
40877
+ "fieldName": "previewCaption"
40878
+ },
40879
+ {
40880
+ "name": "submit-label",
40881
+ "type": {
40882
+ "text": "string"
40883
+ },
40884
+ "default": "''",
40885
+ "description": "Label for the built-in submit button. Empty (default) renders no button.",
40886
+ "fieldName": "submitLabel"
40887
+ },
40888
+ {
40889
+ "name": "manual",
40890
+ "type": {
40891
+ "text": "boolean"
40892
+ },
40893
+ "default": "false",
40894
+ "description": "Disables the debounced auto-save; saving then happens only via submit. Preview pushes are unaffected.",
40895
+ "fieldName": "manual"
40896
+ }
40897
+ ],
40898
+ "superclass": {
40899
+ "name": "ZincElement",
40900
+ "module": "/src/internal/zinc-element"
40901
+ },
40902
+ "summary": "A theme editor: slotted form controls drive a live preview frame,\nwith a toolbar for the preview's light/dark mode and device width.",
40903
+ "tagNameWithoutPrefix": "theme-editor",
40904
+ "tagName": "zn-theme-editor",
40905
+ "customElement": true,
40906
+ "jsDoc": "/**\n * @summary A theme editor: slotted form controls drive a live preview frame,\n * with a toolbar for the preview's light/dark mode and device width.\n * @documentation https://zinc.style/components/theme-editor\n * @status experimental\n * @since 1.0\n *\n * @dependency zn-collapsible\n * @dependency zn-preview-frame\n * @dependency zn-icon\n * @dependency zn-button\n * @dependency zn-tabs\n * @dependency zn-navbar\n * @dependency zn-select\n *\n * @event zn-theme-change - Emitted when the values, mode or device change.\n * @event zn-theme-submit - Emitted on submit (button click), carrying the\n * current values. With `action` set, only fires after a successful save.\n * @event zn-error - Emitted when a save fails. Also seen for preview render\n * failures: the frame's zn-error is composed and not stopped, so it bubbles\n * out through the editor too.\n *\n * @slot - Ungrouped theme controls, rendered above any sections. Controls\n * assigned `slot=\"<name>\"` matching a `sections` entry (or, when nested, a\n * `groups` entry) render inside that section/group instead. Harvesting and\n * change detection walk every slot's full assigned subtree, not just direct\n * children.\n * @slot toolbar - Actions in the toolbar, right-aligned beside the device\n * controls. Where a save button belongs.\n * @slot footer - Actions pinned beneath the controls. The built-in submit button\n * lives in the toolbar, not here.\n *\n * @csspart base - The component's base wrapper.\n * @csspart controls - The left-hand controls column, full height.\n * @csspart controls-header - The controls column's header row: `controls-caption` on the left, the light/dark mode toggle on the right.\n * @csspart 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 * @csspart section - A rendered section's or group's collapsible (`section-layout=\"collapsible\"`, or any nested group).\n * @csspart footer - The footer wrapper beneath the controls.\n * @csspart preview - The preview column.\n * @csspart error - The inline error strip.\n * @csspart preview__base - The frame's base wrapper (forwarded from zn-preview-frame).\n * @csspart preview__stage - The frame's device-width wrapper (forwarded from zn-preview-frame).\n * @csspart preview__iframe - The frame's iframe (forwarded from zn-preview-frame).\n * @csspart preview__error - The frame's own error overlay (forwarded from zn-preview-frame).\n *\n * @cssproperty --zn-theme-editor-controls-width - Width of the controls column.\n */",
40907
+ "documentation": "https://zinc.style/components/theme-editor",
40908
+ "status": "experimental",
40909
+ "since": "1.0",
40910
+ "dependencies": [
40911
+ "zn-collapsible",
40912
+ "zn-preview-frame",
40913
+ "zn-icon",
40914
+ "zn-button",
40915
+ "zn-tabs",
40916
+ "zn-navbar",
40917
+ "zn-select"
40918
+ ]
40919
+ }
40920
+ ],
40921
+ "exports": [
40922
+ {
40923
+ "kind": "js",
40924
+ "name": "default",
40925
+ "declaration": {
40926
+ "name": "ZnThemeEditor",
40927
+ "module": "components/theme-editor/theme-editor.js"
40928
+ }
40929
+ }
40930
+ ]
40931
+ },
39664
40932
  {
39665
40933
  "kind": "javascript-module",
39666
40934
  "path": "components/tile/tile.js",
@@ -42314,7 +43582,7 @@
42314
43582
  "package": {
42315
43583
  "name": "@kubex/zinc",
42316
43584
  "description": "A collection of web components for building web applications based off of @shoelace-style/Shoelace",
42317
- "version": "1.1.67",
43585
+ "version": "1.1.69",
42318
43586
  "author": "",
42319
43587
  "license": "MIT"
42320
43588
  }