@jxsuite/studio 0.13.0 → 0.15.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 +467 -625
- package/dist/studio.js.map +37 -37
- package/package.json +1 -1
- package/src/canvas/canvas-live-render.js +25 -0
- package/src/canvas/canvas-render.js +20 -2
- package/src/canvas/canvas-utils.js +1 -2
- package/src/editor/component-inline-edit.js +1 -3
- package/src/editor/content-inline-edit.js +1 -3
- package/src/editor/context-menu.js +73 -35
- package/src/editor/insertion-helper.js +0 -1
- package/src/editor/shortcuts.js +39 -45
- package/src/files/file-ops.js +57 -108
- package/src/files/files.js +13 -8
- package/src/panels/activity-bar.js +6 -4
- package/src/panels/canvas-dnd.js +4 -10
- package/src/panels/dnd.js +45 -7
- package/src/panels/editors.js +14 -16
- package/src/panels/elements-panel.js +13 -13
- package/src/panels/git-panel.js +2 -1
- package/src/panels/layers-panel.js +11 -12
- package/src/panels/left-panel.js +2 -2
- package/src/panels/panel-events.js +19 -25
- package/src/panels/preview-render.js +7 -3
- package/src/panels/pseudo-preview.js +9 -8
- package/src/panels/statusbar.js +8 -16
- package/src/panels/style-inputs.js +2 -3
- package/src/panels/style-utils.js +8 -6
- package/src/panels/stylebook-layers-panel.js +5 -5
- package/src/panels/stylebook-panel.js +16 -16
- package/src/panels/toolbar.js +2 -2
- package/src/state.js +2 -3
- package/src/store.js +2 -133
- package/src/studio.js +111 -239
- package/src/tabs/tab.js +19 -4
- package/src/tabs/transact.js +19 -1
- package/src/ui/color-selector.js +4 -5
- package/src/view.js +3 -0
- package/src/workspace/workspace.js +5 -0
package/src/state.js
CHANGED
|
@@ -211,7 +211,6 @@ export function createState(doc) {
|
|
|
211
211
|
mode: "component", // 'component' | 'content'
|
|
212
212
|
content: { frontmatter: {} }, // frontmatter metadata for .md files
|
|
213
213
|
ui: {
|
|
214
|
-
leftTab: "layers", // 'files' | 'layers' | 'blocks' | 'state' | 'data'
|
|
215
214
|
rightTab: "properties", // 'properties' | 'events' | 'style'
|
|
216
215
|
zoom: 1,
|
|
217
216
|
activeMedia: null, // '--md' | null (base) — focused canvas/breakpoint
|
|
@@ -377,7 +376,7 @@ export function pushDocument(state, doc, documentPath) {
|
|
|
377
376
|
const newState = createState(doc);
|
|
378
377
|
newState.documentStack = [...(state.documentStack || []), frame];
|
|
379
378
|
newState.documentPath = documentPath;
|
|
380
|
-
newState.ui = { ...state.ui,
|
|
379
|
+
newState.ui = { ...state.ui, activeMedia: null, activeSelector: null };
|
|
381
380
|
return newState;
|
|
382
381
|
}
|
|
383
382
|
|
|
@@ -395,6 +394,6 @@ export function popDocument(state) {
|
|
|
395
394
|
...state,
|
|
396
395
|
...frame,
|
|
397
396
|
documentStack: stack,
|
|
398
|
-
ui: { ...state.ui
|
|
397
|
+
ui: { ...state.ui },
|
|
399
398
|
};
|
|
400
399
|
}
|
package/src/store.js
CHANGED
|
@@ -12,10 +12,6 @@ import { activeTab } from "./workspace/workspace.js";
|
|
|
12
12
|
|
|
13
13
|
export {
|
|
14
14
|
createState,
|
|
15
|
-
selectNode,
|
|
16
|
-
hoverNode,
|
|
17
|
-
pushDocument,
|
|
18
|
-
popDocument,
|
|
19
15
|
getNodeAtPath,
|
|
20
16
|
flattenTree,
|
|
21
17
|
nodeLabel,
|
|
@@ -27,8 +23,6 @@ export {
|
|
|
27
23
|
projectState,
|
|
28
24
|
setProjectState,
|
|
29
25
|
updateFrontmatter,
|
|
30
|
-
toFlat,
|
|
31
|
-
fromFlat,
|
|
32
26
|
} from "./state.js";
|
|
33
27
|
|
|
34
28
|
// ─── DOM shortcuts & element refs ────────────────────────────────────────────
|
|
@@ -213,85 +207,7 @@ export function renderOnly(...names) {
|
|
|
213
207
|
}
|
|
214
208
|
}
|
|
215
209
|
|
|
216
|
-
// ───
|
|
217
|
-
// studio.js registers the real update implementation via setUpdateFn() during bootstrap.
|
|
218
|
-
// This allows extracted modules to import `update` from store.js without circular deps.
|
|
219
|
-
|
|
220
|
-
/** @type {(state: import("./state.js").StudioState) => void} */
|
|
221
|
-
let _updateFn = () => {
|
|
222
|
-
throw new Error("update() called before setUpdateFn() — bootstrap not complete");
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
/** @type {() => import("./state.js").StudioState | null} */
|
|
226
|
-
let _getStateFn = () => null;
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Register the update implementation. Called by studio.js at module load time.
|
|
230
|
-
*
|
|
231
|
-
* @param {(state: import("./state.js").StudioState) => void} fn
|
|
232
|
-
*/
|
|
233
|
-
export function setUpdateFn(fn) {
|
|
234
|
-
_updateFn = fn;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* Register the state getter. Called by studio.js at module load time.
|
|
239
|
-
*
|
|
240
|
-
* @param {() => import("./state.js").StudioState} fn — returns current S
|
|
241
|
-
*/
|
|
242
|
-
export function setGetStateFn(fn) {
|
|
243
|
-
_getStateFn = fn;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* Get the current state (live, not stale). Synthesized from the active tab's reactive state.
|
|
248
|
-
*
|
|
249
|
-
* @returns {import("./state.js").StudioState}
|
|
250
|
-
*/
|
|
251
|
-
export function getState() {
|
|
252
|
-
const tab = activeTab.value;
|
|
253
|
-
if (tab) {
|
|
254
|
-
return /** @type {any} */ ({
|
|
255
|
-
document: tab.doc.document,
|
|
256
|
-
mode: tab.doc.mode,
|
|
257
|
-
dirty: tab.doc.dirty,
|
|
258
|
-
handlersSource: tab.doc.handlersSource,
|
|
259
|
-
content: tab.doc.content,
|
|
260
|
-
documentPath: tab.documentPath,
|
|
261
|
-
fileHandle: tab.fileHandle,
|
|
262
|
-
selection: tab.session.selection,
|
|
263
|
-
hover: tab.session.hover,
|
|
264
|
-
clipboard: tab.session.clipboard,
|
|
265
|
-
ui: tab.session.ui,
|
|
266
|
-
canvas: tab.session.canvas,
|
|
267
|
-
documentStack: tab.session.documentStack,
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
|
-
return /** @type {any} */ (_getStateFn());
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* Dispatch a state update + selective re-render.
|
|
275
|
-
*
|
|
276
|
-
* @param {import("./state.js").StudioState} newState
|
|
277
|
-
*/
|
|
278
|
-
export function update(newState) {
|
|
279
|
-
_updateFn(newState);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// ─── Session dispatch (late-bound) ──────────────────────────────────────────
|
|
283
|
-
// Lightweight dispatcher for session-only changes (selection, hover, ui).
|
|
284
|
-
// Does NOT trigger autosave middleware or push history.
|
|
285
|
-
|
|
286
|
-
/** @type {(patch: object) => void} */
|
|
287
|
-
let _updateSessionFn = () => {
|
|
288
|
-
throw new Error("updateSession() called before setUpdateSessionFn() — bootstrap not complete");
|
|
289
|
-
};
|
|
290
|
-
|
|
291
|
-
/** @param {(patch: object) => void} fn */
|
|
292
|
-
export function setUpdateSessionFn(fn) {
|
|
293
|
-
_updateSessionFn = fn;
|
|
294
|
-
}
|
|
210
|
+
// ─── Session dispatch ──────────────────────────────────────────────────────
|
|
295
211
|
|
|
296
212
|
/**
|
|
297
213
|
* Dispatch a session-only state update (selection, hover, ui). Writes directly to reactive tab.
|
|
@@ -316,11 +232,10 @@ export function updateSession(patch) {
|
|
|
316
232
|
}
|
|
317
233
|
}
|
|
318
234
|
}
|
|
319
|
-
_updateSessionFn(patch);
|
|
320
235
|
}
|
|
321
236
|
|
|
322
237
|
/**
|
|
323
|
-
* Update a single UI field.
|
|
238
|
+
* Update a single UI field.
|
|
324
239
|
*
|
|
325
240
|
* @param {string} field
|
|
326
241
|
* @param {unknown} value
|
|
@@ -330,7 +245,6 @@ export function updateUi(field, value) {
|
|
|
330
245
|
if (tab) {
|
|
331
246
|
/** @type {any} */ (tab.session.ui)[field] = value;
|
|
332
247
|
}
|
|
333
|
-
_updateSessionFn({ ui: { [field]: value } });
|
|
334
248
|
}
|
|
335
249
|
|
|
336
250
|
/**
|
|
@@ -345,49 +259,4 @@ export function updateCanvas(patch) {
|
|
|
345
259
|
/** @type {any} */ (tab.session.canvas)[k] = v;
|
|
346
260
|
}
|
|
347
261
|
}
|
|
348
|
-
_updateSessionFn({ canvas: patch });
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
/** @type {((state: import("./state.js").StudioState) => void)[]} */
|
|
352
|
-
const _updateMiddleware = [];
|
|
353
|
-
|
|
354
|
-
/**
|
|
355
|
-
* Register middleware that runs after every update().
|
|
356
|
-
*
|
|
357
|
-
* @param {(state: import("./state.js").StudioState) => void} fn — receives (state) after core
|
|
358
|
-
* update
|
|
359
|
-
*/
|
|
360
|
-
export function addUpdateMiddleware(fn) {
|
|
361
|
-
_updateMiddleware.push(fn);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
/**
|
|
365
|
-
* Run all registered update middleware.
|
|
366
|
-
*
|
|
367
|
-
* @param {import("./state.js").StudioState} state
|
|
368
|
-
*/
|
|
369
|
-
export function runUpdateMiddleware(state) {
|
|
370
|
-
for (const mw of _updateMiddleware) mw(state);
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
/** @type {((prevDoc: object, prevSel: import("./state.js").JxPath | null) => void)[]} */
|
|
374
|
-
const _postRenderHooks = [];
|
|
375
|
-
|
|
376
|
-
/**
|
|
377
|
-
* Register a hook that runs after renders in update().
|
|
378
|
-
*
|
|
379
|
-
* @param {(prevDoc: object, prevSel: import("./state.js").JxPath | null) => void} fn
|
|
380
|
-
*/
|
|
381
|
-
export function addPostRenderHook(fn) {
|
|
382
|
-
_postRenderHooks.push(fn);
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
/**
|
|
386
|
-
* Run all registered post-render hooks.
|
|
387
|
-
*
|
|
388
|
-
* @param {object} prevDoc
|
|
389
|
-
* @param {import("./state.js").JxPath | null} prevSel
|
|
390
|
-
*/
|
|
391
|
-
export function runPostRenderHooks(prevDoc, prevSel) {
|
|
392
|
-
for (const hook of _postRenderHooks) hook(prevDoc, prevSel);
|
|
393
262
|
}
|