@jxsuite/studio 0.28.2 → 0.28.4
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 +86144 -83971
- package/dist/studio.js.map +229 -219
- package/package.json +5 -5
- package/src/browse/browse-modal.ts +9 -3
- package/src/browse/browse.ts +139 -82
- package/src/canvas/canvas-diff.ts +35 -18
- package/src/canvas/canvas-helpers.ts +55 -21
- package/src/canvas/canvas-live-render.ts +140 -89
- package/src/canvas/canvas-render.ts +127 -82
- package/src/canvas/canvas-utils.ts +68 -42
- package/src/canvas/nested-site-style.ts +15 -7
- package/src/editor/component-inline-edit.ts +90 -51
- package/src/editor/content-inline-edit.ts +75 -72
- package/src/editor/context-menu.ts +125 -71
- package/src/editor/convert-targets.ts +17 -13
- package/src/editor/convert-to-component.ts +51 -28
- package/src/editor/convert-to-repeater.ts +44 -19
- package/src/editor/inline-edit.ts +107 -52
- package/src/editor/inline-format.ts +128 -60
- package/src/editor/insertion-helper.ts +26 -14
- package/src/editor/shortcuts.ts +89 -43
- package/src/editor/slash-menu.ts +41 -26
- package/src/files/components.ts +9 -7
- package/src/files/file-ops.ts +53 -33
- package/src/files/files.ts +246 -143
- package/src/format/constraints.ts +25 -15
- package/src/format/format-host.ts +33 -10
- package/src/github/github-auth.ts +24 -14
- package/src/github/github-publish.ts +20 -14
- package/src/new-project/new-project-modal.ts +27 -18
- package/src/panels/activity-bar.ts +27 -26
- package/src/panels/ai-panel.ts +100 -44
- package/src/panels/block-action-bar.ts +84 -52
- package/src/panels/canvas-dnd.ts +47 -28
- package/src/panels/data-explorer.ts +24 -11
- package/src/panels/dnd.ts +148 -100
- package/src/panels/editors.ts +54 -37
- package/src/panels/elements-panel.ts +23 -13
- package/src/panels/events-panel.ts +48 -38
- package/src/panels/git-panel.ts +95 -60
- package/src/panels/head-panel.ts +138 -84
- package/src/panels/imports-panel.ts +66 -29
- package/src/panels/layers-panel.ts +80 -36
- package/src/panels/left-panel.ts +86 -53
- package/src/panels/overlays.ts +36 -19
- package/src/panels/panel-events.ts +48 -27
- package/src/panels/panel-scheduler.ts +41 -23
- package/src/panels/preview-render.ts +26 -26
- package/src/panels/properties-panel.ts +155 -118
- package/src/panels/pseudo-preview.ts +31 -15
- package/src/panels/quick-search.ts +28 -13
- package/src/panels/right-panel.ts +35 -24
- package/src/panels/shared.ts +46 -29
- package/src/panels/signals-panel.ts +303 -186
- package/src/panels/statusbar.ts +27 -12
- package/src/panels/style-inputs.ts +30 -24
- package/src/panels/style-panel.ts +130 -90
- package/src/panels/style-utils.ts +63 -23
- package/src/panels/stylebook-layers-panel.ts +27 -30
- package/src/panels/stylebook-panel.ts +140 -72
- package/src/panels/tab-strip.ts +21 -10
- package/src/panels/toolbar.ts +52 -40
- package/src/panels/welcome-screen.ts +1 -1
- package/src/platform.ts +2 -1
- package/src/platforms/devserver.ts +221 -105
- package/src/recent-projects.ts +15 -7
- package/src/resize-edges.ts +7 -5
- package/src/services/cem-export.ts +73 -57
- package/src/services/code-services.ts +52 -25
- package/src/services/monaco-setup.ts +5 -5
- package/src/settings/content-types-editor.ts +133 -62
- package/src/settings/css-vars-editor.ts +31 -14
- package/src/settings/defs-editor.ts +125 -63
- package/src/settings/general-settings.ts +11 -6
- package/src/settings/head-editor.ts +30 -15
- package/src/settings/schema-field-ui.ts +75 -35
- package/src/settings/settings-modal.ts +35 -17
- package/src/site-context.ts +80 -47
- package/src/state.ts +98 -65
- package/src/store.ts +42 -23
- package/src/studio.ts +165 -144
- package/src/tabs/tab.ts +51 -45
- package/src/tabs/transact.ts +230 -109
- package/src/types.ts +60 -51
- package/src/ui/button-group.ts +3 -2
- package/src/ui/color-selector.ts +33 -15
- package/src/ui/expression-editor.ts +139 -86
- package/src/ui/field-input.ts +35 -18
- package/src/ui/field-row.ts +1 -1
- package/src/ui/icons.ts +5 -6
- package/src/ui/layers.ts +33 -26
- package/src/ui/media-picker.ts +13 -7
- package/src/ui/panel-resize.ts +39 -20
- package/src/ui/spectrum.ts +4 -2
- package/src/ui/unit-selector.ts +20 -11
- package/src/ui/value-selector.ts +13 -7
- package/src/ui/widgets.ts +34 -18
- package/src/utils/canvas-media.ts +66 -33
- package/src/utils/edit-display.ts +43 -44
- package/src/utils/google-fonts.ts +10 -6
- package/src/utils/inherited-style.ts +22 -8
- package/src/utils/studio-utils.ts +88 -45
- package/src/view.ts +9 -5
- package/src/workspace/workspace.ts +49 -29
package/src/types.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
/// <reference lib="dom" />
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
JsonValue as SchemaJsonValue,
|
|
4
|
+
JxMutableNode,
|
|
5
|
+
JxPath,
|
|
6
|
+
ProjectConfig,
|
|
7
|
+
} from "@jxsuite/schema/types";
|
|
3
8
|
|
|
4
9
|
// ─── Git & Platform Types ───────────────────────────────────────────────────
|
|
5
10
|
|
|
@@ -34,7 +39,7 @@ export interface ComponentMeta {
|
|
|
34
39
|
tagName: string;
|
|
35
40
|
$id?: string | null;
|
|
36
41
|
path: string;
|
|
37
|
-
props?: { name: string; type?: string; default?: unknown }[];
|
|
42
|
+
props?: { name: string; type?: string; default?: JsonValue; [k: string]: unknown }[];
|
|
38
43
|
hasElements?: boolean;
|
|
39
44
|
}
|
|
40
45
|
|
|
@@ -60,12 +65,12 @@ export interface DirEntry {
|
|
|
60
65
|
export interface StudioPlatform {
|
|
61
66
|
id: string;
|
|
62
67
|
projectRoot: string;
|
|
63
|
-
activate(root?: string)
|
|
64
|
-
openProject()
|
|
68
|
+
activate: (root?: string) => Promise<void>;
|
|
69
|
+
openProject: () => Promise<{
|
|
65
70
|
config: ProjectConfig;
|
|
66
71
|
handle: { root: string; name: string; projectConfig: ProjectConfig };
|
|
67
72
|
} | null>;
|
|
68
|
-
probeRootProject()
|
|
73
|
+
probeRootProject: () => Promise<{
|
|
69
74
|
meta: { root: string; name: string };
|
|
70
75
|
info: {
|
|
71
76
|
isSiteProject: boolean;
|
|
@@ -73,60 +78,60 @@ export interface StudioPlatform {
|
|
|
73
78
|
directories?: string[];
|
|
74
79
|
};
|
|
75
80
|
} | null>;
|
|
76
|
-
listDirectory(dir: string)
|
|
77
|
-
readFile(path: string)
|
|
78
|
-
writeFile(path: string, content: string)
|
|
79
|
-
uploadFile(path: string, data: string | File | Blob | ArrayBuffer)
|
|
80
|
-
deleteFile(path: string)
|
|
81
|
-
renameFile(from: string, to: string)
|
|
82
|
-
createDirectory(path: string)
|
|
83
|
-
discoverComponents(dir?: string)
|
|
84
|
-
addPackage(name: string)
|
|
85
|
-
removePackage(name: string)
|
|
86
|
-
listPackages()
|
|
87
|
-
codeService(action: string, payload: unknown)
|
|
88
|
-
resolveSiteContext(filePath: string)
|
|
81
|
+
listDirectory: (dir: string) => Promise<DirEntry[]>;
|
|
82
|
+
readFile: (path: string) => Promise<string>;
|
|
83
|
+
writeFile: (path: string, content: string) => Promise<void>;
|
|
84
|
+
uploadFile: (path: string, data: string | File | Blob | ArrayBuffer) => Promise<unknown>;
|
|
85
|
+
deleteFile: (path: string) => Promise<void>;
|
|
86
|
+
renameFile: (from: string, to: string) => Promise<void>;
|
|
87
|
+
createDirectory: (path: string) => Promise<void>;
|
|
88
|
+
discoverComponents: (dir?: string) => Promise<ComponentMeta[]>;
|
|
89
|
+
addPackage: (name: string) => Promise<unknown>;
|
|
90
|
+
removePackage: (name: string) => Promise<unknown>;
|
|
91
|
+
listPackages: () => Promise<PackageInfo[]>;
|
|
92
|
+
codeService: (action: string, payload: unknown) => Promise<CodeServiceResult | null>;
|
|
93
|
+
resolveSiteContext: (filePath: string) => Promise<{
|
|
89
94
|
sitePath: string | null;
|
|
90
95
|
projectConfig?: ProjectConfig;
|
|
91
96
|
fileRelPath?: string;
|
|
92
97
|
}>;
|
|
93
|
-
locateFile(name: string)
|
|
94
|
-
searchFiles(query: string, extensions?: string[])
|
|
98
|
+
locateFile: (name: string) => Promise<string | null>;
|
|
99
|
+
searchFiles: (query: string, extensions?: string[]) => Promise<DirEntry[]>;
|
|
95
100
|
/** List the project's registered format classes (auto-discovered from imports). */
|
|
96
|
-
listFormats
|
|
101
|
+
listFormats?: () => Promise<unknown[]>;
|
|
97
102
|
/** Invoke a format capability (parse/serialize) — { format, action, source?, doc?, options? }. */
|
|
98
|
-
formatAction
|
|
99
|
-
fetchPluginSchema(src: string, prototype?: string, base?: string)
|
|
100
|
-
gitStatus()
|
|
101
|
-
gitBranches()
|
|
102
|
-
gitLog(limit?: number)
|
|
103
|
-
gitStage(files: string[])
|
|
104
|
-
gitUnstage(files: string[])
|
|
105
|
-
gitCommit(message: string)
|
|
106
|
-
gitPush(opts?: { setUpstream?: boolean })
|
|
107
|
-
gitPull()
|
|
108
|
-
gitFetch()
|
|
109
|
-
gitCheckout(branch: string)
|
|
110
|
-
gitCreateBranch(name: string)
|
|
111
|
-
gitDiff(path?: string)
|
|
112
|
-
gitShow(opts: { path: string; ref?: string })
|
|
113
|
-
gitDiscard(files: string[])
|
|
114
|
-
gitClone
|
|
115
|
-
gitInit()
|
|
116
|
-
gitAddRemote(name: string, url: string)
|
|
117
|
-
createProject(opts: {
|
|
103
|
+
formatAction?: (payload: Record<string, unknown>) => Promise<unknown>;
|
|
104
|
+
fetchPluginSchema: (src: string, prototype?: string, base?: string) => Promise<unknown>;
|
|
105
|
+
gitStatus: () => Promise<GitStatusResult>;
|
|
106
|
+
gitBranches: () => Promise<GitBranchesResult>;
|
|
107
|
+
gitLog: (limit?: number) => Promise<GitLogEntry[]>;
|
|
108
|
+
gitStage: (files: string[]) => Promise<void>;
|
|
109
|
+
gitUnstage: (files: string[]) => Promise<void>;
|
|
110
|
+
gitCommit: (message: string) => Promise<void>;
|
|
111
|
+
gitPush: (opts?: { setUpstream?: boolean }) => Promise<void>;
|
|
112
|
+
gitPull: () => Promise<void>;
|
|
113
|
+
gitFetch: () => Promise<void>;
|
|
114
|
+
gitCheckout: (branch: string) => Promise<void>;
|
|
115
|
+
gitCreateBranch: (name: string) => Promise<void>;
|
|
116
|
+
gitDiff: (path?: string) => Promise<string>;
|
|
117
|
+
gitShow: (opts: { path: string; ref?: string }) => Promise<string>;
|
|
118
|
+
gitDiscard: (files: string[]) => Promise<void>;
|
|
119
|
+
gitClone?: (url: string) => Promise<{ ok: boolean; root: string }>;
|
|
120
|
+
gitInit: () => Promise<void>;
|
|
121
|
+
gitAddRemote: (name: string, url: string) => Promise<void>;
|
|
122
|
+
createProject: (opts: {
|
|
118
123
|
name: string;
|
|
119
124
|
description?: string;
|
|
120
125
|
url?: string;
|
|
121
126
|
adapter?: string;
|
|
122
127
|
directory: string;
|
|
123
|
-
})
|
|
124
|
-
aiAuthStatus()
|
|
125
|
-
aiCreateSession(opts: { message: string; systemPrompt?: string })
|
|
126
|
-
aiSendMessage(id: string, message: string)
|
|
127
|
-
aiStreamUrl(id: string)
|
|
128
|
-
aiStopSession(id: string)
|
|
129
|
-
aiDeleteSession(id: string)
|
|
128
|
+
}) => Promise<{ root: string; config: ProjectConfig }>;
|
|
129
|
+
aiAuthStatus: () => Promise<{ authenticated: boolean; error?: string }>;
|
|
130
|
+
aiCreateSession: (opts: { message: string; systemPrompt?: string }) => Promise<{ id: string }>;
|
|
131
|
+
aiSendMessage: (id: string, message: string) => Promise<void>;
|
|
132
|
+
aiStreamUrl: (id: string) => string | Promise<string>;
|
|
133
|
+
aiStopSession: (id: string) => Promise<void>;
|
|
134
|
+
aiDeleteSession: (id: string) => Promise<void>;
|
|
130
135
|
}
|
|
131
136
|
|
|
132
137
|
// ─── Studio Types ───────────────────────────────────────────────────────────
|
|
@@ -167,8 +172,8 @@ export interface GitDiffState {
|
|
|
167
172
|
originalContent: string;
|
|
168
173
|
currentContent: string;
|
|
169
174
|
fileStatus: string;
|
|
170
|
-
originalDoc?:
|
|
171
|
-
currentDoc?:
|
|
175
|
+
originalDoc?: JxMutableNode;
|
|
176
|
+
currentDoc?: JxMutableNode;
|
|
172
177
|
original?: unknown;
|
|
173
178
|
}
|
|
174
179
|
|
|
@@ -191,4 +196,8 @@ export interface ProjectState {
|
|
|
191
196
|
[key: string]: unknown;
|
|
192
197
|
}
|
|
193
198
|
|
|
194
|
-
|
|
199
|
+
/**
|
|
200
|
+
* A JSON document value, or `undefined` to signal property removal in the mutators. Re-uses the
|
|
201
|
+
* schema's precise recursive JSON model.
|
|
202
|
+
*/
|
|
203
|
+
export type JsonValue = SchemaJsonValue | undefined;
|
package/src/ui/button-group.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { html, nothing } from "lit-html";
|
|
10
10
|
import { classMap } from "lit-html/directives/class-map.js";
|
|
11
11
|
import { abbreviateValue, kebabToLabel } from "../utils/studio-utils";
|
|
12
|
-
import icons from "./icons";
|
|
12
|
+
import { icons } from "./icons";
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Render a button group widget with optional overflow menu.
|
|
@@ -74,8 +74,9 @@ export function renderButtonGroup(
|
|
|
74
74
|
<sp-popover>
|
|
75
75
|
<sp-menu
|
|
76
76
|
@change=${(e: Event) => {
|
|
77
|
-
if ((e.target as HTMLInputElement).value)
|
|
77
|
+
if ((e.target as HTMLInputElement).value) {
|
|
78
78
|
onChange((e.target as HTMLInputElement).value);
|
|
79
|
+
}
|
|
79
80
|
}}
|
|
80
81
|
>
|
|
81
82
|
<sp-menu-item value="__none__">—</sp-menu-item>
|
package/src/ui/color-selector.ts
CHANGED
|
@@ -29,7 +29,9 @@ interface ColorVar {
|
|
|
29
29
|
/** Extract --color-* CSS custom properties from the effective (site + document) style. */
|
|
30
30
|
function getColorVars() {
|
|
31
31
|
const style = getEffectiveStyle(activeTab.value?.doc.document?.style);
|
|
32
|
-
if (!style)
|
|
32
|
+
if (!style) {
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
33
35
|
const vars = [];
|
|
34
36
|
for (const [k, v] of Object.entries(style)) {
|
|
35
37
|
if (k.startsWith("--color") && (typeof v === "string" || typeof v === "number")) {
|
|
@@ -49,27 +51,37 @@ function varToLabel(name: string) {
|
|
|
49
51
|
|
|
50
52
|
/** Resolve a color value for display — if it's a var() reference, look up the actual color. */
|
|
51
53
|
function resolveColorForDisplay(val: string | number | undefined) {
|
|
52
|
-
if (!val)
|
|
54
|
+
if (!val) {
|
|
55
|
+
return "transparent";
|
|
56
|
+
}
|
|
53
57
|
const s = String(val);
|
|
54
58
|
const m = s.match(/^var\((--[^)]+)\)$/);
|
|
55
59
|
if (m) {
|
|
56
60
|
const style = getEffectiveStyle(activeTab.value?.doc.document?.style);
|
|
57
61
|
const resolved = style?.[m[1]];
|
|
58
|
-
if (typeof resolved === "string")
|
|
62
|
+
if (typeof resolved === "string") {
|
|
63
|
+
return resolved;
|
|
64
|
+
}
|
|
59
65
|
return "transparent";
|
|
60
66
|
}
|
|
61
67
|
return s;
|
|
62
68
|
}
|
|
63
69
|
|
|
64
70
|
function safeColor(val: string | number | undefined) {
|
|
65
|
-
if (!val)
|
|
71
|
+
if (!val) {
|
|
72
|
+
return "transparent";
|
|
73
|
+
}
|
|
66
74
|
return resolveColorForDisplay(val);
|
|
67
75
|
}
|
|
68
76
|
|
|
69
77
|
/** Normalize a color string to include # prefix for hex values. */
|
|
70
78
|
function normalizeHex(c: string) {
|
|
71
|
-
if (!c)
|
|
72
|
-
|
|
79
|
+
if (!c) {
|
|
80
|
+
return c;
|
|
81
|
+
}
|
|
82
|
+
if (c.startsWith("var(") || c.startsWith("rgb") || c.startsWith("hsl")) {
|
|
83
|
+
return c;
|
|
84
|
+
}
|
|
73
85
|
return c.replace(/^#?/, "#");
|
|
74
86
|
}
|
|
75
87
|
|
|
@@ -83,9 +95,13 @@ function matchesColorVar(
|
|
|
83
95
|
value: string | number | undefined,
|
|
84
96
|
colorVars: { name: string; value: string }[],
|
|
85
97
|
) {
|
|
86
|
-
if (!value || typeof value !== "string")
|
|
98
|
+
if (!value || typeof value !== "string") {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
87
101
|
const m = value.match(/^var\((--[^)]+)\)$/);
|
|
88
|
-
if (!m)
|
|
102
|
+
if (!m) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
89
105
|
return colorVars.find((cv) => cv.name === m[1]) || null;
|
|
90
106
|
}
|
|
91
107
|
|
|
@@ -94,8 +110,8 @@ function matchesColorVar(
|
|
|
94
110
|
export class JxColorPopover extends LitElement {
|
|
95
111
|
static properties = {
|
|
96
112
|
color: { type: String },
|
|
97
|
-
displayColor: { type: String, attribute: false },
|
|
98
113
|
colorVars: { attribute: false },
|
|
114
|
+
displayColor: { attribute: false, type: String },
|
|
99
115
|
};
|
|
100
116
|
|
|
101
117
|
declare color: string;
|
|
@@ -132,29 +148,31 @@ export class JxColorPopover extends LitElement {
|
|
|
132
148
|
const color = normalizeHex(String((e.target as HTMLElement & { color: string }).color));
|
|
133
149
|
this.displayColor = color;
|
|
134
150
|
this.color = color;
|
|
135
|
-
this.dispatchEvent(new CustomEvent("color-change", {
|
|
151
|
+
this.dispatchEvent(new CustomEvent("color-change", { bubbles: true, detail: color }));
|
|
136
152
|
}
|
|
137
153
|
|
|
138
154
|
_handleSlider(e: Event) {
|
|
139
155
|
const color = normalizeHex(String((e.target as HTMLElement & { color: string }).color));
|
|
140
156
|
this.displayColor = color;
|
|
141
157
|
this.color = color;
|
|
142
|
-
this.dispatchEvent(new CustomEvent("color-change", {
|
|
158
|
+
this.dispatchEvent(new CustomEvent("color-change", { bubbles: true, detail: color }));
|
|
143
159
|
}
|
|
144
160
|
|
|
145
161
|
_handleText(e: Event) {
|
|
146
162
|
const val = (e.target as HTMLInputElement).value.trim();
|
|
147
|
-
if (!val)
|
|
163
|
+
if (!val) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
148
166
|
this.displayColor = val;
|
|
149
167
|
this.color = val;
|
|
150
|
-
this.dispatchEvent(new CustomEvent("color-change", {
|
|
168
|
+
this.dispatchEvent(new CustomEvent("color-change", { bubbles: true, detail: val }));
|
|
151
169
|
}
|
|
152
170
|
|
|
153
171
|
_handleSwatch(e: Event, varName: string) {
|
|
154
172
|
e.stopPropagation();
|
|
155
173
|
const varRef = `var(${varName})`;
|
|
156
174
|
this.color = varRef;
|
|
157
|
-
this.dispatchEvent(new CustomEvent("color-change", {
|
|
175
|
+
this.dispatchEvent(new CustomEvent("color-change", { bubbles: true, detail: varRef }));
|
|
158
176
|
}
|
|
159
177
|
|
|
160
178
|
render() {
|
|
@@ -306,5 +324,5 @@ export function renderColorSelector(
|
|
|
306
324
|
|
|
307
325
|
/** Whether any color popover is currently open. */
|
|
308
326
|
export function isColorPopoverOpen() {
|
|
309
|
-
return
|
|
327
|
+
return Boolean(document.querySelector(".style-input-color sp-overlay[open]"));
|
|
310
328
|
}
|