@gramlot/gramlot-examples 0.2.15 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +12 -5
  2. package/package.json +4 -3
  3. package/src/gramlot_examples/catalog.json +163 -1
  4. package/src/gramlot_examples/gallery/collections.js +4 -0
  5. package/src/gramlot_examples/gallery/dist/frame.js +88 -28
  6. package/src/gramlot_examples/gallery/dist/gallery.js +211 -52
  7. package/src/gramlot_examples/gallery/dist/inputs.js +24456 -0
  8. package/src/gramlot_examples/gallery/dist/inspector.js +42 -18
  9. package/src/gramlot_examples/gallery/dist/layout.js +541 -0
  10. package/src/gramlot_examples/gallery/dist/theme-styles.js +2 -2
  11. package/src/gramlot_examples/gallery/gallery-page.js +49 -17
  12. package/src/gramlot_examples/gallery/gallery.css +50 -4
  13. package/src/gramlot_examples/index.js +3 -2
  14. package/src/gramlot_examples/pages/README.md +5 -2
  15. package/src/gramlot_examples/pages/binding/06_style_and_visibility.md +77 -12
  16. package/src/gramlot_examples/pages/binding/09_forms.js +1 -1
  17. package/src/gramlot_examples/pages/components/01_textbox.js +32 -0
  18. package/src/gramlot_examples/pages/components/01_textbox.md +14 -0
  19. package/src/gramlot_examples/pages/components/02_checkbox.js +25 -0
  20. package/src/gramlot_examples/pages/components/02_checkbox.md +14 -0
  21. package/src/gramlot_examples/pages/components/03_radio_button_text.js +30 -0
  22. package/src/gramlot_examples/pages/components/03_radio_button_text.md +16 -0
  23. package/src/gramlot_examples/pages/components/04_text_box_area.js +23 -0
  24. package/src/gramlot_examples/pages/components/04_text_box_area.md +14 -0
  25. package/src/gramlot_examples/pages/components/05_passwordbox.js +23 -0
  26. package/src/gramlot_examples/pages/components/05_passwordbox.md +14 -0
  27. package/src/gramlot_examples/pages/components/06_radio_button.js +28 -0
  28. package/src/gramlot_examples/pages/components/06_radio_button.md +14 -0
  29. package/src/gramlot_examples/pages/components/07_colorpicker.js +24 -0
  30. package/src/gramlot_examples/pages/components/07_colorpicker.md +14 -0
  31. package/src/gramlot_examples/pages/components/08_horizontal_slider.js +24 -0
  32. package/src/gramlot_examples/pages/components/08_horizontal_slider.md +14 -0
  33. package/src/gramlot_examples/pages/components/09_vertical_slider.js +24 -0
  34. package/src/gramlot_examples/pages/components/09_vertical_slider.md +14 -0
  35. package/src/gramlot_examples/pages/components/10_number_textbox.js +30 -0
  36. package/src/gramlot_examples/pages/components/10_number_textbox.md +16 -0
  37. package/src/gramlot_examples/pages/components/11_date_textbox.js +23 -0
  38. package/src/gramlot_examples/pages/components/11_date_textbox.md +18 -0
  39. package/src/gramlot_examples/pages/components/12_time_textbox.js +23 -0
  40. package/src/gramlot_examples/pages/components/12_time_textbox.md +16 -0
  41. package/src/gramlot_examples/pages/components/13_filtering_select.js +23 -0
  42. package/src/gramlot_examples/pages/components/13_filtering_select.md +20 -0
  43. package/src/gramlot_examples/pages/components/14_callback_select.js +45 -0
  44. package/src/gramlot_examples/pages/components/14_callback_select.md +24 -0
  45. package/src/gramlot_examples/pages/components/15_combo_box.js +23 -0
  46. package/src/gramlot_examples/pages/components/15_combo_box.md +22 -0
  47. package/src/gramlot_examples/pages/components/16_checkbox_text.js +23 -0
  48. package/src/gramlot_examples/pages/components/16_checkbox_text.md +23 -0
  49. package/src/gramlot_examples/pages/components/17_date_calendar.js +25 -0
  50. package/src/gramlot_examples/pages/components/17_date_calendar.md +22 -0
  51. package/src/gramlot_examples/pages/components/18_validation.js +31 -0
  52. package/src/gramlot_examples/pages/components/18_validation.md +29 -0
  53. package/src/gramlot_examples/pages/components/19_formlet.js +26 -0
  54. package/src/gramlot_examples/pages/components/19_formlet.md +12 -0
  55. package/src/gramlot_examples/pages/components/20_group_box.js +26 -0
  56. package/src/gramlot_examples/pages/components/20_group_box.md +12 -0
  57. package/src/gramlot_examples/pages/components/21_switch.js +19 -0
  58. package/src/gramlot_examples/pages/components/21_switch.md +12 -0
  59. package/src/gramlot_examples/pages/components/22_button.js +18 -0
  60. package/src/gramlot_examples/pages/components/22_button.md +12 -0
  61. package/src/gramlot_examples/pages/components/23_toggle_button.js +18 -0
  62. package/src/gramlot_examples/pages/components/23_toggle_button.md +12 -0
  63. package/src/gramlot_examples/pages/components/24_dropdown_button.js +21 -0
  64. package/src/gramlot_examples/pages/components/24_dropdown_button.md +12 -0
  65. package/src/gramlot_examples/pages/components/25_validation_engine.js +51 -0
  66. package/src/gramlot_examples/pages/components/25_validation_engine.md +26 -0
  67. package/src/gramlot_examples/pages/components/README.md +40 -0
  68. package/src/gramlot_examples/pages/controllers/02_controller.js +1 -1
  69. package/src/gramlot_examples/pages/controllers/16_attribute_projection.js +3 -3
  70. package/src/gramlot_examples/pages/controllers/16_attribute_projection.md +8 -8
  71. package/src/gramlot_examples/pages/controllers/22_pointer_transforms.js +39 -0
  72. package/src/gramlot_examples/pages/controllers/22_pointer_transforms.md +64 -0
  73. package/src/gramlot_examples/pages/controllers/README.md +3 -0
  74. package/src/gramlot_examples/pages/html_svg/06_forms.js +3 -3
