@jxsuite/studio 0.23.2 → 0.24.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/studio.js +2230 -714
- package/dist/studio.js.map +121 -104
- package/package.json +8 -7
- package/src/browse/{browse-modal.js → browse-modal.ts} +9 -10
- package/src/browse/{browse.js → browse.ts} +109 -84
- package/src/canvas/{canvas-diff.js → canvas-diff.ts} +42 -35
- package/src/canvas/{canvas-helpers.js → canvas-helpers.ts} +25 -19
- package/src/canvas/{canvas-live-render.js → canvas-live-render.ts} +53 -63
- package/src/canvas/{canvas-render.js → canvas-render.ts} +110 -121
- package/src/canvas/{canvas-utils.js → canvas-utils.ts} +48 -44
- package/src/canvas/{nested-site-style.js → nested-site-style.ts} +3 -3
- package/src/editor/{component-inline-edit.js → component-inline-edit.ts} +45 -33
- package/src/editor/{content-inline-edit.js → content-inline-edit.ts} +27 -45
- package/src/editor/{context-menu.js → context-menu.ts} +38 -36
- package/src/editor/{convert-targets.js → convert-targets.ts} +15 -12
- package/src/editor/{convert-to-component.js → convert-to-component.ts} +25 -26
- package/src/editor/{convert-to-repeater.js → convert-to-repeater.ts} +60 -40
- package/src/editor/{inline-edit.js → inline-edit.ts} +91 -55
- package/src/editor/{inline-format.js → inline-format.ts} +46 -51
- package/src/editor/{insertion-helper.js → insertion-helper.ts} +47 -63
- package/src/editor/{shortcuts.js → shortcuts.ts} +45 -31
- package/src/editor/{slash-menu.js → slash-menu.ts} +34 -35
- package/src/files/{components.js → components.ts} +12 -15
- package/src/files/{file-ops.js → file-ops.ts} +36 -29
- package/src/files/{files.js → files.ts} +102 -84
- package/src/github/{github-auth.js → github-auth.ts} +3 -3
- package/src/github/{github-publish.js → github-publish.ts} +20 -18
- package/src/markdown/{md-allowlist.js → md-allowlist.ts} +5 -2
- package/src/markdown/{md-convert.js → md-convert.ts} +146 -169
- package/src/new-project/{new-project-modal.js → new-project-modal.ts} +16 -18
- package/src/panels/{activity-bar.js → activity-bar.ts} +26 -34
- package/src/panels/{ai-panel.js → ai-panel.ts} +30 -30
- package/src/panels/{block-action-bar.js → block-action-bar.ts} +64 -73
- package/src/panels/{canvas-dnd.js → canvas-dnd.ts} +44 -49
- package/src/panels/{data-explorer.js → data-explorer.ts} +21 -15
- package/src/panels/dnd.ts +417 -0
- package/src/panels/{editors.js → editors.ts} +43 -50
- package/src/panels/{elements-panel.js → elements-panel.ts} +30 -27
- package/src/panels/{events-panel.js → events-panel.ts} +33 -25
- package/src/panels/{git-panel.js → git-panel.ts} +97 -83
- package/src/panels/{head-panel.js → head-panel.ts} +117 -139
- package/src/panels/{imports-panel.js → imports-panel.ts} +69 -89
- package/src/panels/{layers-panel.js → layers-panel.ts} +61 -57
- package/src/panels/{left-panel.js → left-panel.ts} +56 -63
- package/src/panels/{overlays.js → overlays.ts} +28 -36
- package/src/panels/{panel-events.js → panel-events.ts} +53 -51
- package/src/panels/{preview-render.js → preview-render.ts} +20 -15
- package/src/panels/{properties-panel.js → properties-panel.ts} +212 -246
- package/src/panels/{pseudo-preview.js → pseudo-preview.ts} +9 -8
- package/src/panels/{quick-search.js → quick-search.ts} +16 -17
- package/src/panels/{right-panel.js → right-panel.ts} +41 -59
- package/src/panels/{shared.js → shared.ts} +7 -5
- package/src/panels/{signals-panel.js → signals-panel.ts} +322 -362
- package/src/panels/{statusbar.js → statusbar.ts} +14 -14
- package/src/panels/{style-inputs.js → style-inputs.ts} +66 -48
- package/src/panels/{style-panel.js → style-panel.ts} +235 -290
- package/src/panels/{style-utils.js → style-utils.ts} +32 -31
- package/src/panels/{stylebook-layers-panel.js → stylebook-layers-panel.ts} +22 -14
- package/src/panels/{stylebook-panel.js → stylebook-panel.ts} +127 -140
- package/src/panels/{tab-strip.js → tab-strip.ts} +12 -14
- package/src/panels/{toolbar.js → toolbar.ts} +68 -70
- package/src/panels/{welcome-screen.js → welcome-screen.ts} +14 -16
- package/src/{platform.js → platform.ts} +5 -3
- package/src/platforms/{devserver.js → devserver.ts} +53 -44
- package/src/{recent-projects.js → recent-projects.ts} +17 -12
- package/src/{resize-edges.js → resize-edges.ts} +18 -13
- package/src/services/{cem-export.js → cem-export.ts} +14 -7
- package/src/services/{code-services.js → code-services.ts} +29 -20
- package/src/services/{monaco-setup.js → monaco-setup.ts} +2 -3
- package/src/settings/{content-types-editor.js → content-types-editor.ts} +88 -67
- package/src/settings/{css-vars-editor.js → css-vars-editor.ts} +78 -51
- package/src/settings/{defs-editor.js → defs-editor.ts} +70 -56
- package/src/settings/{general-settings.js → general-settings.ts} +29 -28
- package/src/settings/{head-editor.js → head-editor.ts} +37 -35
- package/src/settings/{schema-field-ui.js → schema-field-ui.ts} +86 -76
- package/src/settings/{settings-modal.js → settings-modal.ts} +14 -16
- package/src/{site-context.js → site-context.ts} +35 -32
- package/src/{state.js → state.ts} +95 -78
- package/src/{store.js → store.ts} +60 -63
- package/src/{studio.js → studio.ts} +117 -119
- package/src/tabs/tab.ts +196 -0
- package/src/tabs/{transact.js → transact.ts} +107 -60
- package/src/types.ts +185 -0
- package/src/ui/{button-group.js → button-group.ts} +21 -21
- package/src/ui/{color-selector.js → color-selector.ts} +44 -37
- package/src/ui/{expression-editor.js → expression-editor.ts} +65 -40
- package/src/ui/{field-row.js → field-row.ts} +19 -2
- package/src/ui/{icons.js → icons.ts} +2 -2
- package/src/ui/{layers.js → layers.ts} +33 -24
- package/src/ui/{media-picker.js → media-picker.ts} +13 -9
- package/src/ui/{panel-resize.js → panel-resize.ts} +9 -4
- package/src/ui/{spectrum.js → spectrum.ts} +4 -4
- package/src/ui/{unit-selector.js → unit-selector.ts} +16 -19
- package/src/ui/{value-selector.js → value-selector.ts} +28 -28
- package/src/ui/{widgets.js → widgets.ts} +62 -15
- package/src/utils/{canvas-media.js → canvas-media.ts} +29 -14
- package/src/utils/{edit-display.js → edit-display.ts} +23 -20
- package/src/utils/{google-fonts.js → google-fonts.ts} +14 -13
- package/src/utils/{inherited-style.js → inherited-style.ts} +15 -10
- package/src/utils/{studio-utils.js → studio-utils.ts} +35 -23
- package/src/{view.js → view.ts} +53 -55
- package/src/workspace/{workspace.js → workspace.ts} +44 -33
- package/src/panels/dnd.js +0 -426
- package/src/tabs/tab.js +0 -192
- /package/src/{reactivity.js → reactivity.ts} +0 -0
|
@@ -1,25 +1,25 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
1
2
|
/** Statusbar — status message display for Jx Studio */
|
|
2
3
|
|
|
3
|
-
import { statusbarEl, getNodeAtPath, nodeLabel, updateSession, renderOnly } from "../store
|
|
4
|
-
import { effect, effectScope } from "../reactivity
|
|
5
|
-
import { activeTab } from "../workspace/workspace
|
|
4
|
+
import { statusbarEl, getNodeAtPath, nodeLabel, updateSession, renderOnly } from "../store";
|
|
5
|
+
import { effect, effectScope } from "../reactivity";
|
|
6
|
+
import { activeTab } from "../workspace/workspace";
|
|
7
|
+
import type { JxPath } from "../state";
|
|
6
8
|
|
|
7
9
|
// ─── Module state ────────────────────────────────────────────────────────────
|
|
8
10
|
|
|
9
11
|
let statusMsg = "";
|
|
10
12
|
/** @type {ReturnType<typeof setTimeout> | undefined} */
|
|
11
|
-
let statusTimeout;
|
|
12
|
-
|
|
13
|
-
let
|
|
14
|
-
/** @type {import("@vue/reactivity").EffectScope | null} */
|
|
15
|
-
let _scope = null;
|
|
13
|
+
let statusTimeout: ReturnType<typeof setTimeout> | undefined;
|
|
14
|
+
let _rerender: (() => void) | null = null;
|
|
15
|
+
let _scope: import("@vue/reactivity").EffectScope | null = null;
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Register the callback used to re-render the statusbar. Called once from studio.js during init.
|
|
19
19
|
*
|
|
20
20
|
* @param {() => void} fn
|
|
21
21
|
*/
|
|
22
|
-
export function setStatusbarRenderer(fn) {
|
|
22
|
+
export function setStatusbarRenderer(fn: () => void) {
|
|
23
23
|
_rerender = fn;
|
|
24
24
|
}
|
|
25
25
|
|
|
@@ -51,7 +51,7 @@ export function unmountStatusbar() {
|
|
|
51
51
|
// ─── Statusbar ───────────────────────────────────────────────────────────────
|
|
52
52
|
|
|
53
53
|
/** @param {string} text */
|
|
54
|
-
function esc(text) {
|
|
54
|
+
function esc(text: string) {
|
|
55
55
|
return String(text).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -61,7 +61,7 @@ export function renderStatusbar() {
|
|
|
61
61
|
const parts = [];
|
|
62
62
|
if (tab?.doc.mode === "content") parts.push("Content Mode");
|
|
63
63
|
if (tab?.session.selection?.length) {
|
|
64
|
-
const sel =
|
|
64
|
+
const sel = tab.session.selection as JxPath;
|
|
65
65
|
const node = getNodeAtPath(tab.doc.document, sel);
|
|
66
66
|
parts.push(`Selected: ${esc(nodeLabel(node))}`);
|
|
67
67
|
|
|
@@ -85,8 +85,8 @@ export function renderStatusbar() {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
/** @param {Event} e */
|
|
88
|
-
function _onStatusbarClick(e) {
|
|
89
|
-
const target =
|
|
88
|
+
function _onStatusbarClick(e: Event) {
|
|
89
|
+
const target = e.target as HTMLElement;
|
|
90
90
|
if (!target.classList.contains("sb-path-seg")) return;
|
|
91
91
|
const pathStr = target.dataset.path;
|
|
92
92
|
if (!pathStr) return;
|
|
@@ -105,7 +105,7 @@ function _onStatusbarClick(e) {
|
|
|
105
105
|
* @param {string} msg
|
|
106
106
|
* @param {number} [duration]
|
|
107
107
|
*/
|
|
108
|
-
export function statusMessage(msg, duration = 3000) {
|
|
108
|
+
export function statusMessage(msg: string, duration: number = 3000) {
|
|
109
109
|
statusMsg = msg;
|
|
110
110
|
_rerender?.();
|
|
111
111
|
clearTimeout(statusTimeout);
|
|
@@ -1,19 +1,20 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
1
2
|
/** Style input widgets — keyword, select, combobox, and font renderers for the style panel. */
|
|
2
3
|
|
|
3
4
|
import { html } from "lit-html";
|
|
4
5
|
import { live } from "lit-html/directives/live.js";
|
|
5
|
-
import { debouncedStyleCommit } from "../store
|
|
6
|
-
import { activeTab } from "../workspace/workspace
|
|
7
|
-
import { transactDoc, mutateUpdateStyle } from "../tabs/transact
|
|
8
|
-
import { widgetForType as _widgetForType } from "../ui/widgets
|
|
9
|
-
import { kebabToLabel, friendlyNameToVar, varDisplayName } from "../utils/studio-utils
|
|
6
|
+
import { debouncedStyleCommit } from "../store";
|
|
7
|
+
import { activeTab } from "../workspace/workspace";
|
|
8
|
+
import { transactDoc, mutateUpdateStyle } from "../tabs/transact";
|
|
9
|
+
import { widgetForType as _widgetForType } from "../ui/widgets";
|
|
10
|
+
import { kebabToLabel, friendlyNameToVar, varDisplayName } from "../utils/studio-utils";
|
|
10
11
|
import {
|
|
11
12
|
TYPO_PREVIEW_PROPS,
|
|
12
13
|
currentFontFamily,
|
|
13
14
|
getFontVars,
|
|
14
15
|
getCssInitialMap,
|
|
15
16
|
camelToKebab,
|
|
16
|
-
} from "./style-utils
|
|
17
|
+
} from "./style-utils";
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* Dual-mode keyword input — shared by select (enum) and combobox (examples) widgets.
|
|
@@ -21,16 +22,21 @@ import {
|
|
|
21
22
|
* @param {string[]} options @param {string} prop @param {string} value @param {(value: string) =>
|
|
22
23
|
* void} onChange
|
|
23
24
|
*/
|
|
24
|
-
export function renderKeywordInput(
|
|
25
|
+
export function renderKeywordInput(
|
|
26
|
+
options: string[],
|
|
27
|
+
prop: string,
|
|
28
|
+
value: string,
|
|
29
|
+
onChange: (value: string) => void,
|
|
30
|
+
) {
|
|
25
31
|
const cssInitialMap = getCssInitialMap();
|
|
26
32
|
const isTypoPreview = TYPO_PREVIEW_PROPS.has(prop) || prop === "fontWeight";
|
|
27
33
|
const font = isTypoPreview ? currentFontFamily() : "";
|
|
28
34
|
const cssProp = isTypoPreview ? camelToKebab(prop) : "";
|
|
29
35
|
|
|
30
|
-
const comboOptions = options.map((
|
|
36
|
+
const comboOptions = options.map((v: string) => {
|
|
31
37
|
const label = v.includes("-")
|
|
32
38
|
? kebabToLabel(v)
|
|
33
|
-
: v.replace(/^./, (
|
|
39
|
+
: v.replace(/^./, (c: string) => c.toUpperCase());
|
|
34
40
|
const style = isTypoPreview ? `${cssProp}: ${v};${font ? ` font-family: ${font}` : ""}` : "";
|
|
35
41
|
return { value: v, label, style };
|
|
36
42
|
});
|
|
@@ -40,10 +46,9 @@ export function renderKeywordInput(options, prop, value, onChange) {
|
|
|
40
46
|
.value=${value || ""}
|
|
41
47
|
placeholder=${cssInitialMap.get(prop) || ""}
|
|
42
48
|
.options=${comboOptions}
|
|
43
|
-
@change=${(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
onChange(/** @type {HTMLInputElement} */ (e.target).value),
|
|
49
|
+
@change=${(e: Event) => onChange((e.target as HTMLInputElement).value)}
|
|
50
|
+
@input=${debouncedStyleCommit(`kw:${prop}`, 400, (e: Event) =>
|
|
51
|
+
onChange((e.target as HTMLInputElement).value),
|
|
47
52
|
)}
|
|
48
53
|
></jx-value-selector>`;
|
|
49
54
|
}
|
|
@@ -52,12 +57,20 @@ export function renderKeywordInput(options, prop, value, onChange) {
|
|
|
52
57
|
* @param {{ enum?: string[] }} entry @param {string} prop @param {string} value @param {(value:
|
|
53
58
|
* string) => void} onChange
|
|
54
59
|
*/
|
|
55
|
-
export function renderSelectInput(
|
|
60
|
+
export function renderSelectInput(
|
|
61
|
+
entry: { enum?: string[] },
|
|
62
|
+
prop: string,
|
|
63
|
+
value: string,
|
|
64
|
+
onChange: (value: string) => void,
|
|
65
|
+
) {
|
|
56
66
|
return renderKeywordInput(entry.enum || [], prop, value, onChange);
|
|
57
67
|
}
|
|
58
68
|
|
|
59
69
|
/** @param {{ title: string; value: string }} preset @param {(value: string) => void} onChange */
|
|
60
|
-
function handleFontPresetSelection(
|
|
70
|
+
function handleFontPresetSelection(
|
|
71
|
+
preset: { title: string; value: string },
|
|
72
|
+
onChange: (value: string) => void,
|
|
73
|
+
) {
|
|
61
74
|
const varName = friendlyNameToVar(preset.title, "--font-");
|
|
62
75
|
if (!activeTab.value?.doc.document?.style?.[varName]) {
|
|
63
76
|
transactDoc(activeTab.value, (t) => mutateUpdateStyle(t, [], varName, preset.value));
|
|
@@ -69,7 +82,11 @@ function handleFontPresetSelection(preset, onChange) {
|
|
|
69
82
|
* @param {string} val @param {{ title: string; value: string }[]} presets @param {(value: string)
|
|
70
83
|
* => void} onChange
|
|
71
84
|
*/
|
|
72
|
-
function handleFontSelection(
|
|
85
|
+
function handleFontSelection(
|
|
86
|
+
val: string,
|
|
87
|
+
presets: { title: string; value: string }[],
|
|
88
|
+
onChange: (value: string) => void,
|
|
89
|
+
) {
|
|
73
90
|
if (!val) return;
|
|
74
91
|
if (val.startsWith("__preset__:")) {
|
|
75
92
|
const title = val.slice("__preset__:".length);
|
|
@@ -109,13 +126,16 @@ function handleFontSelection(val, presets, onChange) {
|
|
|
109
126
|
* presets
|
|
110
127
|
* @returns {({ value: string; label: string; style: string } | { divider: true })[]}
|
|
111
128
|
*/
|
|
112
|
-
export function buildFontOptions(
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
129
|
+
export function buildFontOptions(
|
|
130
|
+
fontVars: { name: string; value: string }[],
|
|
131
|
+
presets: { title: string; value: string }[],
|
|
132
|
+
) {
|
|
133
|
+
const opts: ({ value: string; label: string; style: string } | { divider: true })[] =
|
|
134
|
+
fontVars.map((fv) => ({
|
|
135
|
+
value: fv.name,
|
|
136
|
+
label: varDisplayName(fv.name, "--font-"),
|
|
137
|
+
style: `font-family: ${fv.value}`,
|
|
138
|
+
}));
|
|
119
139
|
const unadded = presets.filter(
|
|
120
140
|
(/** @type {{ title: string; value: string }} */ p) =>
|
|
121
141
|
!fontVars.some(
|
|
@@ -142,7 +162,12 @@ export function buildFontOptions(fontVars, presets) {
|
|
|
142
162
|
* }} entry
|
|
143
163
|
* @param {string} prop @param {string} value @param {(value: string) => void} onChange
|
|
144
164
|
*/
|
|
145
|
-
export function renderComboboxInput(
|
|
165
|
+
export function renderComboboxInput(
|
|
166
|
+
entry: { enum?: string[]; examples?: string[]; presets?: { title: string; value: string }[] },
|
|
167
|
+
prop: string,
|
|
168
|
+
value: string,
|
|
169
|
+
onChange: (value: string) => void,
|
|
170
|
+
) {
|
|
146
171
|
const cssInitialMap = getCssInitialMap();
|
|
147
172
|
const fontVars = prop === "fontFamily" ? getFontVars() : [];
|
|
148
173
|
const presets = entry.presets || [];
|
|
@@ -157,10 +182,10 @@ export function renderComboboxInput(entry, prop, value, onChange) {
|
|
|
157
182
|
.value=${comboValue}
|
|
158
183
|
placeholder=${cssInitialMap.get("fontFamily") || ""}
|
|
159
184
|
.options=${fontOptions}
|
|
160
|
-
@change=${(
|
|
161
|
-
handleFontSelection(
|
|
162
|
-
@input=${debouncedStyleCommit("combo:fontFamily", 400, (
|
|
163
|
-
onChange(
|
|
185
|
+
@change=${(e: Event) =>
|
|
186
|
+
handleFontSelection((e.target as HTMLInputElement).value, presets, onChange)}
|
|
187
|
+
@input=${debouncedStyleCommit("combo:fontFamily", 400, (e: Event) =>
|
|
188
|
+
onChange((e.target as HTMLInputElement).value),
|
|
164
189
|
)}
|
|
165
190
|
></jx-value-selector>`;
|
|
166
191
|
}
|
|
@@ -174,8 +199,8 @@ export function renderComboboxInput(entry, prop, value, onChange) {
|
|
|
174
199
|
size="s"
|
|
175
200
|
placeholder=${cssInitialMap.get(prop) || ""}
|
|
176
201
|
.value=${live(value || "")}
|
|
177
|
-
@input=${debouncedStyleCommit(`combo:${prop}`, 400, (
|
|
178
|
-
onChange(
|
|
202
|
+
@input=${debouncedStyleCommit(`combo:${prop}`, 400, (e: Event) =>
|
|
203
|
+
onChange((e.target as HTMLInputElement).value),
|
|
179
204
|
)}
|
|
180
205
|
></sp-textfield>
|
|
181
206
|
`;
|
|
@@ -186,24 +211,17 @@ export function renderComboboxInput(entry, prop, value, onChange) {
|
|
|
186
211
|
* inputs and CSS initial-value placeholders.
|
|
187
212
|
*/
|
|
188
213
|
export function widgetForType(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
214
|
+
type: string,
|
|
215
|
+
entry: Record<string, unknown>,
|
|
216
|
+
prop: string,
|
|
217
|
+
value: string,
|
|
218
|
+
onCommit: (value: string) => void,
|
|
219
|
+
opts: { placeholder?: string } = {},
|
|
195
220
|
) {
|
|
196
221
|
const cssInitialMap = getCssInitialMap();
|
|
197
|
-
return _widgetForType(
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
/** @type {(val: string | number) => void} */ (onCommit),
|
|
203
|
-
{
|
|
204
|
-
placeholder: opts.placeholder || cssInitialMap.get(prop) || "",
|
|
205
|
-
renderSelect: renderSelectInput,
|
|
206
|
-
renderCombobox: renderComboboxInput,
|
|
207
|
-
},
|
|
208
|
-
);
|
|
222
|
+
return _widgetForType(type, entry, prop, value, onCommit as (val: string | number) => void, {
|
|
223
|
+
placeholder: opts.placeholder || cssInitialMap.get(prop) || "",
|
|
224
|
+
renderSelect: renderSelectInput,
|
|
225
|
+
renderCombobox: renderComboboxInput,
|
|
226
|
+
});
|
|
209
227
|
}
|