@jxsuite/studio 0.10.2 → 0.13.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.
- package/README.md +82 -0
- package/dist/studio.js +5114 -3424
- package/dist/studio.js.map +65 -49
- package/package.json +6 -3
- package/src/browse/browse.js +27 -3
- package/src/canvas/canvas-diff.js +184 -0
- package/src/canvas/canvas-helpers.js +10 -14
- package/src/canvas/canvas-live-render.js +136 -17
- package/src/canvas/canvas-render.js +154 -21
- package/src/canvas/canvas-utils.js +21 -23
- package/src/editor/component-inline-edit.js +54 -41
- package/src/editor/content-inline-edit.js +46 -47
- package/src/editor/context-menu.js +63 -39
- package/src/editor/convert-to-component.js +11 -14
- package/src/editor/insertion-helper.js +8 -10
- package/src/editor/shortcuts.js +69 -39
- package/src/files/components.js +15 -4
- package/src/files/files.js +72 -24
- package/src/panels/activity-bar.js +29 -7
- package/src/panels/block-action-bar.js +104 -80
- package/src/panels/canvas-dnd.js +132 -50
- package/src/panels/dnd.js +32 -28
- package/src/panels/editors.js +7 -14
- package/src/panels/elements-panel.js +9 -3
- package/src/panels/events-panel.js +44 -39
- package/src/panels/git-panel.js +45 -3
- package/src/panels/layers-panel.js +16 -11
- package/src/panels/left-panel.js +108 -43
- package/src/panels/overlays.js +97 -35
- package/src/panels/panel-events.js +18 -11
- package/src/panels/properties-panel.js +467 -98
- package/src/panels/right-panel.js +85 -37
- package/src/panels/shared.js +0 -22
- package/src/panels/signals-panel.js +125 -54
- package/src/panels/statusbar.js +23 -8
- package/src/panels/style-inputs.js +4 -2
- package/src/panels/style-panel.js +128 -105
- package/src/panels/stylebook-panel.js +42 -17
- package/src/panels/tab-strip.js +124 -0
- package/src/panels/toolbar.js +39 -9
- package/src/reactivity.js +28 -0
- package/src/settings/content-types-editor.js +78 -8
- package/src/settings/defs-editor.js +56 -7
- package/src/settings/schema-field-ui.js +99 -11
- package/src/site-context.js +105 -0
- package/src/state.js +0 -456
- package/src/store.js +105 -124
- package/src/studio.js +112 -121
- package/src/tabs/tab.js +153 -0
- package/src/tabs/transact.js +406 -0
- package/src/ui/spectrum.js +2 -0
- package/src/view.js +3 -0
- package/src/workspace/workspace.js +89 -0
|
@@ -5,7 +5,14 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { html, nothing } from "lit-html";
|
|
8
|
-
import {
|
|
8
|
+
import { activeTab } from "../workspace/workspace.js";
|
|
9
|
+
import {
|
|
10
|
+
transactDoc,
|
|
11
|
+
mutateUpdateDef,
|
|
12
|
+
mutateAddDef,
|
|
13
|
+
mutateRemoveDef,
|
|
14
|
+
mutateRenameDef,
|
|
15
|
+
} from "../tabs/transact.js";
|
|
9
16
|
import { renderFieldRow } from "../ui/field-row.js";
|
|
10
17
|
import { fetchPluginSchema, pluginSchemaCache } from "../services/code-services.js";
|
|
11
18
|
|
|
@@ -266,7 +273,7 @@ export function renderSignalsTemplate(S, ctx) {
|
|
|
266
273
|
class="signal-del"
|
|
267
274
|
@click=${(/** @type {any} */ e) => {
|
|
268
275
|
e.stopPropagation();
|
|
269
|
-
|
|
276
|
+
transactDoc(activeTab.value, (t) => mutateRemoveDef(t, name));
|
|
270
277
|
}}
|
|
271
278
|
>
|
|
272
279
|
<sp-icon-delete slot="icon"></sp-icon-delete>
|
|
@@ -304,7 +311,7 @@ export function renderSignalsTemplate(S, ctx) {
|
|
|
304
311
|
while (S.document.state && S.document.state[n]) {
|
|
305
312
|
n = nameBase + i++;
|
|
306
313
|
}
|
|
307
|
-
|
|
314
|
+
transactDoc(activeTab.value, (t) => mutateAddDef(t, n, structuredClone(template)));
|
|
308
315
|
expandedSignal = n;
|
|
309
316
|
ctx.renderLeftPanel();
|
|
310
317
|
}}
|
|
@@ -396,7 +403,7 @@ function renderSignalEditorTemplate(
|
|
|
396
403
|
const nameField = signalFieldRow("Name", name, (/** @type {any} */ v) => {
|
|
397
404
|
if (v && v !== name && !(S.document.state && S.document.state[v])) {
|
|
398
405
|
expandedSignal = v;
|
|
399
|
-
|
|
406
|
+
transactDoc(activeTab.value, (t) => mutateRenameDef(t, name, v));
|
|
400
407
|
}
|
|
401
408
|
});
|
|
402
409
|
|
|
@@ -414,7 +421,9 @@ function renderSignalEditorTemplate(
|
|
|
414
421
|
const cemFields = isCustomElementDoc(S)
|
|
415
422
|
? html`
|
|
416
423
|
${signalFieldRow("Attribute", def.attribute || "", (/** @type {any} */ v) =>
|
|
417
|
-
|
|
424
|
+
transactDoc(activeTab.value, (t) =>
|
|
425
|
+
mutateUpdateDef(t, name, { attribute: v || undefined }),
|
|
426
|
+
),
|
|
418
427
|
)}
|
|
419
428
|
${renderFieldRow({
|
|
420
429
|
prop: "reflects",
|
|
@@ -425,14 +434,19 @@ function renderSignalEditorTemplate(
|
|
|
425
434
|
class="field-check"
|
|
426
435
|
?checked=${!!def.reflects}
|
|
427
436
|
@change=${(/** @type {any} */ e) =>
|
|
428
|
-
|
|
437
|
+
transactDoc(activeTab.value, (t) =>
|
|
438
|
+
mutateUpdateDef(t, name, { reflects: e.target.checked || undefined }),
|
|
439
|
+
)}
|
|
429
440
|
></sp-checkbox>
|
|
430
441
|
`,
|
|
431
442
|
})}
|
|
432
443
|
${signalFieldRow(
|
|
433
444
|
"Deprecated",
|
|
434
445
|
typeof def.deprecated === "string" ? def.deprecated : "",
|
|
435
|
-
(/** @type {any} */ v) =>
|
|
446
|
+
(/** @type {any} */ v) =>
|
|
447
|
+
transactDoc(activeTab.value, (t) =>
|
|
448
|
+
mutateUpdateDef(t, name, { deprecated: v || undefined }),
|
|
449
|
+
),
|
|
436
450
|
)}
|
|
437
451
|
`
|
|
438
452
|
: nothing;
|
|
@@ -442,8 +456,20 @@ function renderSignalEditorTemplate(
|
|
|
442
456
|
"Type",
|
|
443
457
|
["string", "integer", "number", "boolean", "array", "object"],
|
|
444
458
|
def.type || "string",
|
|
445
|
-
(/** @type {any} */ v) =>
|
|
459
|
+
(/** @type {any} */ v) =>
|
|
460
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { type: v })),
|
|
446
461
|
)}
|
|
462
|
+
${def.type === "string" || !def.type
|
|
463
|
+
? pickerRow(
|
|
464
|
+
"Format",
|
|
465
|
+
["", "image", "date", "color"],
|
|
466
|
+
def.format || "",
|
|
467
|
+
(/** @type {any} */ v) =>
|
|
468
|
+
transactDoc(activeTab.value, (t) =>
|
|
469
|
+
mutateUpdateDef(t, name, { format: v || undefined }),
|
|
470
|
+
),
|
|
471
|
+
)
|
|
472
|
+
: nothing}
|
|
447
473
|
${signalFieldRow("Default", defaultVal, (/** @type {any} */ v) => {
|
|
448
474
|
let parsed = v;
|
|
449
475
|
if (def.type === "integer") parsed = parseInt(v, 10) || 0;
|
|
@@ -456,10 +482,12 @@ function renderSignalEditorTemplate(
|
|
|
456
482
|
parsed = v;
|
|
457
483
|
}
|
|
458
484
|
}
|
|
459
|
-
|
|
485
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { default: parsed }));
|
|
460
486
|
})}
|
|
461
487
|
${signalFieldRow("Description", def.description || "", (/** @type {any} */ v) =>
|
|
462
|
-
|
|
488
|
+
transactDoc(activeTab.value, (t) =>
|
|
489
|
+
mutateUpdateDef(t, name, { description: v || undefined }),
|
|
490
|
+
),
|
|
463
491
|
)}
|
|
464
492
|
${cemFields}
|
|
465
493
|
`;
|
|
@@ -482,7 +510,9 @@ function renderSignalEditorTemplate(
|
|
|
482
510
|
const expr = e.target.value;
|
|
483
511
|
const depMatches = expr.match(/\$[a-zA-Z_]\w*/g) || [];
|
|
484
512
|
const deps = [...new Set(depMatches)].map((d) => `#/state/${d}`);
|
|
485
|
-
|
|
513
|
+
transactDoc(activeTab.value, (t) =>
|
|
514
|
+
mutateUpdateDef(t, name, { $compute: expr, $deps: deps }),
|
|
515
|
+
);
|
|
486
516
|
}, 500);
|
|
487
517
|
}}
|
|
488
518
|
></textarea>
|
|
@@ -526,16 +556,17 @@ function renderDataSourceFields(
|
|
|
526
556
|
if (proto === "Request") {
|
|
527
557
|
return html`
|
|
528
558
|
${signalFieldRow("URL", def.url || "", (/** @type {any} */ v) =>
|
|
529
|
-
|
|
559
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { url: v })),
|
|
530
560
|
)}
|
|
531
561
|
${pickerRow(
|
|
532
562
|
"Method",
|
|
533
563
|
["GET", "POST", "PUT", "DELETE", "PATCH"],
|
|
534
564
|
def.method || "GET",
|
|
535
|
-
(/** @type {any} */ v) =>
|
|
565
|
+
(/** @type {any} */ v) =>
|
|
566
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { method: v })),
|
|
536
567
|
)}
|
|
537
568
|
${pickerRow("Timing", ["client", "server"], def.timing || "client", (/** @type {any} */ v) =>
|
|
538
|
-
|
|
569
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { timing: v })),
|
|
539
570
|
)}
|
|
540
571
|
`;
|
|
541
572
|
}
|
|
@@ -548,13 +579,13 @@ function renderDataSourceFields(
|
|
|
548
579
|
: "";
|
|
549
580
|
return html`
|
|
550
581
|
${signalFieldRow("Key", def.key || "", (/** @type {any} */ v) =>
|
|
551
|
-
|
|
582
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { key: v })),
|
|
552
583
|
)}
|
|
553
584
|
${textareaRow("Default", defaultStr, (/** @type {any} */ v) => {
|
|
554
585
|
try {
|
|
555
|
-
|
|
586
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { default: JSON.parse(v) }));
|
|
556
587
|
} catch {
|
|
557
|
-
|
|
588
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { default: v }));
|
|
558
589
|
}
|
|
559
590
|
})}
|
|
560
591
|
`;
|
|
@@ -562,23 +593,25 @@ function renderDataSourceFields(
|
|
|
562
593
|
if (proto === "IndexedDB") {
|
|
563
594
|
return html`
|
|
564
595
|
${signalFieldRow("Database", def.database || "", (/** @type {any} */ v) =>
|
|
565
|
-
|
|
596
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { database: v })),
|
|
566
597
|
)}
|
|
567
598
|
${signalFieldRow("Store", def.store || "", (/** @type {any} */ v) =>
|
|
568
|
-
|
|
599
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { store: v })),
|
|
569
600
|
)}
|
|
570
601
|
${signalFieldRow("Version", String(def.version || 1), (/** @type {any} */ v) =>
|
|
571
|
-
|
|
602
|
+
transactDoc(activeTab.value, (t) =>
|
|
603
|
+
mutateUpdateDef(t, name, { version: parseInt(v, 10) || 1 }),
|
|
604
|
+
),
|
|
572
605
|
)}
|
|
573
606
|
`;
|
|
574
607
|
}
|
|
575
608
|
if (proto === "Cookie") {
|
|
576
609
|
return html`
|
|
577
610
|
${signalFieldRow("Cookie", def.name || "", (/** @type {any} */ v) =>
|
|
578
|
-
|
|
611
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { name: v })),
|
|
579
612
|
)}
|
|
580
613
|
${signalFieldRow("Default", def.default || "", (/** @type {any} */ v) =>
|
|
581
|
-
|
|
614
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { default: v })),
|
|
582
615
|
)}
|
|
583
616
|
`;
|
|
584
617
|
}
|
|
@@ -593,7 +626,9 @@ function renderDataSourceFields(
|
|
|
593
626
|
: "";
|
|
594
627
|
return textareaRow(fieldLabel, defaultStr, (/** @type {any} */ v) => {
|
|
595
628
|
try {
|
|
596
|
-
|
|
629
|
+
transactDoc(activeTab.value, (t) =>
|
|
630
|
+
mutateUpdateDef(t, name, { [fieldName]: JSON.parse(v) }),
|
|
631
|
+
);
|
|
597
632
|
} catch {}
|
|
598
633
|
});
|
|
599
634
|
}
|
|
@@ -612,16 +647,19 @@ function renderFunctionFields(
|
|
|
612
647
|
const srcFields = def.$src
|
|
613
648
|
? html`
|
|
614
649
|
${signalFieldRow("Source", def.$src || "", (/** @type {any} */ v) =>
|
|
615
|
-
|
|
650
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { $src: v || undefined })),
|
|
616
651
|
)}
|
|
617
652
|
${signalFieldRow("Export", def.$export || "", (/** @type {any} */ v) =>
|
|
618
|
-
|
|
653
|
+
transactDoc(activeTab.value, (t) =>
|
|
654
|
+
mutateUpdateDef(t, name, { $export: v || undefined }),
|
|
655
|
+
),
|
|
619
656
|
)}
|
|
620
657
|
`
|
|
621
658
|
: textareaRow(
|
|
622
659
|
"Body",
|
|
623
660
|
def.body || "",
|
|
624
|
-
(/** @type {any} */ v) =>
|
|
661
|
+
(/** @type {any} */ v) =>
|
|
662
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { body: v })),
|
|
625
663
|
{ minHeight: "60px", mono: true },
|
|
626
664
|
);
|
|
627
665
|
|
|
@@ -643,7 +681,9 @@ function renderFunctionFields(
|
|
|
643
681
|
`
|
|
644
682
|
: nothing}
|
|
645
683
|
${signalFieldRow("Description", def.description || "", (/** @type {any} */ v) =>
|
|
646
|
-
|
|
684
|
+
transactDoc(activeTab.value, (t) =>
|
|
685
|
+
mutateUpdateDef(t, name, { description: v || undefined }),
|
|
686
|
+
),
|
|
647
687
|
)}
|
|
648
688
|
`;
|
|
649
689
|
}
|
|
@@ -677,8 +717,8 @@ function renderParameterEditorTemplate(
|
|
|
677
717
|
<span
|
|
678
718
|
style="cursor:pointer;opacity:0.5;margin-left:2px"
|
|
679
719
|
@click=${() => {
|
|
680
|
-
|
|
681
|
-
|
|
720
|
+
transactDoc(activeTab.value, (t) =>
|
|
721
|
+
mutateUpdateDef(t, name, {
|
|
682
722
|
parameters: params.filter(
|
|
683
723
|
(/** @type {any} */ _, /** @type {any} */ j) => j !== i,
|
|
684
724
|
).length
|
|
@@ -698,8 +738,10 @@ function renderParameterEditorTemplate(
|
|
|
698
738
|
placeholder="+"
|
|
699
739
|
@keydown=${(/** @type {any} */ e) => {
|
|
700
740
|
if (e.key === "Enter" && e.target.value.trim()) {
|
|
701
|
-
|
|
702
|
-
|
|
741
|
+
transactDoc(activeTab.value, (t) =>
|
|
742
|
+
mutateUpdateDef(t, name, {
|
|
743
|
+
parameters: [...params, { name: e.target.value.trim() }],
|
|
744
|
+
}),
|
|
703
745
|
);
|
|
704
746
|
}
|
|
705
747
|
}}
|
|
@@ -735,7 +777,9 @@ function renderParameterEditorTemplate(
|
|
|
735
777
|
@change=${(/** @type {any} */ e) => {
|
|
736
778
|
const next = [...params];
|
|
737
779
|
next[i] = { ...next[i], name: e.target.value };
|
|
738
|
-
|
|
780
|
+
transactDoc(activeTab.value, (t) =>
|
|
781
|
+
mutateUpdateDef(t, name, { parameters: next }),
|
|
782
|
+
);
|
|
739
783
|
}}
|
|
740
784
|
/>
|
|
741
785
|
<input
|
|
@@ -749,7 +793,9 @@ function renderParameterEditorTemplate(
|
|
|
749
793
|
...next[i],
|
|
750
794
|
type: e.target.value ? { text: e.target.value } : undefined,
|
|
751
795
|
};
|
|
752
|
-
|
|
796
|
+
transactDoc(activeTab.value, (t) =>
|
|
797
|
+
mutateUpdateDef(t, name, { parameters: next }),
|
|
798
|
+
);
|
|
753
799
|
}}
|
|
754
800
|
/>
|
|
755
801
|
<input
|
|
@@ -760,7 +806,9 @@ function renderParameterEditorTemplate(
|
|
|
760
806
|
@change=${(/** @type {any} */ e) => {
|
|
761
807
|
const next = [...params];
|
|
762
808
|
next[i] = { ...next[i], description: e.target.value || undefined };
|
|
763
|
-
|
|
809
|
+
transactDoc(activeTab.value, (t) =>
|
|
810
|
+
mutateUpdateDef(t, name, { parameters: next }),
|
|
811
|
+
);
|
|
764
812
|
}}
|
|
765
813
|
/>
|
|
766
814
|
<input
|
|
@@ -770,7 +818,9 @@ function renderParameterEditorTemplate(
|
|
|
770
818
|
@change=${(/** @type {any} */ e) => {
|
|
771
819
|
const next = [...params];
|
|
772
820
|
next[i] = { ...next[i], optional: e.target.checked || undefined };
|
|
773
|
-
|
|
821
|
+
transactDoc(activeTab.value, (t) =>
|
|
822
|
+
mutateUpdateDef(t, name, { parameters: next }),
|
|
823
|
+
);
|
|
774
824
|
}}
|
|
775
825
|
/>
|
|
776
826
|
<span
|
|
@@ -779,7 +829,9 @@ function renderParameterEditorTemplate(
|
|
|
779
829
|
const next = params.filter(
|
|
780
830
|
(/** @type {any} */ _, /** @type {any} */ j) => j !== i,
|
|
781
831
|
);
|
|
782
|
-
|
|
832
|
+
transactDoc(activeTab.value, (t) =>
|
|
833
|
+
mutateUpdateDef(t, name, { parameters: next.length ? next : undefined }),
|
|
834
|
+
);
|
|
783
835
|
}}
|
|
784
836
|
>×</span
|
|
785
837
|
>
|
|
@@ -788,7 +840,10 @@ function renderParameterEditorTemplate(
|
|
|
788
840
|
)}
|
|
789
841
|
<button
|
|
790
842
|
class="kv-add"
|
|
791
|
-
@click=${() =>
|
|
843
|
+
@click=${() =>
|
|
844
|
+
transactDoc(activeTab.value, (t) =>
|
|
845
|
+
mutateUpdateDef(t, name, { parameters: [...params, { name: "" }] }),
|
|
846
|
+
)}
|
|
792
847
|
>
|
|
793
848
|
+ Add parameter
|
|
794
849
|
</button>
|
|
@@ -831,7 +886,7 @@ function renderEmitsEditorTemplate(
|
|
|
831
886
|
@change=${(/** @type {any} */ e) => {
|
|
832
887
|
const next = [...emits];
|
|
833
888
|
next[i] = { ...next[i], name: e.target.value };
|
|
834
|
-
|
|
889
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { emits: next }));
|
|
835
890
|
}}
|
|
836
891
|
/>
|
|
837
892
|
<input
|
|
@@ -842,7 +897,7 @@ function renderEmitsEditorTemplate(
|
|
|
842
897
|
@change=${(/** @type {any} */ e) => {
|
|
843
898
|
const next = [...emits];
|
|
844
899
|
next[i] = { ...next[i], type: e.target.value ? { text: e.target.value } : undefined };
|
|
845
|
-
|
|
900
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { emits: next }));
|
|
846
901
|
}}
|
|
847
902
|
/>
|
|
848
903
|
<input
|
|
@@ -853,14 +908,14 @@ function renderEmitsEditorTemplate(
|
|
|
853
908
|
@change=${(/** @type {any} */ e) => {
|
|
854
909
|
const next = [...emits];
|
|
855
910
|
next[i] = { ...next[i], description: e.target.value || undefined };
|
|
856
|
-
|
|
911
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { emits: next }));
|
|
857
912
|
}}
|
|
858
913
|
/>
|
|
859
914
|
<span
|
|
860
915
|
style="cursor:pointer;opacity:0.5"
|
|
861
916
|
@click=${() => {
|
|
862
|
-
|
|
863
|
-
|
|
917
|
+
transactDoc(activeTab.value, (t) =>
|
|
918
|
+
mutateUpdateDef(t, name, {
|
|
864
919
|
emits: emits.filter((/** @type {any} */ _, /** @type {any} */ j) => j !== i)
|
|
865
920
|
.length
|
|
866
921
|
? emits.filter((/** @type {any} */ _, /** @type {any} */ j) => j !== i)
|
|
@@ -875,7 +930,10 @@ function renderEmitsEditorTemplate(
|
|
|
875
930
|
)}
|
|
876
931
|
<button
|
|
877
932
|
class="kv-add"
|
|
878
|
-
@click=${() =>
|
|
933
|
+
@click=${() =>
|
|
934
|
+
transactDoc(activeTab.value, (t) =>
|
|
935
|
+
mutateUpdateDef(t, name, { emits: [...emits, { name: "" }] }),
|
|
936
|
+
)}
|
|
879
937
|
>
|
|
880
938
|
+ Add event
|
|
881
939
|
</button>
|
|
@@ -892,7 +950,7 @@ export function renderSchemaFieldsTemplate(
|
|
|
892
950
|
/** @type {any} */ schema,
|
|
893
951
|
/** @type {any} */ def,
|
|
894
952
|
/** @type {any} */ name,
|
|
895
|
-
/** @type {any} */
|
|
953
|
+
/** @type {any} */ _S,
|
|
896
954
|
) {
|
|
897
955
|
if (!schema?.properties) return nothing;
|
|
898
956
|
|
|
@@ -915,8 +973,8 @@ export function renderSchemaFieldsTemplate(
|
|
|
915
973
|
? String(ps.default)
|
|
916
974
|
: "__none__"}
|
|
917
975
|
@change=${(/** @type {any} */ e) =>
|
|
918
|
-
|
|
919
|
-
|
|
976
|
+
transactDoc(activeTab.value, (t) =>
|
|
977
|
+
mutateUpdateDef(t, name, {
|
|
920
978
|
[prop]: e.target.value === "__none__" ? undefined : e.target.value,
|
|
921
979
|
}),
|
|
922
980
|
)}
|
|
@@ -931,7 +989,9 @@ export function renderSchemaFieldsTemplate(
|
|
|
931
989
|
control = html`<sp-checkbox
|
|
932
990
|
?checked=${currentValue ?? ps.default ?? false}
|
|
933
991
|
@change=${(/** @type {any} */ e) =>
|
|
934
|
-
|
|
992
|
+
transactDoc(activeTab.value, (t) =>
|
|
993
|
+
mutateUpdateDef(t, name, { [prop]: e.target.checked }),
|
|
994
|
+
)}
|
|
935
995
|
></sp-checkbox>`;
|
|
936
996
|
} else if (ps.type === "integer" || ps.type === "number") {
|
|
937
997
|
/** @type {any} */
|
|
@@ -948,7 +1008,9 @@ export function renderSchemaFieldsTemplate(
|
|
|
948
1008
|
debounce = setTimeout(() => {
|
|
949
1009
|
const parsed =
|
|
950
1010
|
ps.type === "integer" ? parseInt(e.target.value, 10) : parseFloat(e.target.value);
|
|
951
|
-
|
|
1011
|
+
transactDoc(activeTab.value, (t) =>
|
|
1012
|
+
mutateUpdateDef(t, name, { [prop]: isNaN(parsed) ? undefined : parsed }),
|
|
1013
|
+
);
|
|
952
1014
|
}, 400);
|
|
953
1015
|
}}
|
|
954
1016
|
></sp-number-field>`;
|
|
@@ -984,7 +1046,9 @@ export function renderSchemaFieldsTemplate(
|
|
|
984
1046
|
clearTimeout(debounce);
|
|
985
1047
|
debounce = setTimeout(() => {
|
|
986
1048
|
try {
|
|
987
|
-
|
|
1049
|
+
transactDoc(activeTab.value, (t) =>
|
|
1050
|
+
mutateUpdateDef(t, name, { [prop]: JSON.parse(e.target.value) }),
|
|
1051
|
+
);
|
|
988
1052
|
} catch {}
|
|
989
1053
|
}, 500);
|
|
990
1054
|
}}
|
|
@@ -1004,7 +1068,9 @@ export function renderSchemaFieldsTemplate(
|
|
|
1004
1068
|
clearTimeout(debounce);
|
|
1005
1069
|
debounce = setTimeout(() => {
|
|
1006
1070
|
try {
|
|
1007
|
-
|
|
1071
|
+
transactDoc(activeTab.value, (t) =>
|
|
1072
|
+
mutateUpdateDef(t, name, { [prop]: JSON.parse(e.target.value) }),
|
|
1073
|
+
);
|
|
1008
1074
|
} catch {}
|
|
1009
1075
|
}, 500);
|
|
1010
1076
|
}}
|
|
@@ -1021,7 +1087,10 @@ export function renderSchemaFieldsTemplate(
|
|
|
1021
1087
|
@input=${(/** @type {any} */ e) => {
|
|
1022
1088
|
clearTimeout(debounce);
|
|
1023
1089
|
debounce = setTimeout(
|
|
1024
|
-
() =>
|
|
1090
|
+
() =>
|
|
1091
|
+
transactDoc(activeTab.value, (t) =>
|
|
1092
|
+
mutateUpdateDef(t, name, { [prop]: e.target.value || undefined }),
|
|
1093
|
+
),
|
|
1025
1094
|
400,
|
|
1026
1095
|
);
|
|
1027
1096
|
}}
|
|
@@ -1077,16 +1146,18 @@ export function renderExternalPrototypeEditorTemplate(
|
|
|
1077
1146
|
|
|
1078
1147
|
return html`
|
|
1079
1148
|
${signalFieldRow("Source", def.$src || "", (/** @type {any} */ v) => {
|
|
1080
|
-
|
|
1149
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { $src: v || undefined }));
|
|
1081
1150
|
pluginSchemaCache.delete(`${v}::${def.$prototype}`);
|
|
1082
1151
|
})}
|
|
1083
1152
|
${signalFieldRow("Prototype", def.$prototype || "", (/** @type {any} */ v) => {
|
|
1084
|
-
|
|
1153
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { $prototype: v || undefined }));
|
|
1085
1154
|
pluginSchemaCache.delete(`${def.$src}::${v}`);
|
|
1086
1155
|
})}
|
|
1087
1156
|
${def.$export
|
|
1088
1157
|
? signalFieldRow("Export", def.$export || "", (/** @type {any} */ v) =>
|
|
1089
|
-
|
|
1158
|
+
transactDoc(activeTab.value, (t) =>
|
|
1159
|
+
mutateUpdateDef(t, name, { $export: v || undefined }),
|
|
1160
|
+
),
|
|
1090
1161
|
)
|
|
1091
1162
|
: nothing}
|
|
1092
1163
|
${schemaContent}
|
package/src/panels/statusbar.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/** Statusbar — status message display for Jx Studio */
|
|
2
2
|
|
|
3
|
-
import { statusbarEl, getNodeAtPath, nodeLabel
|
|
3
|
+
import { statusbarEl, getNodeAtPath, nodeLabel } from "../store.js";
|
|
4
|
+
import { effect, effectScope } from "../reactivity.js";
|
|
5
|
+
import { activeTab } from "../workspace/workspace.js";
|
|
4
6
|
|
|
5
7
|
// ─── Module state ────────────────────────────────────────────────────────────
|
|
6
8
|
|
|
@@ -9,8 +11,8 @@ let statusMsg = "";
|
|
|
9
11
|
let statusTimeout;
|
|
10
12
|
/** @type {(() => void) | null} */
|
|
11
13
|
let _rerender = null;
|
|
12
|
-
/** @type {(
|
|
13
|
-
let
|
|
14
|
+
/** @type {import("@vue/reactivity").EffectScope | null} */
|
|
15
|
+
let _scope = null;
|
|
14
16
|
|
|
15
17
|
/**
|
|
16
18
|
* Register the callback used to re-render the statusbar. Called once from studio.js during init.
|
|
@@ -21,16 +23,29 @@ export function setStatusbarRenderer(fn) {
|
|
|
21
23
|
_rerender = fn;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
/** Subscribe the statusbar to state changes. */
|
|
26
|
+
/** Subscribe the statusbar to state changes via reactive effect. */
|
|
25
27
|
export function mountStatusbar() {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
_scope = effectScope();
|
|
29
|
+
_scope.run(() => {
|
|
30
|
+
effect(() => {
|
|
31
|
+
const tab = activeTab.value;
|
|
32
|
+
if (!tab) return;
|
|
33
|
+
// Track relevant reactive properties
|
|
34
|
+
void tab.doc.document;
|
|
35
|
+
void tab.doc.mode;
|
|
36
|
+
void tab.session.selection;
|
|
37
|
+
renderStatusbar({
|
|
38
|
+
mode: tab.doc.mode,
|
|
39
|
+
document: tab.doc.document,
|
|
40
|
+
selection: tab.session.selection,
|
|
41
|
+
});
|
|
42
|
+
});
|
|
28
43
|
});
|
|
29
44
|
}
|
|
30
45
|
|
|
31
46
|
export function unmountStatusbar() {
|
|
32
|
-
|
|
33
|
-
|
|
47
|
+
_scope?.stop();
|
|
48
|
+
_scope = null;
|
|
34
49
|
}
|
|
35
50
|
|
|
36
51
|
// ─── Statusbar ───────────────────────────────────────────────────────────────
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import { html } from "lit-html";
|
|
4
4
|
import { live } from "lit-html/directives/live.js";
|
|
5
|
-
import { getState,
|
|
5
|
+
import { getState, debouncedStyleCommit } from "../store.js";
|
|
6
|
+
import { activeTab } from "../workspace/workspace.js";
|
|
7
|
+
import { transactDoc, mutateUpdateStyle } from "../tabs/transact.js";
|
|
6
8
|
import { widgetForType as _widgetForType } from "../ui/widgets.js";
|
|
7
9
|
import { kebabToLabel, friendlyNameToVar, varDisplayName } from "../utils/studio-utils.js";
|
|
8
10
|
import {
|
|
@@ -54,7 +56,7 @@ function handleFontPresetSelection(preset, onChange) {
|
|
|
54
56
|
const S = getState();
|
|
55
57
|
const varName = friendlyNameToVar(preset.title, "--font-");
|
|
56
58
|
if (!S.document?.style?.[varName]) {
|
|
57
|
-
|
|
59
|
+
transactDoc(activeTab.value, (t) => mutateUpdateStyle(t, [], varName, preset.value));
|
|
58
60
|
}
|
|
59
61
|
onChange(`var(${varName})`);
|
|
60
62
|
}
|