@jxsuite/studio 0.25.1 → 0.25.3

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.
package/dist/studio.js CHANGED
@@ -270207,6 +270207,161 @@ function renderFieldRow({
270207
270207
  `;
270208
270208
  }
270209
270209
 
270210
+ // src/ui/field-input.ts
270211
+ init_lit_html();
270212
+ init_live();
270213
+
270214
+ // ../../node_modules/.bun/lit-html@3.3.3/node_modules/lit-html/development/directives/keyed.js
270215
+ init_lit_html();
270216
+ init_directive();
270217
+ init_directive_helpers();
270218
+
270219
+ class Keyed extends Directive {
270220
+ constructor() {
270221
+ super(...arguments);
270222
+ this.key = nothing;
270223
+ }
270224
+ render(k, v) {
270225
+ this.key = k;
270226
+ return v;
270227
+ }
270228
+ update(part, [k, v]) {
270229
+ if (k !== this.key) {
270230
+ setCommittedValue(part);
270231
+ this.key = k;
270232
+ }
270233
+ return v;
270234
+ }
270235
+ }
270236
+ var keyed = directive(Keyed);
270237
+
270238
+ // src/ui/field-input.ts
270239
+ var DEFAULT_DEBOUNCE_MS = 350;
270240
+ var _drafts = new Map;
270241
+ function getFieldValue(key, committed) {
270242
+ const d2 = _drafts.get(key);
270243
+ return d2 ? d2.value : committed;
270244
+ }
270245
+ function setDraft(key, value2) {
270246
+ const d2 = _drafts.get(key);
270247
+ if (d2)
270248
+ d2.value = value2;
270249
+ else
270250
+ _drafts.set(key, { value: value2 });
270251
+ }
270252
+ function scheduleDraftCommit(key, ms, commit) {
270253
+ const d2 = _drafts.get(key);
270254
+ if (!d2)
270255
+ return;
270256
+ if (d2.timer)
270257
+ clearTimeout(d2.timer);
270258
+ d2.timer = setTimeout(() => {
270259
+ const cur = _drafts.get(key);
270260
+ if (!cur)
270261
+ return;
270262
+ delete cur.timer;
270263
+ commit(cur.value);
270264
+ }, ms);
270265
+ }
270266
+ function commitField(key, commit) {
270267
+ const d2 = _drafts.get(key);
270268
+ if (!d2)
270269
+ return;
270270
+ if (d2.timer)
270271
+ clearTimeout(d2.timer);
270272
+ const value2 = d2.value;
270273
+ _drafts.delete(key);
270274
+ commit(value2);
270275
+ }
270276
+ function makeHandlers(key, ms, commit, commitMode = "live") {
270277
+ return {
270278
+ onInput: (e) => {
270279
+ const v = e.target.value;
270280
+ setDraft(key, v);
270281
+ if (commitMode === "live")
270282
+ scheduleDraftCommit(key, ms, commit);
270283
+ },
270284
+ onCommit: (e) => {
270285
+ const v = e.target.value;
270286
+ setDraft(key, v);
270287
+ commitField(key, commit);
270288
+ },
270289
+ onKeydown: (e, multiline) => {
270290
+ if (e.key === "Enter" && !multiline) {
270291
+ commitField(key, commit);
270292
+ }
270293
+ }
270294
+ };
270295
+ }
270296
+ function spTextField(key, value2, commit, opts = {}) {
270297
+ const ms = opts.debounceMs ?? DEFAULT_DEBOUNCE_MS;
270298
+ const { onInput, onCommit, onKeydown: onKeydown2 } = makeHandlers(key, ms, commit, opts.commitMode);
270299
+ return keyed(key, html3`
270300
+ <sp-textfield
270301
+ size=${opts.size ?? "s"}
270302
+ placeholder=${opts.placeholder ?? ""}
270303
+ ?disabled=${!!opts.disabled}
270304
+ style=${opts.style ?? ""}
270305
+ .value=${live(getFieldValue(key, value2))}
270306
+ @input=${onInput}
270307
+ @change=${onCommit}
270308
+ @keydown=${(e) => onKeydown2(e, false)}
270309
+ ></sp-textfield>
270310
+ `);
270311
+ }
270312
+ function spTextArea(key, value2, commit, opts = {}) {
270313
+ const ms = opts.debounceMs ?? DEFAULT_DEBOUNCE_MS;
270314
+ const { onInput, onCommit } = makeHandlers(key, ms, commit, opts.commitMode);
270315
+ return keyed(key, html3`
270316
+ <sp-textfield
270317
+ multiline
270318
+ size=${opts.size ?? "s"}
270319
+ placeholder=${opts.placeholder ?? ""}
270320
+ ?disabled=${!!opts.disabled}
270321
+ style=${opts.style ?? ""}
270322
+ .value=${live(getFieldValue(key, value2))}
270323
+ @input=${onInput}
270324
+ @change=${onCommit}
270325
+ ></sp-textfield>
270326
+ `);
270327
+ }
270328
+ function rawTextArea(key, value2, commit, opts = {}) {
270329
+ const ms = opts.debounceMs ?? DEFAULT_DEBOUNCE_MS;
270330
+ const { onInput, onCommit } = makeHandlers(key, ms, commit, opts.commitMode);
270331
+ const style2 = [
270332
+ `min-height:${opts.minHeight ?? "40px"}`,
270333
+ opts.mono ? "font-family:'SF Mono','Fira Code','Consolas',monospace;font-size:11px" : "",
270334
+ opts.style ?? ""
270335
+ ].filter(Boolean).join(";");
270336
+ return keyed(key, html3`
270337
+ <textarea
270338
+ class="field-input"
270339
+ style=${style2}
270340
+ placeholder=${opts.placeholder ?? ""}
270341
+ ?disabled=${!!opts.disabled}
270342
+ .value=${live(getFieldValue(key, value2))}
270343
+ @input=${onInput}
270344
+ @change=${onCommit}
270345
+ ></textarea>
270346
+ `);
270347
+ }
270348
+ function spNumberField(value2, commit, opts = {}) {
270349
+ return html3`
270350
+ <sp-number-field
270351
+ size=${opts.size ?? "s"}
270352
+ ?hide-stepper=${opts.hideStepper ?? true}
270353
+ ?disabled=${!!opts.disabled}
270354
+ style=${opts.style ?? ""}
270355
+ .value=${live(value2 !== undefined ? Number(value2) : undefined)}
270356
+ @change=${(e) => {
270357
+ const raw = e.target.value;
270358
+ const n2 = Number(raw);
270359
+ commit(raw === "" || isNaN(n2) ? undefined : n2);
270360
+ }}
270361
+ ></sp-number-field>
270362
+ `;
270363
+ }
270364
+
270210
270365
  // src/ui/expression-editor.ts
270211
270366
  init_lit_html();
270212
270367
  init_live();
@@ -270848,17 +271003,10 @@ function signalFieldRow(label4, value2, onChange) {
270848
271003
  prop: label4,
270849
271004
  label: label4,
270850
271005
  hasValue: false,
270851
- widget: html3`
270852
- <sp-textfield
270853
- size="s"
270854
- .value=${value2}
270855
- @change=${(e) => {
270856
- const v = e.target.value;
271006
+ widget: spTextField(`sig:${label4}`, value2, (v) => {
270857
271007
  if (v !== value2)
270858
271008
  onChange(v);
270859
- }}
270860
- ></sp-textfield>
270861
- `
271009
+ }, { commitMode: "blur" })
270862
271010
  });
270863
271011
  }
270864
271012
  function normParam(p) {
@@ -271018,28 +271166,15 @@ function renderSignalEditorTemplate(S, name, def3, ctx) {
271018
271166
  });
271019
271167
  };
271020
271168
  const textareaRow = (label4, value2, onChange, opts = {}) => {
271021
- let debounce;
271022
271169
  return renderFieldRow({
271023
271170
  prop: label4,
271024
271171
  label: label4,
271025
271172
  hasValue: false,
271026
- widget: html3`
271027
- <textarea
271028
- class="field-input"
271029
- style=${styleMap({
271030
- minHeight: opts.minHeight || "40px",
271031
- ...opts.mono && {
271032
- fontFamily: "'SF Mono','Fira Code','Consolas',monospace",
271033
- fontSize: "11px"
271034
- }
271035
- })}
271036
- .value=${value2}
271037
- @input=${(e) => {
271038
- clearTimeout(debounce);
271039
- debounce = setTimeout(() => onChange(e.target.value), 500);
271040
- }}
271041
- ></textarea>
271042
- `
271173
+ widget: rawTextArea(`sig:${label4}`, value2, onChange, {
271174
+ debounceMs: 500,
271175
+ ...opts.minHeight != null && { minHeight: opts.minHeight },
271176
+ ...opts.mono != null && { mono: opts.mono }
271177
+ })
271043
271178
  });
271044
271179
  };
271045
271180
  const nameField = signalFieldRow("Name", name, (v) => {
@@ -271819,7 +271954,7 @@ function _objectWithoutProperties(e, t) {
271819
271954
  return i2;
271820
271955
  }
271821
271956
 
271822
- // ../../node_modules/.bun/@atlaskit+pragmatic-drag-and-drop-hitbox@1.1.0/node_modules/@atlaskit/pragmatic-drag-and-drop-hitbox/dist/esm/internal/memoize.js
271957
+ // ../../node_modules/.bun/@atlaskit+pragmatic-drag-and-drop-hitbox@1.2.0/node_modules/@atlaskit/pragmatic-drag-and-drop-hitbox/dist/esm/internal/memoize.js
271823
271958
  function isShallowEqual(a, b) {
271824
271959
  var aKeys = Object.keys(a);
271825
271960
  var bKeys = Object.keys(b);
@@ -271844,7 +271979,7 @@ function stable() {
271844
271979
  };
271845
271980
  }
271846
271981
 
271847
- // ../../node_modules/.bun/@atlaskit+pragmatic-drag-and-drop-hitbox@1.1.0/node_modules/@atlaskit/pragmatic-drag-and-drop-hitbox/dist/esm/tree-item.js
271982
+ // ../../node_modules/.bun/@atlaskit+pragmatic-drag-and-drop-hitbox@1.2.0/node_modules/@atlaskit/pragmatic-drag-and-drop-hitbox/dist/esm/tree-item.js
271848
271983
  var _excluded = ["block"];
271849
271984
  function ownKeys4(e, r) {
271850
271985
  var t = Object.keys(e);
@@ -274794,6 +274929,18 @@ var _prevStylebookCustomizedOnly = false;
274794
274929
  function initCanvasRender(ctx) {
274795
274930
  _ctx11 = ctx;
274796
274931
  }
274932
+ function sourceLang(tab) {
274933
+ if (tab.doc.sourceFormat === "md")
274934
+ return "markdown";
274935
+ return (tab.documentPath || "").endsWith(".js") ? "javascript" : "json";
274936
+ }
274937
+ function sourceContent(tab, lang) {
274938
+ if (lang === "markdown")
274939
+ return serializeDocument(tab);
274940
+ if (lang === "javascript")
274941
+ return tab.doc.document?.toString?.() || "";
274942
+ return JSON.stringify(tab.doc.document, null, 2);
274943
+ }
274797
274944
  function renderCanvas() {
274798
274945
  const tab = activeTab.value;
274799
274946
  if (!tab) {
@@ -274822,13 +274969,11 @@ function renderCanvas() {
274822
274969
  view.functionEditor = null;
274823
274970
  }
274824
274971
  if (canvasMode === "source" && view.monacoEditor) {
274825
- const filePath = tab.documentPath || "document.json";
274826
- const isJs = filePath.endsWith(".js");
274827
- const newVal = isJs ? S.document?.toString?.() || "" : JSON.stringify(S.document, null, 2);
274828
- const currentVal = view.monacoEditor.getValue();
274829
- if (currentVal !== newVal) {
274830
- view.monacoEditor._ignoreNextChange = true;
274831
- view.monacoEditor.setValue(newVal);
274972
+ const editor2 = view.monacoEditor;
274973
+ const newVal = sourceContent(tab, sourceLang(tab));
274974
+ if (!editor2.hasTextFocus() && editor2.getValue() !== newVal) {
274975
+ editor2._ignoreNextChange = true;
274976
+ editor2.setValue(newVal);
274832
274977
  }
274833
274978
  return;
274834
274979
  }
@@ -274907,8 +275052,8 @@ function renderCanvas() {
274907
275052
  ></div>
274908
275053
  </div>`, canvasWrap);
274909
275054
  const filePath = tab.documentPath || "document.json";
274910
- const lang = filePath.endsWith(".js") ? "javascript" : "json";
274911
- const content3 = lang === "json" ? JSON.stringify(S.document, null, 2) : S.document?.toString?.() || "";
275055
+ const lang = sourceLang(tab);
275056
+ const content3 = sourceContent(tab, lang);
274912
275057
  const modelUri = Uri2.parse("file:///" + filePath);
274913
275058
  const model = editor.createModel(content3, lang, modelUri);
274914
275059
  view.monacoEditor = editor.create(editorContainer, {
@@ -274933,11 +275078,18 @@ function renderCanvas() {
274933
275078
  return;
274934
275079
  }
274935
275080
  clearTimeout(debounce);
274936
- debounce = setTimeout(() => {
275081
+ debounce = setTimeout(async () => {
274937
275082
  const tab2 = activeTab.value;
274938
275083
  if (!tab2)
274939
275084
  return;
274940
- if (lang === "json") {
275085
+ if (lang === "markdown") {
275086
+ try {
275087
+ const { document: document4, frontmatter: frontmatter2 } = await loadMarkdown(editor2.getValue());
275088
+ tab2.doc.document = document4;
275089
+ tab2.doc.content.frontmatter = frontmatter2;
275090
+ tab2.doc.dirty = true;
275091
+ } catch {}
275092
+ } else if (lang === "json") {
274941
275093
  try {
274942
275094
  tab2.doc.document = JSON.parse(editor2.getValue());
274943
275095
  tab2.doc.dirty = true;
@@ -276549,28 +276701,9 @@ function renderMetaFieldRow(field, head, applyMutation) {
276549
276701
  })
276550
276702
  });
276551
276703
  }
276552
- const widget = field.multiline ? html3`
276553
- <sp-textfield
276554
- size="s"
276555
- multiline
276556
- .value=${live(val)}
276557
- placeholder="${field.label}…"
276558
- @input=${debouncedStyleCommit(`head:${field.key}`, 400, (e) => {
276559
- const content3 = e.target.value?.trim() ?? "";
276560
- applyMutation((d2) => upsertMeta(d2, field.attr, field.key, content3));
276561
- })}
276562
- ></sp-textfield>
276563
- ` : html3`
276564
- <sp-textfield
276565
- size="s"
276566
- .value=${live(val)}
276567
- placeholder=${field.key === "viewport" ? "width=device-width, initial-scale=1" : `${field.label}…`}
276568
- @input=${debouncedStyleCommit(`head:${field.key}`, 400, (e) => {
276569
- const content3 = e.target.value?.trim() ?? "";
276570
- applyMutation((d2) => upsertMeta(d2, field.attr, field.key, content3));
276571
- })}
276572
- ></sp-textfield>
276573
- `;
276704
+ const commit = (v) => applyMutation((d2) => upsertMeta(d2, field.attr, field.key, v.trim()));
276705
+ const placeholder = field.key === "viewport" ? "width=device-width, initial-scale=1" : `${field.label}…`;
276706
+ const widget = field.multiline ? spTextArea(`head:${field.key}`, val, commit, { placeholder: `${field.label}…` }) : spTextField(`head:${field.key}`, val, commit, { placeholder });
276574
276707
  return renderFieldRow({
276575
276708
  prop: field.key,
276576
276709
  label: field.label,
@@ -276663,22 +276796,13 @@ function renderHeadTemplate({
276663
276796
  onClear: () => applyMutation((d2) => {
276664
276797
  delete d2.title;
276665
276798
  }),
276666
- widget: html3`
276667
- <sp-textfield
276668
- size="s"
276669
- .value=${live(title)}
276670
- placeholder="Page title…"
276671
- @input=${debouncedStyleCommit("head:title", 400, (e) => {
276672
- const val = e.target.value?.trim() ?? "";
276673
- applyMutation((d2) => {
276674
- if (val)
276675
- d2.title = val;
276676
- else
276677
- delete d2.title;
276678
- });
276679
- })}
276680
- ></sp-textfield>
276681
- `
276799
+ widget: spTextField("head:title", title, (v) => applyMutation((d2) => {
276800
+ const val = v.trim();
276801
+ if (val)
276802
+ d2.title = val;
276803
+ else
276804
+ delete d2.title;
276805
+ }), { placeholder: "Page title…" })
276682
276806
  })}
276683
276807
  ${PAGE_FIELDS.map((field) => renderMetaFieldRow(field, head, applyMutation))}
276684
276808
  ${renderFieldRow({
@@ -276874,17 +276998,10 @@ function renderFmField(field, entry, value2, requiredFields) {
276874
276998
  label: displayLabel,
276875
276999
  hasValue: hasVal,
276876
277000
  onClear,
276877
- widget: html3`
276878
- <sp-textfield
276879
- size="s"
276880
- placeholder="comma, separated"
276881
- .value=${live(display)}
276882
- @input=${debouncedStyleCommit(`fm:${field}`, 400, (e) => {
276883
- const arr = e.target.value ? e.target.value.split(",").map((s2) => s2.trim()).filter(Boolean) : undefined;
277001
+ widget: spTextField(`fm:${field}`, display, (v) => {
277002
+ const arr = v ? v.split(",").map((s2) => s2.trim()).filter(Boolean) : undefined;
276884
277003
  transactDoc(activeTab.value, (t) => mutateUpdateFrontmatter(t, field, arr));
276885
- })}
276886
- ></sp-textfield>
276887
- `
277004
+ }, { placeholder: "comma, separated" })
276888
277005
  });
276889
277006
  }
276890
277007
  if (Array.isArray(entry.enum)) {
@@ -276919,17 +277036,7 @@ function renderFmField(field, entry, value2, requiredFields) {
276919
277036
  label: displayLabel,
276920
277037
  hasValue: hasVal,
276921
277038
  onClear,
276922
- widget: html3`
276923
- <sp-number-field
276924
- size="s"
276925
- hide-stepper
276926
- .value=${live(value2 !== undefined ? Number(value2) : undefined)}
276927
- @change=${debouncedStyleCommit(`fm:${field}`, 400, (e) => {
276928
- const v = e.target.value;
276929
- transactDoc(activeTab.value, (t) => mutateUpdateFrontmatter(t, field, isNaN(Number(v)) ? undefined : Number(v)));
276930
- })}
276931
- ></sp-number-field>
276932
- `
277039
+ widget: spNumberField(value2 !== undefined ? Number(value2) : undefined, (n2) => transactDoc(activeTab.value, (t) => mutateUpdateFrontmatter(t, field, n2)))
276933
277040
  });
276934
277041
  }
276935
277042
  return renderFieldRow({
@@ -276937,16 +277044,7 @@ function renderFmField(field, entry, value2, requiredFields) {
276937
277044
  label: displayLabel,
276938
277045
  hasValue: hasVal,
276939
277046
  onClear,
276940
- widget: html3`
276941
- <sp-textfield
276942
- size="s"
276943
- placeholder=${entry.format === "date" ? "YYYY-MM-DD" : ""}
276944
- .value=${live(value2 || "")}
276945
- @input=${debouncedStyleCommit(`fm:${field}`, 400, (e) => {
276946
- transactDoc(activeTab.value, (t) => mutateUpdateFrontmatter(t, field, e.target.value || undefined));
276947
- })}
276948
- ></sp-textfield>
276949
- `
277047
+ widget: spTextField(`fm:${field}`, value2 || "", (v) => transactDoc(activeTab.value, (t) => mutateUpdateFrontmatter(t, field, v || undefined)), { placeholder: entry.format === "date" ? "YYYY-MM-DD" : "" })
276950
277048
  });
276951
277049
  }
276952
277050
 
@@ -306352,6 +306450,87 @@ function toolbarTemplate() {
306352
306450
  init_lit_html();
306353
306451
  init_store();
306354
306452
  init_reactivity();
306453
+
306454
+ // src/panels/panel-scheduler.ts
306455
+ function isTextInput(el) {
306456
+ if (!el)
306457
+ return false;
306458
+ const tag5 = el.tagName.toLowerCase();
306459
+ if (tag5 === "input" || tag5 === "textarea")
306460
+ return true;
306461
+ if (tag5 === "sp-textfield" || tag5 === "sp-number-field" || tag5 === "sp-search")
306462
+ return true;
306463
+ if (el.shadowRoot?.activeElement)
306464
+ return isTextInput(el.shadowRoot.activeElement);
306465
+ return false;
306466
+ }
306467
+ function createPanelScheduler(opts) {
306468
+ const { root: root3, render: render6, blockWhile } = opts;
306469
+ let editing = false;
306470
+ let scheduled = false;
306471
+ let pending = false;
306472
+ let rendering = false;
306473
+ let rafId = 0;
306474
+ const blocked = () => editing || (blockWhile ? blockWhile() : false);
306475
+ function flush() {
306476
+ scheduled = false;
306477
+ rafId = 0;
306478
+ if (rendering)
306479
+ return;
306480
+ if (blocked()) {
306481
+ pending = true;
306482
+ return;
306483
+ }
306484
+ pending = false;
306485
+ rendering = true;
306486
+ try {
306487
+ render6();
306488
+ } finally {
306489
+ rendering = false;
306490
+ }
306491
+ }
306492
+ function schedule() {
306493
+ if (scheduled)
306494
+ return;
306495
+ scheduled = true;
306496
+ rafId = requestAnimationFrame(flush);
306497
+ }
306498
+ function onFocusIn(e20) {
306499
+ editing = isTextInput(e20.target);
306500
+ }
306501
+ function onFocusOut() {
306502
+ editing = false;
306503
+ if (pending)
306504
+ schedule();
306505
+ }
306506
+ return {
306507
+ schedule,
306508
+ isEditing: () => blocked(),
306509
+ bindFocus() {
306510
+ root3.addEventListener("focusin", onFocusIn);
306511
+ root3.addEventListener("focusout", onFocusOut);
306512
+ },
306513
+ unbind() {
306514
+ root3.removeEventListener("focusin", onFocusIn);
306515
+ root3.removeEventListener("focusout", onFocusOut);
306516
+ if (rafId)
306517
+ cancelAnimationFrame(rafId);
306518
+ scheduled = false;
306519
+ pending = false;
306520
+ editing = false;
306521
+ rendering = false;
306522
+ },
306523
+ flushNow() {
306524
+ if (rafId)
306525
+ cancelAnimationFrame(rafId);
306526
+ rafId = 0;
306527
+ scheduled = false;
306528
+ flush();
306529
+ }
306530
+ };
306531
+ }
306532
+
306533
+ // src/panels/right-panel.ts
306355
306534
  init_workspace2();
306356
306535
 
306357
306536
  // src/panels/events-panel.ts
@@ -309598,21 +309777,12 @@ function bindableFieldRow(label4, type2, rawValue, onChange, filterFn = null, ex
309598
309777
  const defs = tab.doc.document.state || {};
309599
309778
  const isBound = typeof rawValue === "object" && rawValue !== null && rawValue.$ref;
309600
309779
  const signalDefs = Object.entries(defs).filter(([, d3]) => filterFn ? filterFn(d3) : !d3?.$handler && d3?.$prototype !== "Function");
309601
- let debounce;
309602
- const onInput2 = (e20) => {
309603
- clearTimeout(debounce);
309604
- debounce = setTimeout(() => onChange(e20.target.value), 400);
309605
- };
309606
309780
  const staticVal = isBound ? "" : rawValue ?? "";
309607
- const staticTpl = type2 === "textarea" ? html3`<sp-textfield
309608
- multiline
309609
- size="s"
309610
- .value=${live(staticVal)}
309611
- @input=${onInput2}
309612
- ></sp-textfield>` : type2 === "checkbox" ? html3`<sp-checkbox
309781
+ const fieldKey = `prop:${label4}`;
309782
+ const staticTpl = type2 === "textarea" ? spTextArea(fieldKey, String(staticVal), (v) => onChange(v)) : type2 === "checkbox" ? html3`<sp-checkbox
309613
309783
  ?checked=${!!staticVal}
309614
309784
  @change=${(e20) => onChange(e20.target.checked)}
309615
- ></sp-checkbox>` : html3`<sp-textfield size="s" .value=${live(staticVal)} @input=${onInput2}></sp-textfield>`;
309785
+ ></sp-checkbox>` : spTextField(fieldKey, String(staticVal), (v) => onChange(v));
309616
309786
  const boundTpl = html3`
309617
309787
  <sp-picker
309618
309788
  size="s"
@@ -309856,15 +310026,9 @@ function renderComponentPropsFieldsTemplate(node2, path2, mapSignals, navigateTo
309856
310026
  } else if (prop.format === "color") {
309857
310027
  widgetTpl = renderColorSelector(prop.name, staticVal, onChange);
309858
310028
  } else if (prop.format === "date") {
309859
- widgetTpl = html3`<sp-textfield
309860
- size="s"
309861
- placeholder="YYYY-MM-DD"
309862
- .value=${live(staticVal)}
309863
- @input=${(e20) => {
309864
- clearTimeout(debounce);
309865
- debounce = setTimeout(() => onChange(e20.target.value), 400);
309866
- }}
309867
- ></sp-textfield>`;
310029
+ widgetTpl = spTextField(`cprop:${prop.name}`, String(staticVal), (v) => onChange(v), {
310030
+ placeholder: "YYYY-MM-DD"
310031
+ });
309868
310032
  } else if (parsed.kind === "boolean") {
309869
310033
  widgetTpl = html3`<sp-checkbox
309870
310034
  size="s"
@@ -309890,14 +310054,7 @@ function renderComponentPropsFieldsTemplate(node2, path2, mapSignals, navigateTo
309890
310054
  @change=${(e20) => onChange(e20.detail?.value ?? e20.target.value)}
309891
310055
  ></jx-value-selector>`;
309892
310056
  } else {
309893
- widgetTpl = html3`<sp-textfield
309894
- size="s"
309895
- .value=${live(staticVal)}
309896
- @input=${(e20) => {
309897
- clearTimeout(debounce);
309898
- debounce = setTimeout(() => onChange(e20.target.value), 400);
309899
- }}
309900
- ></sp-textfield>`;
310057
+ widgetTpl = spTextField(`cprop:${prop.name}`, String(staticVal), (v) => onChange(v));
309901
310058
  }
309902
310059
  return html3`
309903
310060
  <div class="style-row" data-prop=${prop.name}>
@@ -310334,13 +310491,7 @@ function renderPropertiesPanelTemplate(ctx) {
310334
310491
  ></span>` : nothing}
310335
310492
  <sp-field-label size="s">ID</sp-field-label>
310336
310493
  </div>
310337
- <sp-textfield
310338
- size="s"
310339
- .value=${live(node2.$id || "")}
310340
- @input=${debouncedStyleCommit("prop:$id", 400, (e20) => {
310341
- transactDoc(activeTab.value, (t15) => mutateUpdateProperty(t15, path2, "$id", e20.target.value || undefined));
310342
- })}
310343
- ></sp-textfield>
310494
+ ${spTextField("prop:$id", String(node2.$id || ""), (v) => transactDoc(activeTab.value, (t15) => mutateUpdateProperty(t15, path2, "$id", v || undefined)))}
310344
310495
  </div>
310345
310496
  <div class="style-row" data-prop="className">
310346
310497
  <div class="style-row-label">
@@ -310354,13 +310505,7 @@ function renderPropertiesPanelTemplate(ctx) {
310354
310505
  ></span>` : nothing}
310355
310506
  <sp-field-label size="s">Class</sp-field-label>
310356
310507
  </div>
310357
- <sp-textfield
310358
- size="s"
310359
- .value=${live(node2.className || "")}
310360
- @input=${debouncedStyleCommit("prop:className", 400, (e20) => {
310361
- transactDoc(activeTab.value, (t15) => mutateUpdateProperty(t15, path2, "className", e20.target.value || undefined));
310362
- })}
310363
- ></sp-textfield>
310508
+ ${spTextField("prop:className", String(node2.className || ""), (v) => transactDoc(activeTab.value, (t15) => mutateUpdateProperty(t15, path2, "className", v || undefined)))}
310364
310509
  </div>
310365
310510
  ${!Array.isArray(node2.children) || node2.children.length === 0 ? html3`
310366
310511
  <div class="style-row" data-prop="textContent">
@@ -310375,14 +310520,7 @@ function renderPropertiesPanelTemplate(ctx) {
310375
310520
  ></span>` : nothing}
310376
310521
  <sp-field-label size="s">Text Content</sp-field-label>
310377
310522
  </div>
310378
- <sp-textfield
310379
- size="s"
310380
- multiline
310381
- .value=${live(typeof node2.textContent === "string" ? node2.textContent : node2.textContent ?? "")}
310382
- @input=${debouncedStyleCommit("prop:textContent", 400, (e20) => {
310383
- transactDoc(activeTab.value, (t15) => mutateUpdateProperty(t15, path2, "textContent", e20.target.value || undefined));
310384
- })}
310385
- ></sp-textfield>
310523
+ ${spTextArea("prop:textContent", typeof node2.textContent === "string" ? node2.textContent : "", (v) => transactDoc(activeTab.value, (t15) => mutateUpdateProperty(t15, path2, "textContent", v || undefined)))}
310386
310524
  </div>
310387
310525
  ` : nothing}
310388
310526
  <div class="style-row" data-prop="hidden">
@@ -311579,34 +311717,17 @@ function renderAiPanelTemplate() {
311579
311717
  // src/panels/right-panel.ts
311580
311718
  var _ctx13 = null;
311581
311719
  var _scope5 = null;
311582
- var _rendering = false;
311583
- var _scheduled2 = false;
311584
- var _hasFocus = false;
311585
- function _isTextInput(el) {
311586
- if (!el)
311587
- return false;
311588
- const tag5 = el.tagName.toLowerCase();
311589
- if (tag5 === "input" || tag5 === "textarea")
311590
- return true;
311591
- if (tag5 === "sp-textfield" || tag5 === "sp-number-field" || tag5 === "sp-search")
311592
- return true;
311593
- if (el.shadowRoot?.activeElement)
311594
- return _isTextInput(el.shadowRoot.activeElement);
311595
- return false;
311596
- }
311597
- function _onFocusIn(e21) {
311598
- _hasFocus = _isTextInput(e21.target);
311599
- }
311600
- function _onFocusOut() {
311601
- _hasFocus = false;
311602
- render6();
311603
- }
311720
+ var _scheduler = null;
311604
311721
  function mount6(ctx) {
311605
311722
  _ctx13 = ctx;
311606
311723
  mountAiPanel();
311607
311724
  registerRightPanelRender(render6);
311608
- rightPanel.addEventListener("focusin", _onFocusIn);
311609
- rightPanel.addEventListener("focusout", _onFocusOut);
311725
+ _scheduler = createPanelScheduler({
311726
+ root: rightPanel,
311727
+ render: _doRender,
311728
+ blockWhile: isColorPopoverOpen
311729
+ });
311730
+ _scheduler.bindFocus();
311610
311731
  _scope5 = effectScope();
311611
311732
  _scope5.run(() => {
311612
311733
  effect(() => {
@@ -311623,22 +311744,12 @@ function mount6(ctx) {
311623
311744
  tab.session.ui.styleFilter;
311624
311745
  tab.session.ui.styleFilterActive;
311625
311746
  tab.session.ui.inspectorSections;
311626
- if (!_hasFocus && !isColorPopoverOpen()) {
311627
- render6();
311628
- }
311747
+ render6();
311629
311748
  });
311630
311749
  });
311631
311750
  }
311632
- var _rafId = 0;
311633
311751
  function render6() {
311634
- if (!_ctx13)
311635
- return;
311636
- if (_rendering)
311637
- return;
311638
- if (!_scheduled2) {
311639
- _scheduled2 = true;
311640
- _rafId = requestAnimationFrame(_flush2);
311641
- }
311752
+ _scheduler?.schedule();
311642
311753
  }
311643
311754
  var _propsContainer = null;
311644
311755
  var _eventsContainer = null;
@@ -311658,16 +311769,9 @@ function _ensureContainers() {
311658
311769
  _assistantContainer.className = "panel-body";
311659
311770
  _assistantContainer.style.cssText = "display:flex;flex-direction:column;overflow:hidden";
311660
311771
  }
311661
- function _flush2() {
311662
- _scheduled2 = false;
311663
- _rafId = 0;
311772
+ function _doRender() {
311664
311773
  if (!_ctx13)
311665
311774
  return;
311666
- if (_rendering)
311667
- return;
311668
- if (_hasFocus || isColorPopoverOpen())
311669
- return;
311670
- _rendering = true;
311671
311775
  try {
311672
311776
  const ctx = _ctx13;
311673
311777
  const aTab = activeTab.value;
@@ -311745,8 +311849,6 @@ function _flush2() {
311745
311849
  _lastTab = tab;
311746
311850
  } catch (e21) {
311747
311851
  console.error("right-panel render error:", e21);
311748
- } finally {
311749
- _rendering = false;
311750
311852
  }
311751
311853
  requestAnimationFrame(() => mountQuikChat());
311752
311854
  _ctx13.updateForcedPseudoPreview();
@@ -311960,20 +312062,11 @@ function renderElementsTemplate(ctx) {
311960
312062
  // src/panels/left-panel.ts
311961
312063
  var _ctx14 = null;
311962
312064
  var _scope6 = null;
311963
- var _rendering2 = false;
311964
- var _scheduled3 = false;
311965
- var _hasFocus2 = false;
311966
- function _onFocusIn2() {
311967
- _hasFocus2 = true;
311968
- }
311969
- function _onFocusOut2() {
311970
- _hasFocus2 = false;
311971
- render7();
311972
- }
312065
+ var _scheduler2 = null;
311973
312066
  function mount7(ctx) {
311974
312067
  _ctx14 = ctx;
311975
- leftPanel.addEventListener("focusin", _onFocusIn2);
311976
- leftPanel.addEventListener("focusout", _onFocusOut2);
312068
+ _scheduler2 = createPanelScheduler({ root: leftPanel, render: _doRender2 });
312069
+ _scheduler2.bindFocus();
311977
312070
  _scope6 = effectScope();
311978
312071
  _scope6.run(() => {
311979
312072
  effect(() => {
@@ -311987,29 +312080,16 @@ function mount7(ctx) {
311987
312080
  tab.session.ui.gitLoading;
311988
312081
  tab.session.ui.gitError;
311989
312082
  }
311990
- if (!_hasFocus2) {
311991
- render7();
311992
- }
312083
+ render7();
311993
312084
  });
311994
312085
  });
311995
312086
  }
311996
312087
  function render7() {
311997
- if (!_ctx14)
311998
- return;
311999
- if (_rendering2)
312000
- return;
312001
- if (!_scheduled3) {
312002
- _scheduled3 = true;
312003
- queueMicrotask(_flush3);
312004
- }
312088
+ _scheduler2?.schedule();
312005
312089
  }
312006
- function _flush3() {
312007
- _scheduled3 = false;
312090
+ function _doRender2() {
312008
312091
  if (!_ctx14)
312009
312092
  return;
312010
- if (_rendering2)
312011
- return;
312012
- _rendering2 = true;
312013
312093
  try {
312014
312094
  _render();
312015
312095
  } catch (e21) {
@@ -312021,8 +312101,6 @@ function _flush3() {
312021
312101
  } catch (e22) {
312022
312102
  console.error("left-panel retry failed:", e22);
312023
312103
  }
312024
- } finally {
312025
- _rendering2 = false;
312026
312104
  }
312027
312105
  if (view.leftTab === "layers") {
312028
312106
  const sel = leftPanel.querySelector(".layer-row.selected");
@@ -312738,5 +312816,5 @@ effect(() => {
312738
312816
  scheduleAutosave();
312739
312817
  });
312740
312818
 
312741
- //# debugId=8A6CA76BD8515F1464756E2164756E21
312819
+ //# debugId=2006FB9B9654EF0F64756E2164756E21
312742
312820
  //# sourceMappingURL=studio.js.map