@@ -49,6 +49,9 @@
49
49
  }
50
50
  throw new Error(`Invalid ${type} value: ${text || "(empty)"}`);
51
51
  }
52
+ function readParameterEnums(node) {
53
+ return Object.fromEntries(Object.entries(node._getMeta("gramlot_component")?.parameters ?? {}).filter(([, spec]) => spec.enum).map(([name, spec]) => [name, spec.enum]));
54
+ }
52
55
  var InspectorStyles = class {
53
56
  #document;
54
57
  #element = null;
@@ -137,7 +140,7 @@
137
140
  if (!identities.has(node)) identities.set(node, ++nextNode);
138
141
  return identities.get(node);
139
142
  };
140
- const describe = (store, ancestors = /* @__PURE__ */ new Set()) => {
143
+ const describe = (store, root, ancestors = /* @__PURE__ */ new Set()) => {
141
144
  if (ancestors.has(store)) throw new Error("Inspector snapshots require an acyclic Bag");
142
145
  const next = /* @__PURE__ */ new Set([...ancestors, store]);
143
146
  return store.getNodes().map((node) => {
@@ -148,15 +151,16 @@
148
151
  label: node.label,
149
152
  revision: versions.get(node) ?? 0,
150
153
  value: branch ? null : cell(value),
151
- children: branch ? describe(value, next) : null,
154
+ children: branch ? describe(value, root, next) : null,
152
155
  readonly: !!node.resolver,
156
+ parameterEnums: root === "source" ? readParameterEnums(node) : {},
153
157
  attrs: Object.entries(node.getAttr()).filter(([name]) => name !== "_meta").map(([name, value2]) => [name, cell(value2)])
154
158
  };
155
159
  });
156
160
  };
157
161
  const snapshot = () => ({
158
- data: describe(bag("data")),
159
- source: describe(bag("source")),
162
+ data: describe(bag("data"), "data"),
163
+ source: describe(bag("source"), "source"),
160
164
  breakpoints: [...breakpoints.values()].map(({ test, ...record }) => record)
161
165
  });
162
166
  const send = (data) => {
@@ -376,6 +380,7 @@
376
380
  id: row.id,
377
381
  revision: row.revision,
378
382
  branch,
383
+ parameterEnums: row.parameterEnums,
379
384
  readonly: row.readonly || !!row.value?.readonly,
380
385
  readonlyAttrs: new Set(row.attrs.filter(([, descriptor]) => descriptor.readonly).map(([name]) => name)),
381
386
  valueWire: JSON.stringify(row.value),
@@ -405,7 +410,7 @@
405
410
  this.#notify();
406
411
  }
