@jxsuite/studio 1.0.0 → 1.1.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/dist/iframe-entry.js +622 -49
- package/dist/iframe-entry.js.map +15 -12
- package/dist/studio.css +1333 -0
- package/dist/studio.js +53069 -31746
- package/dist/studio.js.map +109 -74
- package/package.json +11 -9
- package/src/canvas/canvas-live-render.ts +21 -2
- package/src/canvas/canvas-render.ts +35 -16
- package/src/canvas/canvas-utils.ts +118 -72
- package/src/canvas/iframe-entry.ts +20 -0
- package/src/canvas/iframe-eval.ts +155 -0
- package/src/canvas/iframe-host.ts +131 -5
- package/src/canvas/iframe-inline-edit.ts +107 -1
- package/src/canvas/iframe-protocol.ts +43 -3
- package/src/canvas/iframe-render.ts +18 -0
- package/src/collab/collab-session.ts +23 -8
- package/src/collab/collab-state.ts +6 -3
- package/src/component-props.ts +104 -0
- package/src/editor/inline-edit-apply.ts +36 -1
- package/src/editor/inline-edit.ts +58 -1
- package/src/editor/shortcuts.ts +41 -12
- package/src/files/file-ops.ts +14 -0
- package/src/files/files.ts +53 -1
- package/src/grid/cell-editors.ts +288 -0
- package/src/grid/cell-popovers.ts +108 -0
- package/src/grid/csv-codec.ts +122 -0
- package/src/grid/edit-buffer.ts +490 -0
- package/src/grid/grid-controller.ts +417 -0
- package/src/grid/grid-layout.ts +83 -0
- package/src/grid/grid-open.ts +167 -0
- package/src/grid/grid-panel.ts +302 -0
- package/src/grid/grid-source.ts +210 -0
- package/src/grid/grid-view.ts +367 -0
- package/src/grid/schema-columns.ts +261 -0
- package/src/grid/sources/connector-source.ts +217 -0
- package/src/grid/sources/content-source.ts +542 -0
- package/src/grid/sources/csv-file-source.ts +247 -0
- package/src/grid/tabulator-tables.d.ts +120 -0
- package/src/panels/block-action-bar.ts +8 -3
- package/src/panels/chat-panel.ts +98 -0
- package/src/panels/data-grid.ts +9 -387
- package/src/panels/editors.ts +43 -17
- package/src/panels/events-panel.ts +137 -44
- package/src/panels/formula-workspace.ts +379 -0
- package/src/panels/frontmatter-fields.ts +231 -0
- package/src/panels/frontmatter-panel.ts +132 -0
- package/src/panels/git-panel.ts +1 -1
- package/src/panels/head-panel.ts +11 -175
- package/src/panels/properties-panel.ts +154 -144
- package/src/panels/right-panel.ts +9 -47
- package/src/panels/signals-panel.ts +115 -23
- package/src/panels/statement-editor.ts +710 -0
- package/src/panels/style-panel.ts +25 -1
- package/src/panels/stylebook-panel.ts +0 -2
- package/src/panels/tab-bar.ts +175 -6
- package/src/panels/tab-strip.ts +62 -6
- package/src/panels/toolbar.ts +37 -3
- package/src/services/ai-project-tools.ts +541 -0
- package/src/services/ai-session-store.ts +28 -0
- package/src/services/ai-system-prompt.ts +194 -24
- package/src/services/ai-tools.ts +88 -21
- package/src/services/automation.ts +16 -0
- package/src/services/document-assistant.ts +81 -11
- package/src/services/gated-registry.ts +72 -0
- package/src/services/live-preview.ts +0 -0
- package/src/services/preview-eval.ts +68 -0
- package/src/services/project-adoption.ts +31 -0
- package/src/site-context.ts +2 -0
- package/src/store.ts +4 -0
- package/src/studio.ts +83 -52
- package/src/tabs/patch-ops.ts +25 -0
- package/src/tabs/tab.ts +39 -1
- package/src/tabs/transact.ts +60 -13
- package/src/types.ts +12 -0
- package/src/ui/dynamic-slot.ts +272 -0
- package/src/ui/expression-editor.ts +423 -125
- package/src/ui/field-row.ts +5 -0
- package/src/ui/formula-catalog.ts +557 -0
- package/src/ui/formula-chips.ts +216 -0
- package/src/ui/formula-palette.ts +211 -0
- package/src/ui/layers.ts +40 -0
- package/src/ui/media-picker.ts +1 -1
- package/src/ui/panel-resize.ts +15 -1
- package/src/utils/preview-format.ts +26 -0
- package/src/view.ts +4 -4
- package/src/workspace/workspace.ts +14 -0
|
@@ -23,7 +23,10 @@ import {
|
|
|
23
23
|
import { renderFieldRow } from "../ui/field-row";
|
|
24
24
|
import { rawTextArea, spTextField } from "../ui/field-input";
|
|
25
25
|
import { expressionHint, renderExpressionEditor } from "../ui/expression-editor";
|
|
26
|
+
import { renderStatementEditor } from "./statement-editor";
|
|
27
|
+
import { livePreviewExpression } from "../services/live-preview";
|
|
26
28
|
import { renderMediaPicker } from "../ui/media-picker";
|
|
29
|
+
import { renderOnly } from "../store";
|
|
27
30
|
import { registerFormControl, renderForm } from "../ui/schema-form";
|
|
28
31
|
import { resolveContextPointer } from "../services/context-resolver";
|
|
29
32
|
import type { JsonSchema } from "../ui/schema-form";
|
|
@@ -32,6 +35,7 @@ import type {
|
|
|
32
35
|
CemEvent,
|
|
33
36
|
CemParameter,
|
|
34
37
|
JxMutableNode,
|
|
38
|
+
JxStatement,
|
|
35
39
|
JxStateDefinition,
|
|
36
40
|
} from "@jxsuite/schema/types";
|
|
37
41
|
import { fetchPluginSchema, pluginSchemaCache } from "../services/code-services";
|
|
@@ -64,7 +68,7 @@ export interface SignalDef {
|
|
|
64
68
|
$handler?: string;
|
|
65
69
|
type?: string;
|
|
66
70
|
default?: unknown;
|
|
67
|
-
body?: string;
|
|
71
|
+
body?: string | unknown[];
|
|
68
72
|
parameters?: string[];
|
|
69
73
|
timing?: string;
|
|
70
74
|
description?: string;
|
|
@@ -234,6 +238,9 @@ export function defHint(_name: string, def: SignalDef | null | undefined) {
|
|
|
234
238
|
return expressionHint(def.$expression);
|
|
235
239
|
}
|
|
236
240
|
if (def.$prototype === "Function") {
|
|
241
|
+
if (Array.isArray(def.body)) {
|
|
242
|
+
return `${def.body.length} statement${def.body.length === 1 ? "" : "s"}`;
|
|
243
|
+
}
|
|
237
244
|
if (def.body) {
|
|
238
245
|
return def.body.length > 20 ? `${def.body.slice(0, 20)}...` : def.body;
|
|
239
246
|
}
|
|
@@ -819,6 +826,22 @@ function renderSignalEditorTemplate(
|
|
|
819
826
|
} else if (cat === "expression") {
|
|
820
827
|
const exprNode = def.$expression || { operator: "=", target: null };
|
|
821
828
|
fields = html`
|
|
829
|
+
<div style="display:flex;align-items:center;gap:4px">
|
|
830
|
+
<span class="field-label" style="flex:1">Expression</span>
|
|
831
|
+
<sp-action-button
|
|
832
|
+
size="xs"
|
|
833
|
+
quiet
|
|
834
|
+
title="Open in formula workspace"
|
|
835
|
+
@click=${() => {
|
|
836
|
+
ctx.updateSession({
|
|
837
|
+
ui: { editingFormula: { defName: name, type: "def" } },
|
|
838
|
+
});
|
|
839
|
+
ctx.renderCanvas();
|
|
840
|
+
}}
|
|
841
|
+
>
|
|
842
|
+
<sp-icon-full-screen slot="icon"></sp-icon-full-screen>
|
|
843
|
+
</sp-action-button>
|
|
844
|
+
</div>
|
|
822
845
|
${renderExpressionEditor(
|
|
823
846
|
exprNode,
|
|
824
847
|
(newNode: unknown) =>
|
|
@@ -828,7 +851,17 @@ function renderSignalEditorTemplate(
|
|
|
828
851
|
),
|
|
829
852
|
{
|
|
830
853
|
allowEventRef: false,
|
|
854
|
+
// Live-context evaluation in the canvas iframe, snapshot fallback (M6). The signals
|
|
855
|
+
// Panel lives in the left panel — re-render it when a fresh live result lands.
|
|
856
|
+
preview: livePreviewExpression(activeTab.value, `def:${name}`, exprNode, null, () =>
|
|
857
|
+
renderOnly("leftPanel"),
|
|
858
|
+
),
|
|
859
|
+
onInsertDef: (defName, vendored) =>
|
|
860
|
+
transactDoc(activeTab.value, (t) =>
|
|
861
|
+
mutateAddDef(t, defName, vendored as Record<string, JsonValue>),
|
|
862
|
+
),
|
|
831
863
|
stateDefs: Object.keys(S.document.state || {}),
|
|
864
|
+
stateEntries: S.document.state || {},
|
|
832
865
|
},
|
|
833
866
|
)}
|
|
834
867
|
`;
|
|
@@ -957,6 +990,42 @@ function renderFunctionFields(
|
|
|
957
990
|
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { description: v || undefined })),
|
|
958
991
|
);
|
|
959
992
|
|
|
993
|
+
// Structured bodies (spec §20) are a body MODE of the function category, not a new entity:
|
|
994
|
+
// "Statements" renders the statement-card editor over `body: JxStatement[]`; "Code" is the
|
|
995
|
+
// Textarea/Monaco path over `body: string`. Switching modes replaces the body with the other
|
|
996
|
+
// Representation's empty seed — an explicit mode change, nothing is converted.
|
|
997
|
+
const bodyIsStatements = Array.isArray(def.body);
|
|
998
|
+
const bodyModeToggle = html`
|
|
999
|
+
<sp-action-group size="s" compact class="body-mode-toggle">
|
|
1000
|
+
<sp-action-button
|
|
1001
|
+
size="s"
|
|
1002
|
+
class="body-mode-statements"
|
|
1003
|
+
?selected=${bodyIsStatements}
|
|
1004
|
+
@click=${() => {
|
|
1005
|
+
if (!bodyIsStatements) {
|
|
1006
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { body: [] }));
|
|
1007
|
+
ctx.renderLeftPanel();
|
|
1008
|
+
}
|
|
1009
|
+
}}
|
|
1010
|
+
>
|
|
1011
|
+
Statements
|
|
1012
|
+
</sp-action-button>
|
|
1013
|
+
<sp-action-button
|
|
1014
|
+
size="s"
|
|
1015
|
+
class="body-mode-code"
|
|
1016
|
+
?selected=${!bodyIsStatements}
|
|
1017
|
+
@click=${() => {
|
|
1018
|
+
if (bodyIsStatements) {
|
|
1019
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { body: "" }));
|
|
1020
|
+
ctx.renderLeftPanel();
|
|
1021
|
+
}
|
|
1022
|
+
}}
|
|
1023
|
+
>
|
|
1024
|
+
Code
|
|
1025
|
+
</sp-action-button>
|
|
1026
|
+
</sp-action-group>
|
|
1027
|
+
`;
|
|
1028
|
+
|
|
960
1029
|
const bodyField = def.$src
|
|
961
1030
|
? html`
|
|
962
1031
|
${signalFieldRow("Source", def.$src || "", (v: string) =>
|
|
@@ -971,29 +1040,52 @@ function renderFunctionFields(
|
|
|
971
1040
|
: html`
|
|
972
1041
|
<div style="display:flex;align-items:center;gap:4px">
|
|
973
1042
|
<span class="field-label" style="flex:1">Body</span>
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1043
|
+
${bodyModeToggle}
|
|
1044
|
+
${bodyIsStatements
|
|
1045
|
+
? nothing
|
|
1046
|
+
: html`
|
|
1047
|
+
<sp-action-button
|
|
1048
|
+
size="xs"
|
|
1049
|
+
quiet
|
|
1050
|
+
title="Open in code editor"
|
|
1051
|
+
@click=${() => {
|
|
1052
|
+
ctx.updateSession({
|
|
1053
|
+
ui: { editingFunction: { defName: name, type: "def" } },
|
|
1054
|
+
});
|
|
1055
|
+
ctx.renderCanvas();
|
|
1056
|
+
}}
|
|
1057
|
+
>
|
|
1058
|
+
<sp-icon-code slot="icon"></sp-icon-code>
|
|
1059
|
+
</sp-action-button>
|
|
1060
|
+
`}
|
|
987
1061
|
</div>
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
1062
|
+
${bodyIsStatements
|
|
1063
|
+
? renderStatementEditor(
|
|
1064
|
+
def.body as JxStatement[],
|
|
1065
|
+
(next) => {
|
|
1066
|
+
transactDoc(activeTab.value, (t) =>
|
|
1067
|
+
mutateUpdateDef(t, name, { body: next as unknown as JsonValue }),
|
|
1068
|
+
);
|
|
1069
|
+
ctx.renderLeftPanel();
|
|
1070
|
+
},
|
|
1071
|
+
{
|
|
1072
|
+
allowEventRef: true,
|
|
1073
|
+
emits: def.emits ?? [],
|
|
1074
|
+
stateDefs: Object.keys(S.document.state || {}),
|
|
1075
|
+
stateEntries: S.document.state || {},
|
|
1076
|
+
},
|
|
1077
|
+
)
|
|
1078
|
+
: html`
|
|
1079
|
+
<textarea
|
|
1080
|
+
class="field-input"
|
|
1081
|
+
style="min-height:60px;font-family:var(--font-mono);font-size:var(--spectrum-font-size-50, 11px)"
|
|
1082
|
+
.value=${typeof def.body === "string" ? def.body : ""}
|
|
1083
|
+
@input=${(e: Event) => {
|
|
1084
|
+
const v = (e.target as HTMLInputElement).value;
|
|
1085
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, name, { body: v }));
|
|
1086
|
+
}}
|
|
1087
|
+
></textarea>
|
|
1088
|
+
`}
|
|
997
1089
|
`;
|
|
998
1090
|
|
|
999
1091
|
return html`
|