407
412
  };
408
- var gramlot_tools_inspector_default = ":host { all: initial; color-scheme: light; font: 12px/1.4 system-ui, sans-serif; color: #38414b; }\n* { box-sizing: border-box; }\nbutton, input, select { font: inherit; color: inherit; }\nbutton { cursor: pointer; }\nbutton:focus-visible, input:focus-visible, select:focus-visible { outline: 1px solid #3574cb; outline-offset: -1px; }\n.tree { padding: 7px 3px; }\n.properties { background: white; }\n.properties-heading { font-size: 11px; display: flex; align-items: center; justify-content: space-between; height: 29px; padding: 0 8px; background: #f1f3f5; color: #6d7989; border-bottom: 1px solid #d1d7df; }\n.properties-heading button { background: white; border: 1px solid #c5cdda; border-radius: 2px; width: 23px; height: 23px; padding: 0; font-size: 18px; line-height: 20px; }\nfieldset { border: 0; margin: 0; padding: 0; min-width: 0; }\n.property-row { display: grid; grid-template-columns: minmax(95px, 30%) minmax(0, 1fr); min-height: 20px; border-bottom: 1px solid #d1d7df; font-size: 11px; }\n.property-name { display: flex; align-items: center; justify-content: flex-end; background: #888; color: white; font-weight: 700; padding: 1px 6px; border-right: 1px solid #d1d7df; overflow-wrap: anywhere; text-align: right; }\n.property-value { display: flex; align-items: center; min-width: 0; }\n.property-row input { border: 0; border-radius: 0; min-width: 0; width: 100%; height: 19px; padding: 1px 5px; background: transparent; }\n.property-name input { color: white; text-align: right; padding: 0; }\n.property-value input { flex: 1; }\n.property-value input[type=checkbox] { flex: none; width: 14px; height: 14px; margin: 2px 6px; }\n.property-value select { max-width: 82px; height: 20px; padding: 0; border: 0; border-left: 1px solid #d1d7df; background: #f1f3f5; font-size: 10px; }\n.remove { margin-left: auto; flex: none; width: 22px; height: 20px; padding: 3px; border: 0; background: transparent; color: #7c8797; opacity: 0; }\n.remove svg { width: 13px; height: 13px; }\n.property-row:hover .remove, .property-row:focus-within .remove { opacity: 1; }\n.remove:hover { color: #b82323; background: #fbe9e9; }\n:disabled { cursor: default; opacity: .65; }\n.path { flex: none; padding: 5px 9px; border-top: 1px solid #c9cfd6; background: #f5f7f9; color: #697687; font-size: 11px; min-height: 27px; overflow-wrap: anywhere; }\n.error, .edit-status, .breakpoint-status, .breakpoint-line { font-size: 11px; margin: 0; padding: 3px 8px; overflow-wrap: anywhere; }\n.error, .edit-status, .breakpoint-status { color: #a12121; }\n.breakpoint-line { background: #fff2ed; color: #854127; border-bottom: 1px solid #d1d7df; }\n.error:empty, .edit-status:empty, .breakpoint-status:empty, .breakpoint-line:empty { display: none; }\n.breakpoint-dialog { width: min(340px, 90vw); color: #38414b; border: 1px solid #bbc3cf; border-radius: 4px; padding: 12px; box-shadow: 0 8px 28px #0003; font: 12px/1.4 system-ui, sans-serif; }\n.breakpoint-dialog::backdrop { background: #0002; }\n.breakpoint-dialog h2 { font-size: 13px; margin: 0 0 10px; overflow-wrap: anywhere; }\n.breakpoint-dialog select, .breakpoint-dialog input { width: 100%; border: 1px solid #bbc3cf; padding: 4px; margin: 0 0 7px; background: white; }\n.dialog-actions { display: flex; gap: 6px; justify-content: flex-end; margin-top: 7px; }\n.dialog-actions button { padding: 3px 10px; border: 1px solid #bbc3cf; border-radius: 3px; background: #f1f3f5; }\n.heading-label { flex: 1; }\n.properties-heading .breakpoint-count { width: auto; padding: 0 5px; margin-right: 5px; font-size: 11px; color: #b04a35; }\n.breakpoint-entry { display: flex; align-items: center; gap: 6px; padding: 4px 0; border-bottom: 1px solid #d1d7df; }\n.breakpoint-entry span { flex: 1; overflow-wrap: anywhere; }\n.breakpoint-entry button { background: transparent; border: 0; font-size: 17px; }\n[hidden] { display: none !important; }\n.targetbar { flex: none; height: 28px; padding: 2px 6px; background: #edf2fa; border-bottom: 1px solid #dadce0; }\n.targetbar select { width: 100%; height: 23px; border: 0; background: transparent; font-size: 11px; }\n.styles-panel { flex: 1; min-height: 0; overflow: auto; background: #fff; font-size: 11px; }\n.styles-toolbar { position: sticky; top: 0; z-index: 1; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; padding: 6px 8px; background: #f1f3f5; border-bottom: 1px solid #d1d7df; }\n.styles-toolbar span { flex: 1; font-weight: 600; }\n.styles-toolbar button, .styles-toolbar a { padding: 3px 7px; border: 1px solid #c5cdda; border-radius: 3px; background: white; }\n.styles-toolbar a { color: inherit; text-decoration: none; }\n.styles-toolbar a[aria-disabled=true] { cursor: default; opacity: .65; }\n.styles-toolbar a:focus-visible { outline: 1px solid #3574cb; outline-offset: -1px; }\n.styles-help, .styles-empty, .styles-status { margin: 0; padding: 7px 9px; color: #697687; }\n.styles-status { color: #a12121; }\n.styles-status:empty { display: none; }\n.styles-group h3 { margin: 0; padding: 6px 9px; font-size: 11px; background: #edf2fa; border-block: 1px solid #d1d7df; }\n.style-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 25px 23px; align-items: center; gap: 8px; min-width: 0; padding: 3px 9px; border-bottom: 1px solid #e8ebef; }\n.style-row label { min-width: 0; font: 11px/1.4 ui-monospace, monospace; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.style-row input { min-width: 0; width: 100%; height: 23px; padding: 2px 5px; border: 1px solid #c5cdda; border-radius: 3px; background: white; }\n.style-row input[type=color] { width: 25px; padding: 1px; cursor: pointer; }\n.style-row button { grid-column: 4; width: 23px; height: 23px; padding: 0; border: 1px solid #c5cdda; border-radius: 3px; background: #f5f7f9; font-size: 15px; }\n\n:host([embedded]) { display: block; height: 100%; min-height: 0; }\n:host([embedded]) > div { height: 100%; }\n.embedded-panel { display: flex; flex-direction: column; height: 100%; min-height: 0; overflow: hidden; }\n";
413
+ var gramlot_tools_inspector_default = ":host { all: initial; color-scheme: light; font: 12px/1.4 system-ui, sans-serif; color: #38414b; }\n* { box-sizing: border-box; }\nbutton, input, select { font: inherit; color: inherit; }\nbutton { cursor: pointer; }\nbutton:focus-visible, input:focus-visible, select:focus-visible { outline: 1px solid #3574cb; outline-offset: -1px; }\n.tree { padding: 7px 3px; }\n.properties { background: white; }\n.properties-heading { font-size: 11px; display: flex; align-items: center; justify-content: space-between; height: 29px; padding: 0 8px; background: #f1f3f5; color: #6d7989; border-bottom: 1px solid #d1d7df; }\n.properties-heading button { background: white; border: 1px solid #c5cdda; border-radius: 2px; width: 23px; height: 23px; padding: 0; font-size: 18px; line-height: 20px; }\nfieldset { border: 0; margin: 0; padding: 0; min-width: 0; }\n.property-row { display: grid; grid-template-columns: minmax(95px, 30%) minmax(0, 1fr); min-height: 20px; border-bottom: 1px solid #d1d7df; font-size: 11px; }\n.property-name { display: flex; align-items: center; justify-content: flex-end; background: #888; color: white; font-weight: 700; padding: 1px 6px; border-right: 1px solid #d1d7df; overflow-wrap: anywhere; text-align: right; }\n.property-value { display: flex; align-items: center; min-width: 0; }\n.property-row input { border: 0; border-radius: 0; min-width: 0; width: 100%; height: 19px; padding: 1px 5px; background: transparent; }\n.property-name input { color: white; text-align: right; padding: 0; }\n.property-value input { flex: 1; }\n.property-value input[type=checkbox] { flex: none; width: 14px; height: 14px; margin: 2px 6px; }\n.property-value select { max-width: 82px; height: 20px; padding: 0; border: 0; border-left: 1px solid #d1d7df; background: #f1f3f5; font-size: 10px; }\n.remove { display: inline-flex; align-items: center; justify-content: center; margin-left: auto; flex: none; width: 22px; height: 20px; padding: 3px; border: 0; background: transparent; color: #7c8797; opacity: 0; }\n.remove svg { width: 13px; height: 13px; }\n.property-row:hover .remove, .property-row:focus-within .remove { opacity: 1; }\n.remove:hover { color: #b82323; background: #fbe9e9; }\n:disabled { cursor: default; opacity: .65; }\n.path { flex: none; padding: 5px 9px; border-top: 1px solid #c9cfd6; background: #f5f7f9; color: #697687; font-size: 11px; min-height: 27px; overflow-wrap: anywhere; }\n.error, .edit-status, .breakpoint-status, .breakpoint-line { font-size: 11px; margin: 0; padding: 3px 8px; overflow-wrap: anywhere; }\n.error, .edit-status, .breakpoint-status { color: #a12121; }\n.breakpoint-line { background: #fff2ed; color: #854127; border-bottom: 1px solid #d1d7df; }\n.error:empty, .edit-status:empty, .breakpoint-status:empty, .breakpoint-line:empty { display: none; }\n.breakpoint-dialog { width: min(340px, 90vw); color: #38414b; border: 1px solid #bbc3cf; border-radius: 4px; padding: 12px; box-shadow: 0 8px 28px #0003; font: 12px/1.4 system-ui, sans-serif; }\n.breakpoint-dialog::backdrop { background: #0002; }\n.breakpoint-dialog h2 { font-size: 13px; margin: 0 0 10px; overflow-wrap: anywhere; }\n.breakpoint-dialog select, .breakpoint-dialog input { width: 100%; border: 1px solid #bbc3cf; padding: 4px; margin: 0 0 7px; background: white; }\n.dialog-actions { display: flex; gap: 6px; justify-content: flex-end; margin-top: 7px; }\n.dialog-actions button { padding: 3px 10px; border: 1px solid #bbc3cf; border-radius: 3px; background: #f1f3f5; }\n.heading-label { flex: 1; }\n.properties-heading .breakpoint-count { width: auto; padding: 0 5px; margin-right: 5px; font-size: 11px; color: #b04a35; }\n.breakpoint-entry { display: flex; align-items: center; gap: 6px; padding: 4px 0; border-bottom: 1px solid #d1d7df; }\n.breakpoint-entry span { flex: 1; overflow-wrap: anywhere; }\n.breakpoint-entry button { background: transparent; border: 0; font-size: 17px; }\n[hidden] { display: none !important; }\n.targetbar { flex: none; height: 28px; padding: 2px 6px; background: #edf2fa; border-bottom: 1px solid #dadce0; }\n.targetbar select { width: 100%; height: 23px; border: 0; background: transparent; font-size: 11px; }\n.styles-panel { flex: 1; min-height: 0; overflow: auto; background: #fff; font-size: 11px; }\n.styles-toolbar { position: sticky; top: 0; z-index: 1; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; padding: 6px 8px; background: #f1f3f5; border-bottom: 1px solid #d1d7df; }\n.styles-toolbar span { flex: 1; font-weight: 600; }\n.styles-toolbar button, .styles-toolbar a { padding: 3px 7px; border: 1px solid #c5cdda; border-radius: 3px; background: white; }\n.styles-toolbar a { color: inherit; text-decoration: none; }\n.styles-toolbar a[aria-disabled=true] { cursor: default; opacity: .65; }\n.styles-toolbar a:focus-visible { outline: 1px solid #3574cb; outline-offset: -1px; }\n.styles-help, .styles-empty, .styles-status { margin: 0; padding: 7px 9px; color: #697687; }\n.styles-status { color: #a12121; }\n.styles-status:empty { display: none; }\n.styles-group h3 { margin: 0; padding: 6px 9px; font-size: 11px; background: #edf2fa; border-block: 1px solid #d1d7df; }\n.style-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 25px 23px; align-items: center; gap: 8px; min-width: 0; padding: 3px 9px; border-bottom: 1px solid #e8ebef; }\n.style-row label { min-width: 0; font: 11px/1.4 ui-monospace, monospace; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.style-row input { min-width: 0; width: 100%; height: 23px; padding: 2px 5px; border: 1px solid #c5cdda; border-radius: 3px; background: white; }\n.style-row input[type=color] { width: 25px; padding: 1px; cursor: pointer; }\n.style-row button { grid-column: 4; width: 23px; height: 23px; padding: 0; border: 1px solid #c5cdda; border-radius: 3px; background: #f5f7f9; font-size: 15px; }\n\n:host([embedded]) { display: block; height: 100%; min-height: 0; }\n:host([embedded]) > div { height: 100%; }\n.embedded-panel { display: flex; flex-direction: column; height: 100%; min-height: 0; overflow: hidden; }\n\n.property-value select.enum-value { flex: 1; min-width: 0; max-width: none; width: 100%; border: 0; background: white; font: inherit; padding: 1px 5px; }\n";
409
414
  var gramlot_poc_tree_default = "/* Copyright 2025-2026 Softwell S.r.l. - SPDX-License-Identifier: Apache-2.0\n * Inspector subset of the DevTools storeTree stylesheet and inspector.css variables. */\n:host { display:block; font:11px/18px -apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif; color:#38414b; }\n:host([hidden]) { display:none; }\nul { list-style:none; margin:0; padding-left:17px; }\n.tree-root { padding-left:16px; }\n.tree-root > ul { padding-left:2px; }\nsummary, .leaf { position:relative; }\nli { line-height:18px; }\nsummary { display:flex; align-items:center; gap:7px; padding:0 5px; cursor:pointer; user-select:none; list-style:none; }\nsummary::-webkit-details-marker { display:none; }\nsummary::before { content:''; width:5px; height:5px; border-right:1.5px solid #78818a; border-bottom:1.5px solid #78818a; transform:rotate(-45deg); flex:none; margin:0 3px; }\ndetails[open] > summary::before { transform:rotate(45deg); }\n.leaf { display:flex; align-items:center; gap:7px; padding:0 5px 0 23px; cursor:pointer; }\nsummary:hover,.leaf:hover { background:#f0f3f6; }\n.selected,.selected:hover { background:transparent; color:#315dbd; font-weight:700; border-radius:2px; }\n.caption { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n/* Reserve a left gutter; showing an action must not shift the node label. */\n.actions { position:absolute; left:-14px; top:0; display:inline-flex; opacity:0; pointer-events:none; }\nsummary:hover > .actions,.leaf:hover > .actions,summary:focus-visible > .actions,.leaf:focus-visible > .actions,\n.actions:has(button:focus-visible),.actions:has(button.active) { opacity:1; pointer-events:auto; }\n.actions button { border:0; background:transparent; color:#80868b; font:inherit; font-size:11px; line-height:18px; width:14px; height:18px; padding:0; cursor:pointer; border-radius:3px; }\n.actions button:hover { background:#e1e5ed; }\n.actions button[data-action=breakpoint] { font-size:0; }\n.actions button[data-action=breakpoint]::before { content:''; display:inline-block; box-sizing:border-box; width:8px; height:8px; border:1.5px solid currentColor; border-radius:50%; vertical-align:middle; }\n.actions button.active { color:#b3261e; }\n.actions button.active.conditional { color:#f9ab00; }\n.actions button.active[data-action=breakpoint]::before { background:currentColor; }\n.actions button:focus-visible,summary:focus-visible,.leaf:focus-visible { outline:2px solid #356f9f; outline-offset:-2px; }\n";
410
415
  var sequence = 0;
411
416
  var GramlotPocTree = class extends HTMLElement {
@@ -855,6 +860,10 @@
855
860
  ui.data.setItem("editor.dirty", true);
856
861
  ui.data.setItem("editor.status", "Unsaved changes");
857
862
  }
863
+ enumChanged(node) {
864
+ this.editChanged(node);
865
+ inspector.#applyEdit();
866
+ }
858
867
  typeChanged(node) {
859
868
  const row = ui.data.getItem(`editor.rows.${node.getAttr("data-row")}`);
860
869
  row.setItem("inputType", inspector.#inputType(row.getItem("type")));
@@ -1041,7 +1050,7 @@
1041
1050
  const targetbar = palette.div({ node_label: "targetbar", class: "targetbar", hidden: "^singleTarget" });
1042
1051
  targetbar.select({ node_label: "targets", value: "^targetId", disabled: "^busy", "aria-label": "Inspected page", connect_onchange: "inspector.selectTarget" });
1043
1052
  const toolbar = palette.webcomponent({ code: "gramlot-poc-tabs", node_label: "tabs", role: "tablist", "aria-label": "Inspected root" });
1044
- for (const name of ["Data", "Source", "Styles"]) toolbar.button(name, {
1053
+ for (const name of ["Data", "Source", "Styles"]) toolbar.html_button(name, {
1045
1054
  node_label: name.toLowerCase(),
1046
1055
  type: "button",
1047
1056
  role: "tab",
@@ -1063,7 +1072,7 @@
1063
1072
  const properties = content.section({ node_label: "properties", slot: "bottom", class: "properties", "aria-label": "Selected node properties" });
1064
1073
  const heading = properties.div({ class: "properties-heading" });
1065
1074
  heading.span("Properties", { class: "heading-label" });
1066
- heading.button("^breakpointCount", {
1075
+ heading.html_button("^breakpointCount", {
1067
1076
  type: "button",
1068
1077
  class: "breakpoint-count",
1069
1078
  hidden: "^noBreakpoints",
@@ -1071,7 +1080,7 @@
1071
1080
  title: "Active breakpoints",
1072
1081
  connect_onclick: "inspector.showBreakpoints"
1073
1082
  });
1074
- heading.button("+", {
1083
+ heading.html_button("+", {
1075
1084
  type: "button",
1076
1085
  "aria-label": "Add attribute",
1077
1086
  title: "Add attribute",
@@ -1087,8 +1096,8 @@
1087
1096
  const styles = palette.section({ node_label: "styles", class: "styles-panel", hidden: "^treeActive", "aria-label": "CSS variables" });
1088
1097
  const stylebar = styles.div({ class: "styles-toolbar" });
1089
1098
  stylebar.span("Document variables");
1090
- stylebar.button("Refresh", { type: "button", disabled: "^styles.busy", connect_onclick: "inspector.refreshStyles" });
1091
- stylebar.button("Reset all", { type: "button", disabled: "^styles.noChanges", connect_onclick: "inspector.resetStyles" });
1099
+ stylebar.html_button("Refresh", { type: "button", disabled: "^styles.busy", connect_onclick: "inspector.refreshStyles" });
1100
+ stylebar.html_button("Reset all", { type: "button", disabled: "^styles.noChanges", connect_onclick: "inspector.resetStyles" });
1092
1101
  stylebar.a("Download CSS", { href: "^styles.downloadUrl", download: "theme-overrides.css", "aria-disabled": "^styles.noDownload" });
1093
1102
  styles.p("Temporary preview \xB7 Enter or leave a field to apply. Closing the connection clears previews.", { class: "styles-help" });
1094
1103
  styles.p("^styles.status", { role: "status", class: "styles-status" });
@@ -1104,12 +1113,12 @@
1104
1113
  breakpoint.input({ value: "^editor.condition", live: true, connect_oninput: "inspector.breakpointChanged", "aria-label": "Breakpoint condition", placeholder: "Condition (optional)" });
1105
1114
  breakpoint.p("^breakpointStatus", { role: "status", class: "breakpoint-status" });
1106
1115
  const actions = breakpoint.div({ class: "dialog-actions" });
1107
- actions.button("Cancel", { type: "button", connect_onclick: "inspector.closeBreakpoint" });
1108
- actions.button("Save", { type: "button", connect_onclick: "inspector.setBreakpoint" });
1116
+ actions.html_button("Cancel", { type: "button", connect_onclick: "inspector.closeBreakpoint" });
1117
+ actions.html_button("Save", { type: "button", connect_onclick: "inspector.setBreakpoint" });
1109
1118
  const list = palette.dialog({ node_label: "breakpoints", "aria-label": "Active breakpoints", class: "breakpoint-dialog" });
1110
1119
  list.h2("Active breakpoints");
1111
1120
  list.div({ node_label: "entries" });
1112
- list.div({ class: "dialog-actions" }).button("Close", { type: "button", connect_onclick: "inspector.closeBreakpoints" });
1121
+ list.div({ class: "dialog-actions" }).html_button("Close", { type: "button", connect_onclick: "inspector.closeBreakpoints" });
1113
1122
  ui.src.startSource(builder.source);
1114
1123
  for (const name of ["data", "source"]) this.#trees[name] = ui.dom.getDomNode(ui.src.source.getNode(`main.palette.content.tree.${name}`));
1115
1124
  this.#renderTargets();
@@ -1326,7 +1335,7 @@ ${declarations}
1326
1335
  "data-field": "color",
1327
1336
  connect_onchange: "inspector.setStyle"
1328
1337
  });
1329
- row.button("\u21B6", {
1338
+ row.html_button("\u21B6", {
1330
1339
  type: "button",
1331
1340
  "aria-label": `Reset ${record.name}`,
1332
1341
  title: "Reset variable",
@@ -1396,6 +1405,7 @@ ${declarations}
1396
1405
  this.#snapshot = entry ? {
1397
1406
  node: entry.node,
1398
1407
  value: entry.node.getValue(true),
1408
+ parameterEnums: ui.data.getItem("root") !== "source" ? {} : this.#connection ? this.#connection.nodeInfo(entry.node).parameterEnums : readParameterEnums(entry.node),
1399
1409
  attrs: { ...entry.node.getAttr() },
1400
1410
  resolver: entry.node.resolver,
1401
1411
  revision: this.#connection?.nodeInfo(entry.node)?.revision
@@ -1433,7 +1443,20 @@ ${declarations}
1433
1443
  if (fresh) label.input({ value: "^.name", live: true, "aria-label": "New attribute name", "data-row": row.label, connect_oninput: "inspector.editChanged" });
1434
1444
  else label.span(name);
1435
1445
  const cell = line.div({ class: "property-value" });
1436
- cell.input({
1446
+ const choices = !primary && this.#snapshot.parameterEnums[name];
1447
+ const value = data.getItem("text");
1448
+ if (choices && choices.includes(value)) {
1449
+ const select = cell.select({
1450
+ value: "^.text",
1451
+ class: "enum-value",
1452
+ disabled: locked,
1453
+ "aria-label": `${name} value`,
1454
+ "data-row": row.label,
1455
+ connect_onchange: "inspector.enumChanged",
1456
+ connect_onkeydown: "inspector.editKey"
1457
+ });
1458
+ for (const choice of choices) select.option(choice, { value: choice });
1459
+ } else cell.input({
1437
1460
  value: "^.text",
1438
1461
  type: "^.inputType",
1439
1462
  live: true,
@@ -1447,10 +1470,10 @@ ${declarations}
1447
1470
  });
1448
1471
  if (fresh) {
1449
1472
  const type = cell.select({ value: "^.type", "aria-label": "New attribute type", "data-row": row.label, connect_onchange: "inspector.typeChanged" });
1450
- for (const value of editorTypes) type.option(value, { value });
1473
+ for (const value2 of editorTypes) type.option(value2, { value: value2 });
1451
1474
  }
1452
1475
  if (!primary) {
1453
- const button = cell.button({
1476
+ const button = cell.html_button({
1454
1477
  type: "button",
1455
1478
  disabled: locked,
1456
1479
  "aria-label": `Remove ${name || "new attribute"}`,
@@ -1486,6 +1509,7 @@ ${declarations}
1486
1509
  this.#loadEditor(this.#selected());
1487
1510
  } else {
1488
1511
  this.#snapshot = {
1512
+ ...this.#snapshot,
1489
1513
  node: target,
1490
1514
  value: target.getValue(true),
1491
1515
  attrs: { ...target.getAttr() },
@@ -1645,7 +1669,7 @@ ${declarations}
1645
1669
  const config = node.value;
1646
1670
  const row = builder.root.div({ class: "breakpoint-entry" });
1647
1671
  row.span(`${config.getItem("root")}: ${config.getItem("path")} \xB7 ${config.getItem("mode")} \xB7 ${config.getItem("hits")} hits`);
1648
- row.button("\xD7", {
1672
+ row.html_button("\xD7", {
1649
1673
  type: "button",
1650
1674
  "aria-label": `Remove breakpoint ${config.getItem("root")}: ${config.getItem("path")}`,
1651
1675
  "data-breakpoint": node.label,