@jxsuite/studio 2.3.0 → 2.4.1
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/chunks/{content-source-56xpvx83.js → content-source-cn9te96r.js} +8 -8
- package/dist/chunks/{convert-to-repeater-0xh9wwek.js → convert-to-repeater-65gjgdst.js} +7 -7
- package/dist/chunks/{extension-sections-g34239vm.js → extension-sections-mdgmqrry.js} +11 -11
- package/dist/chunks/{files-gkz202dp.js → files-dsh5g8j4.js} +12 -12
- package/dist/chunks/{format-host-pej3srnw.js → format-host-m9h45a79.js} +2 -2
- package/dist/chunks/{git-panel-4j6xbh8g.js → git-panel-rfs8pqjj.js} +7 -7
- package/dist/chunks/{layers-panel-8mvn8sgd.js → layers-panel-6cj5nf6a.js} +10 -10
- package/dist/chunks/{publish-panel-ptddc3kg.js → publish-panel-b0xh7b4y.js} +5 -5
- package/dist/chunks/{quick-search-j88azfs2.js → quick-search-a83fhnsh.js} +13 -13
- package/dist/chunks/{right-panel-egkaxy89.js → right-panel-hrw5kdh5.js} +9 -9
- package/dist/chunks/{studio-4058pg09.js → studio-0svvdm0a.js} +4 -4
- package/dist/chunks/{studio-5amdrjm4.js → studio-1d6bm7eg.js} +7 -7
- package/dist/chunks/{studio-50eed4c9.js → studio-40fm3hyr.js} +2 -2
- package/dist/chunks/{studio-0e4h32g6.js → studio-4m39t01b.js} +5 -5
- package/dist/chunks/{studio-5ne8mdx9.js → studio-675v08qj.js} +2 -2
- package/dist/chunks/{studio-cf4rk7kv.js → studio-91sdrn9x.js} +2 -2
- package/dist/chunks/{studio-bak2cyjr.js → studio-9sxn0eaa.js} +4 -4
- package/dist/chunks/{studio-3q65xvzv.js → studio-d1f2rqxh.js} +4 -4
- package/dist/chunks/{studio-a11d3a1b.js → studio-gfzyxa0m.js} +5 -5
- package/dist/chunks/{studio-x3etxs0s.js → studio-gqpbrrj5.js} +8 -8
- package/dist/chunks/{studio-10s469da.js → studio-h6553a8h.js} +71 -22
- package/dist/chunks/{studio-ncnet0ba.js → studio-jand3kjg.js} +10 -10
- package/dist/chunks/{studio-hk523hby.js → studio-kfq9ed73.js} +3 -3
- package/dist/chunks/{studio-hs8x23fv.js → studio-n9k15qdg.js} +8 -8
- package/dist/chunks/{studio-yxzgjq8q.js → studio-qb6vy1z1.js} +8 -8
- package/dist/chunks/{studio-vdpcpada.js → studio-qymkxbcq.js} +3 -3
- package/dist/chunks/{studio-zdkgwhkv.js → studio-rkr6pm84.js} +3 -3
- package/dist/chunks/{studio-cv606rs1.js → studio-rz861p2b.js} +5 -5
- package/dist/chunks/{studio-4enps87v.js → studio-tdt7b6qb.js} +6 -6
- package/dist/iframe-entry.js +73 -9
- package/dist/studio.js +46 -34
- package/package.json +6 -6
- package/src/canvas/canvas-live-render.ts +2 -4
- package/src/canvas/canvas-origin.ts +25 -0
- package/src/canvas/editable-actions.ts +37 -1
- package/src/canvas/iframe-editable-root.ts +27 -0
- package/src/canvas/iframe-host.ts +118 -7
- package/src/canvas/iframe-inline-edit.ts +64 -2
- package/src/canvas/iframe-protocol.ts +7 -0
- package/src/canvas/iframe-render.ts +38 -1
- package/src/editor/inline-edit-apply.ts +10 -4
- package/src/editor/inline-edit.ts +62 -4
- package/src/platforms/cloud.ts +9 -0
- package/src/services/ai-models.ts +14 -1
- package/src/types.ts +17 -0
- package/src/ui/ai-managed-connect.ts +18 -3
- package/styles/shell.css +7 -0
package/dist/iframe-entry.js
CHANGED
|
@@ -2200,11 +2200,15 @@ async function resolve(source) {
|
|
|
2200
2200
|
if (_resolveCache.has(source)) {
|
|
2201
2201
|
return _resolveCache.get(source);
|
|
2202
2202
|
}
|
|
2203
|
-
const p = fetch(source).then((res) => {
|
|
2203
|
+
const p = fetch(source).then(async (res) => {
|
|
2204
2204
|
if (!res.ok) {
|
|
2205
2205
|
throw new Error(`Jx: failed to fetch ${source} (${res.status})`);
|
|
2206
2206
|
}
|
|
2207
|
-
|
|
2207
|
+
const contentType = res.headers?.get("Content-Type") ?? "";
|
|
2208
|
+
if (contentType.includes("text/html")) {
|
|
2209
|
+
throw new Error(`Jx: ${source} returned HTML, not a document — the host answered a missing file with its ` + `app shell (a single-page fallback), so this path is not served.`);
|
|
2210
|
+
}
|
|
2211
|
+
return await res.json();
|
|
2208
2212
|
});
|
|
2209
2213
|
_resolveCache.set(source, p);
|
|
2210
2214
|
return p;
|
|
@@ -3476,6 +3480,16 @@ function getPath2(obj, path) {
|
|
|
3476
3480
|
return readPath(obj, path);
|
|
3477
3481
|
}
|
|
3478
3482
|
var _privatePropWarned = new Set;
|
|
3483
|
+
function instanceSupplies(el, key) {
|
|
3484
|
+
if (Object.hasOwn(el, key)) {
|
|
3485
|
+
return true;
|
|
3486
|
+
}
|
|
3487
|
+
if (el.hasAttribute(key)) {
|
|
3488
|
+
return true;
|
|
3489
|
+
}
|
|
3490
|
+
const kebab = key.replaceAll(/[A-Z]/gu, (c) => `-${c.toLowerCase()}`);
|
|
3491
|
+
return kebab !== key && el.hasAttribute(kebab);
|
|
3492
|
+
}
|
|
3479
3493
|
function refusePrivateProp(key, where) {
|
|
3480
3494
|
if (!isPrivateStateKey(key)) {
|
|
3481
3495
|
return false;
|
|
@@ -3626,7 +3640,7 @@ async function defineElement(source, baseUrl) {
|
|
|
3626
3640
|
if (isPrivateStateKey(key)) {
|
|
3627
3641
|
continue;
|
|
3628
3642
|
}
|
|
3629
|
-
if (key in this && this[key] !== undefined) {
|
|
3643
|
+
if (key in this && this[key] !== undefined && instanceSupplies(this, key)) {
|
|
3630
3644
|
state[key] = this[key];
|
|
3631
3645
|
}
|
|
3632
3646
|
}
|
|
@@ -4195,6 +4209,8 @@ function injectHead(doc) {
|
|
|
4195
4209
|
}
|
|
4196
4210
|
}
|
|
4197
4211
|
function makeStamper(ctx) {
|
|
4212
|
+
const islands = [];
|
|
4213
|
+
const insideIsland = (path) => islands.some((island) => path.length > island.length && island.every((seg, i) => path[i] === seg));
|
|
4198
4214
|
return (created, path, def2) => {
|
|
4199
4215
|
if (!(created instanceof HTMLElement)) {
|
|
4200
4216
|
return;
|
|
@@ -4203,8 +4219,10 @@ function makeStamper(ctx) {
|
|
|
4203
4219
|
if (isDefinitionRoot) {
|
|
4204
4220
|
created.dataset.jxDefinitionRoot = "";
|
|
4205
4221
|
}
|
|
4206
|
-
|
|
4222
|
+
const isIsland = !isDefinitionRoot && created.tagName.includes("-") && isEditableMode(ctx.canvasMode);
|
|
4223
|
+
if (isIsland) {
|
|
4207
4224
|
created.contentEditable = "false";
|
|
4225
|
+
islands.push(path);
|
|
4208
4226
|
}
|
|
4209
4227
|
const classified = classifyRenderNode(path, def2, ctx);
|
|
4210
4228
|
if (classified.kind === "layout") {
|
|
@@ -4221,6 +4239,9 @@ function makeStamper(ctx) {
|
|
|
4221
4239
|
return;
|
|
4222
4240
|
}
|
|
4223
4241
|
created.dataset.jxPath = serializeJxPath(classified.path);
|
|
4242
|
+
if (!isIsland && isEditableMode(ctx.canvasMode) && insideIsland(path)) {
|
|
4243
|
+
created.contentEditable = "true";
|
|
4244
|
+
}
|
|
4224
4245
|
};
|
|
4225
4246
|
}
|
|
4226
4247
|
function installCanvasImageRetry(root, maxAttempts = 3) {
|
|
@@ -5184,6 +5205,7 @@ var insertFn = null;
|
|
|
5184
5205
|
var endFn = null;
|
|
5185
5206
|
var _plainMode = false;
|
|
5186
5207
|
var _plainOriginal = "";
|
|
5208
|
+
var _plainPosted = false;
|
|
5187
5209
|
var editableVerdicts = null;
|
|
5188
5210
|
function setEditableVerdicts(verdicts) {
|
|
5189
5211
|
editableVerdicts = verdicts;
|
|
@@ -5203,6 +5225,7 @@ function startEditing(el, path, callbacks, opts) {
|
|
|
5203
5225
|
endFn = callbacks.onEnd;
|
|
5204
5226
|
_plainMode = opts?.plainText === true;
|
|
5205
5227
|
_plainOriginal = _plainMode ? el.textContent ?? "" : "";
|
|
5228
|
+
_plainPosted = false;
|
|
5206
5229
|
el.dataset.jxActiveBlock = "";
|
|
5207
5230
|
if (_plainMode) {
|
|
5208
5231
|
try {
|
|
@@ -5236,6 +5259,7 @@ function stopEditing(silent = false) {
|
|
|
5236
5259
|
insertFn = null;
|
|
5237
5260
|
_plainMode = false;
|
|
5238
5261
|
_plainOriginal = "";
|
|
5262
|
+
_plainPosted = false;
|
|
5239
5263
|
if (silent) {
|
|
5240
5264
|
endFn = null;
|
|
5241
5265
|
} else if (endFn) {
|
|
@@ -5247,6 +5271,9 @@ function stopEditing(silent = false) {
|
|
|
5247
5271
|
function commitActiveBlock() {
|
|
5248
5272
|
commitChanges(true);
|
|
5249
5273
|
}
|
|
5274
|
+
function isPlainSession() {
|
|
5275
|
+
return _plainMode && activeEl !== null;
|
|
5276
|
+
}
|
|
5250
5277
|
function isEditing() {
|
|
5251
5278
|
return activeEl !== null;
|
|
5252
5279
|
}
|
|
@@ -5332,6 +5359,7 @@ function releaseWithoutCommit() {
|
|
|
5332
5359
|
insertFn = null;
|
|
5333
5360
|
_plainMode = false;
|
|
5334
5361
|
_plainOriginal = "";
|
|
5362
|
+
_plainPosted = false;
|
|
5335
5363
|
if (endFn) {
|
|
5336
5364
|
const fn = endFn;
|
|
5337
5365
|
endFn = null;
|
|
@@ -5343,8 +5371,14 @@ function commitChanges(inPlace) {
|
|
|
5343
5371
|
return;
|
|
5344
5372
|
}
|
|
5345
5373
|
if (_plainMode) {
|
|
5346
|
-
|
|
5347
|
-
`, " ")
|
|
5374
|
+
const text = (activeEl.textContent ?? "").replaceAll(`
|
|
5375
|
+
`, " ");
|
|
5376
|
+
if (text === _plainOriginal.replaceAll(`
|
|
5377
|
+
`, " ") && !_plainPosted) {
|
|
5378
|
+
return;
|
|
5379
|
+
}
|
|
5380
|
+
_plainPosted = true;
|
|
5381
|
+
commitFn(activePath, null, text, inPlace);
|
|
5348
5382
|
return;
|
|
5349
5383
|
}
|
|
5350
5384
|
normalizeInlineContent(activeEl);
|
|
@@ -5467,6 +5501,9 @@ function openSlashMenu(opts) {
|
|
|
5467
5501
|
if (!activeEl || !insertFn || !activePath) {
|
|
5468
5502
|
return;
|
|
5469
5503
|
}
|
|
5504
|
+
if (_plainMode) {
|
|
5505
|
+
return;
|
|
5506
|
+
}
|
|
5470
5507
|
const sel = window.getSelection();
|
|
5471
5508
|
if (!sel || !sel.rangeCount) {
|
|
5472
5509
|
return;
|
|
@@ -5982,6 +6019,7 @@ var INSERT_TEXT = new Set([
|
|
|
5982
6019
|
"insertTranspose"
|
|
5983
6020
|
]);
|
|
5984
6021
|
var NATIVE_FORMAT_PREFIX = "format";
|
|
6022
|
+
var PROP_STRUCTURAL = new Set(["insertParagraph", "insertLineBreak"]);
|
|
5985
6023
|
function classifyBeforeInput(ctx) {
|
|
5986
6024
|
const { inputType, from, to } = ctx;
|
|
5987
6025
|
if (inputType === "insertCompositionText" || inputType === "insertFromComposition") {
|
|
@@ -5996,6 +6034,9 @@ function classifyBeforeInput(ctx) {
|
|
|
5996
6034
|
if (inputType === "insertFromDrop" || inputType === "deleteByDrag") {
|
|
5997
6035
|
return { kind: "reject" };
|
|
5998
6036
|
}
|
|
6037
|
+
if (ctx.inPropHost) {
|
|
6038
|
+
return PROP_STRUCTURAL.has(inputType) ? { kind: "reject" } : { kind: "native" };
|
|
6039
|
+
}
|
|
5999
6040
|
if (!from || !to) {
|
|
6000
6041
|
return { kind: "reject" };
|
|
6001
6042
|
}
|
|
@@ -6103,6 +6144,11 @@ function startEditableRoot(container, deps) {
|
|
|
6103
6144
|
composing = false;
|
|
6104
6145
|
scheduleCommitTick();
|
|
6105
6146
|
};
|
|
6147
|
+
const forget = () => {
|
|
6148
|
+
cancelCommitTick();
|
|
6149
|
+
activeEl2 = null;
|
|
6150
|
+
activeKey = null;
|
|
6151
|
+
};
|
|
6106
6152
|
const deactivate = () => {
|
|
6107
6153
|
if (!activeEl2) {
|
|
6108
6154
|
return;
|
|
@@ -6177,6 +6223,7 @@ function startEditableRoot(container, deps) {
|
|
|
6177
6223
|
atBlockStart: resolved ? isAtBlockStart(resolved.from) : false,
|
|
6178
6224
|
data: e.data ?? "",
|
|
6179
6225
|
from: resolved?.from ?? null,
|
|
6226
|
+
inPropHost: activeEl2 !== null && activeKey === null,
|
|
6180
6227
|
inputType: e.inputType,
|
|
6181
6228
|
to: resolved?.to ?? null
|
|
6182
6229
|
});
|
|
@@ -6247,6 +6294,7 @@ function startEditableRoot(container, deps) {
|
|
|
6247
6294
|
doc.addEventListener("pointerdown", onPointerDownCapture, true);
|
|
6248
6295
|
return {
|
|
6249
6296
|
capture: () => captureDocSelection(container, deps.isEditableBlock),
|
|
6297
|
+
forget,
|
|
6250
6298
|
isComposing: () => composing,
|
|
6251
6299
|
flush: () => {
|
|
6252
6300
|
if (composing) {
|
|
@@ -6742,14 +6790,18 @@ function startIframeInlineEdit(channel, container, opts) {
|
|
|
6742
6790
|
return true;
|
|
6743
6791
|
}
|
|
6744
6792
|
const node = getNodeAtPath(shadowDoc, hostPath);
|
|
6793
|
+
const attrs = node?.attributes;
|
|
6794
|
+
if (attrs?.[`props.${prop}`] !== undefined || attrs?.[prop] !== undefined) {
|
|
6795
|
+
return false;
|
|
6796
|
+
}
|
|
6745
6797
|
const raw = node?.$props?.[prop];
|
|
6746
6798
|
if (raw == null) {
|
|
6747
6799
|
return true;
|
|
6748
6800
|
}
|
|
6749
|
-
if (typeof raw
|
|
6801
|
+
if (typeof raw !== "string") {
|
|
6750
6802
|
return false;
|
|
6751
6803
|
}
|
|
6752
|
-
return !
|
|
6804
|
+
return !raw.includes("${");
|
|
6753
6805
|
};
|
|
6754
6806
|
const enterPropEditAt = (el, hostPath, prop) => {
|
|
6755
6807
|
channel.post({ kind: "editStart", path: hostPath, prop });
|
|
@@ -6764,6 +6816,7 @@ function startIframeInlineEdit(channel, container, opts) {
|
|
|
6764
6816
|
onEnd: () => {
|
|
6765
6817
|
clearHighlight();
|
|
6766
6818
|
lastNonEmptyRange = null;
|
|
6819
|
+
root.forget();
|
|
6767
6820
|
channel.post({ kind: "editEnd" });
|
|
6768
6821
|
},
|
|
6769
6822
|
onInsert: () => {},
|
|
@@ -6775,6 +6828,9 @@ function startIframeInlineEdit(channel, container, opts) {
|
|
|
6775
6828
|
if (!el) {
|
|
6776
6829
|
return;
|
|
6777
6830
|
}
|
|
6831
|
+
if (isPlainSession()) {
|
|
6832
|
+
return;
|
|
6833
|
+
}
|
|
6778
6834
|
if (lastNonEmptyRange && lastNonEmptyRange.startContainer.isConnected && el.contains(lastNonEmptyRange.commonAncestorContainer)) {
|
|
6779
6835
|
const sel = window.getSelection();
|
|
6780
6836
|
el.focus();
|
|
@@ -6889,6 +6945,14 @@ function startIframeInlineEdit(channel, container, opts) {
|
|
|
6889
6945
|
if (!editingAllowed()) {
|
|
6890
6946
|
return;
|
|
6891
6947
|
}
|
|
6948
|
+
if (msg.prop !== undefined) {
|
|
6949
|
+
const instance = elementForPath2(container, msg.path);
|
|
6950
|
+
const marker = instance?.querySelector(`[data-jx-bound-prop="${CSS.escape(msg.prop)}"]`);
|
|
6951
|
+
if (marker) {
|
|
6952
|
+
activateProp(marker);
|
|
6953
|
+
}
|
|
6954
|
+
return;
|
|
6955
|
+
}
|
|
6892
6956
|
const el = elementForPath2(container, msg.path);
|
|
6893
6957
|
if (el && isEditableBlock(el)) {
|
|
6894
6958
|
root.placeCaret({ offset: msg.offset ?? 0, path: msg.path });
|
|
@@ -8166,5 +8230,5 @@ export {
|
|
|
8166
8230
|
startCanvasIframe
|
|
8167
8231
|
};
|
|
8168
8232
|
|
|
8169
|
-
//# debugId=
|
|
8233
|
+
//# debugId=8BEF1FC0BD88A0F164756E2164756E21
|
|
8170
8234
|
//# sourceMappingURL=iframe-entry.js.map
|
package/dist/studio.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
seedPublishConnected
|
|
3
|
-
} from "./chunks/studio-
|
|
3
|
+
} from "./chunks/studio-qymkxbcq.js";
|
|
4
4
|
import"./chunks/studio-wdt9y92a.js";
|
|
5
5
|
import {
|
|
6
6
|
ElementResolutionController,
|
|
@@ -67,7 +67,7 @@ import {
|
|
|
67
67
|
registerStyleCommands,
|
|
68
68
|
render as render3,
|
|
69
69
|
setInspectorTab
|
|
70
|
-
} from "./chunks/studio-
|
|
70
|
+
} from "./chunks/studio-1d6bm7eg.js";
|
|
71
71
|
import {
|
|
72
72
|
CommandUnavailableError,
|
|
73
73
|
chordFromEvent,
|
|
@@ -99,7 +99,7 @@ import {
|
|
|
99
99
|
showSlashMenu,
|
|
100
100
|
showSlashMenuAtRect,
|
|
101
101
|
suppressBlockActionBar
|
|
102
|
-
} from "./chunks/studio-
|
|
102
|
+
} from "./chunks/studio-qb6vy1z1.js";
|
|
103
103
|
import {
|
|
104
104
|
addableContexts,
|
|
105
105
|
defaultCommands,
|
|
@@ -111,7 +111,7 @@ import {
|
|
|
111
111
|
tokenLabel,
|
|
112
112
|
transposeStylebookStyle,
|
|
113
113
|
writeTokenOverride
|
|
114
|
-
} from "./chunks/studio-
|
|
114
|
+
} from "./chunks/studio-gfzyxa0m.js";
|
|
115
115
|
import {
|
|
116
116
|
DERIVE_PRESETS,
|
|
117
117
|
JxColorPopover,
|
|
@@ -144,7 +144,7 @@ import {
|
|
|
144
144
|
spNumberField,
|
|
145
145
|
spTextArea,
|
|
146
146
|
spTextField
|
|
147
|
-
} from "./chunks/studio-
|
|
147
|
+
} from "./chunks/studio-n9k15qdg.js";
|
|
148
148
|
import {
|
|
149
149
|
LitElement,
|
|
150
150
|
css
|
|
@@ -160,7 +160,7 @@ import {
|
|
|
160
160
|
import {
|
|
161
161
|
initQuickSearch,
|
|
162
162
|
openQuickSearch
|
|
163
|
-
} from "./chunks/studio-
|
|
163
|
+
} from "./chunks/studio-9sxn0eaa.js";
|
|
164
164
|
import {
|
|
165
165
|
addRecentProject,
|
|
166
166
|
clearRecentProjects,
|
|
@@ -187,10 +187,10 @@ import {
|
|
|
187
187
|
removeRecentProject,
|
|
188
188
|
renderFilesTemplate,
|
|
189
189
|
seedEntry
|
|
190
|
-
} from "./chunks/studio-
|
|
190
|
+
} from "./chunks/studio-jand3kjg.js";
|
|
191
191
|
import {
|
|
192
192
|
computeWindow
|
|
193
|
-
} from "./chunks/studio-
|
|
193
|
+
} from "./chunks/studio-91sdrn9x.js";
|
|
194
194
|
import {
|
|
195
195
|
autoSyncProjectOnOpen,
|
|
196
196
|
cleanupGitPanel,
|
|
@@ -211,13 +211,13 @@ import {
|
|
|
211
211
|
registerSourceControlCommands,
|
|
212
212
|
renderGitPanel,
|
|
213
213
|
stripRange
|
|
214
|
-
} from "./chunks/studio-
|
|
214
|
+
} from "./chunks/studio-tdt7b6qb.js";
|
|
215
215
|
import {
|
|
216
216
|
createPanelScheduler
|
|
217
217
|
} from "./chunks/studio-8jpzqk5s.js";
|
|
218
218
|
import {
|
|
219
219
|
selectContributedEntry
|
|
220
|
-
} from "./chunks/studio-
|
|
220
|
+
} from "./chunks/studio-rz861p2b.js";
|
|
221
221
|
import {
|
|
222
222
|
notifySettingsDocument,
|
|
223
223
|
onSettingsDocumentChanged,
|
|
@@ -238,7 +238,7 @@ import {
|
|
|
238
238
|
renderForm,
|
|
239
239
|
renderProvenanceChip,
|
|
240
240
|
resolveContextPointer
|
|
241
|
-
} from "./chunks/studio-
|
|
241
|
+
} from "./chunks/studio-rkr6pm84.js";
|
|
242
242
|
import {
|
|
243
243
|
validateDoc,
|
|
244
244
|
validateProjectConfig
|
|
@@ -263,7 +263,7 @@ import {
|
|
|
263
263
|
registerGridCommands,
|
|
264
264
|
scanLibrary,
|
|
265
265
|
uploadDirForCategory
|
|
266
|
-
} from "./chunks/studio-
|
|
266
|
+
} from "./chunks/studio-4m39t01b.js";
|
|
267
267
|
import {
|
|
268
268
|
live
|
|
269
269
|
} from "./chunks/studio-c31yb4t6.js";
|
|
@@ -307,7 +307,7 @@ import {
|
|
|
307
307
|
setIncludeDrafts,
|
|
308
308
|
startFsSync,
|
|
309
309
|
writesForTurn
|
|
310
|
-
} from "./chunks/studio-
|
|
310
|
+
} from "./chunks/studio-gqpbrrj5.js";
|
|
311
311
|
import"./chunks/studio-2w11grav.js";
|
|
312
312
|
import"./chunks/studio-bw5dz6km.js";
|
|
313
313
|
import {
|
|
@@ -316,18 +316,18 @@ import {
|
|
|
316
316
|
isImage,
|
|
317
317
|
setMediaChangedHandler,
|
|
318
318
|
uploadAssets
|
|
319
|
-
} from "./chunks/studio-
|
|
319
|
+
} from "./chunks/studio-0svvdm0a.js";
|
|
320
320
|
import {
|
|
321
321
|
beginActivity,
|
|
322
322
|
registerActivityPanel,
|
|
323
323
|
showProgressModal
|
|
324
|
-
} from "./chunks/studio-
|
|
324
|
+
} from "./chunks/studio-d1f2rqxh.js";
|
|
325
325
|
import {
|
|
326
326
|
currentDeploy,
|
|
327
327
|
latestDeployment,
|
|
328
328
|
noteDeployment,
|
|
329
329
|
platformSupportsPublish
|
|
330
|
-
} from "./chunks/studio-
|
|
330
|
+
} from "./chunks/studio-675v08qj.js";
|
|
331
331
|
import {
|
|
332
332
|
CATEGORIES,
|
|
333
333
|
SPAN_FULL_RENDER,
|
|
@@ -439,7 +439,7 @@ import {
|
|
|
439
439
|
timeSpan,
|
|
440
440
|
timeSpanAsync,
|
|
441
441
|
updateActivePanelHeaders
|
|
442
|
-
} from "./chunks/studio-
|
|
442
|
+
} from "./chunks/studio-h6553a8h.js";
|
|
443
443
|
import {
|
|
444
444
|
BOTTOM_TAB_IDS,
|
|
445
445
|
BUFFER_COMMIT,
|
|
@@ -606,7 +606,7 @@ import {
|
|
|
606
606
|
updateSiteConfig,
|
|
607
607
|
view,
|
|
608
608
|
workspace
|
|
609
|
-
} from "./chunks/studio-
|
|
609
|
+
} from "./chunks/studio-kfq9ed73.js";
|
|
610
610
|
import {
|
|
611
611
|
classMap,
|
|
612
612
|
ifDefined,
|
|
@@ -669,7 +669,7 @@ import {
|
|
|
669
669
|
mountStillWanted,
|
|
670
670
|
refreshExtensionUi,
|
|
671
671
|
refreshFormats
|
|
672
|
-
} from "./chunks/studio-
|
|
672
|
+
} from "./chunks/studio-40fm3hyr.js";
|
|
673
673
|
import {
|
|
674
674
|
getPlatform,
|
|
675
675
|
hasPlatform,
|
|
@@ -16807,7 +16807,7 @@ function entryIdsFor(collection) {
|
|
|
16807
16807
|
if (known) {
|
|
16808
16808
|
return known;
|
|
16809
16809
|
}
|
|
16810
|
-
const pending = import("./chunks/content-source-
|
|
16810
|
+
const pending = import("./chunks/content-source-cn9te96r.js").then((m) => m.listCollectionEntryIds(collection));
|
|
16811
16811
|
entryIdCache.set(collection, pending);
|
|
16812
16812
|
return pending;
|
|
16813
16813
|
}
|
|
@@ -17068,7 +17068,7 @@ function renderEntryMode(surface, tab) {
|
|
|
17068
17068
|
});
|
|
17069
17069
|
}
|
|
17070
17070
|
async function openEntryEditor(path) {
|
|
17071
|
-
const { openFileInTab: openFileInTab2 } = await import("./chunks/files-
|
|
17071
|
+
const { openFileInTab: openFileInTab2 } = await import("./chunks/files-dsh5g8j4.js");
|
|
17072
17072
|
await openFileInTab2(path);
|
|
17073
17073
|
for (const [id, tab] of workspace.tabs.entries()) {
|
|
17074
17074
|
if (tab.documentPath !== path) {
|
|
@@ -17129,7 +17129,7 @@ async function createEntry(collectionName) {
|
|
|
17129
17129
|
});
|
|
17130
17130
|
return null;
|
|
17131
17131
|
}
|
|
17132
|
-
const { createFileIn: createFileIn2 } = await import("./chunks/files-
|
|
17132
|
+
const { createFileIn: createFileIn2 } = await import("./chunks/files-dsh5g8j4.js");
|
|
17133
17133
|
const created = await createFileIn2({
|
|
17134
17134
|
content,
|
|
17135
17135
|
dir: collection.dir,
|
|
@@ -22349,7 +22349,7 @@ function groupProblems(records = problems) {
|
|
|
22349
22349
|
return groups;
|
|
22350
22350
|
}
|
|
22351
22351
|
function openProblemPath(path) {
|
|
22352
|
-
import("./chunks/files-
|
|
22352
|
+
import("./chunks/files-dsh5g8j4.js").then((m) => m.openFileInTab(path));
|
|
22353
22353
|
}
|
|
22354
22354
|
function actionTpl(record) {
|
|
22355
22355
|
const id = record.action;
|
|
@@ -27264,6 +27264,7 @@ var cache2 = null;
|
|
|
27264
27264
|
var proxyConfigured = false;
|
|
27265
27265
|
var proxyManaged = false;
|
|
27266
27266
|
var proxyDefaultModel = "";
|
|
27267
|
+
var proxyCode;
|
|
27267
27268
|
var proxyProbe = null;
|
|
27268
27269
|
var probeListeners = new Set;
|
|
27269
27270
|
function invalidateModelCache() {
|
|
@@ -27271,6 +27272,7 @@ function invalidateModelCache() {
|
|
|
27271
27272
|
proxyConfigured = false;
|
|
27272
27273
|
proxyManaged = false;
|
|
27273
27274
|
proxyDefaultModel = "";
|
|
27275
|
+
proxyCode = undefined;
|
|
27274
27276
|
proxyProbe = null;
|
|
27275
27277
|
}
|
|
27276
27278
|
function ensureProxyProbe(onSettled) {
|
|
@@ -27292,6 +27294,9 @@ function isProxyConfigured() {
|
|
|
27292
27294
|
function isManagedProxy() {
|
|
27293
27295
|
return proxyManaged;
|
|
27294
27296
|
}
|
|
27297
|
+
function proxyStateCode() {
|
|
27298
|
+
return proxyCode;
|
|
27299
|
+
}
|
|
27295
27300
|
function siblingRoute(chatUrl, segment) {
|
|
27296
27301
|
let url;
|
|
27297
27302
|
try {
|
|
@@ -27326,6 +27331,7 @@ async function fetchAvailableModels(opts = {}) {
|
|
|
27326
27331
|
proxyConfigured = data.configured === true;
|
|
27327
27332
|
proxyManaged = data.managed === true;
|
|
27328
27333
|
proxyDefaultModel = data.defaultModel ?? "";
|
|
27334
|
+
proxyCode = data.code;
|
|
27329
27335
|
cache2 = (data.models || []).map((m) => ({ id: m.id, name: m.name || m.id }));
|
|
27330
27336
|
return cache2;
|
|
27331
27337
|
}
|
|
@@ -27490,17 +27496,22 @@ function createManagedConnect(opts) {
|
|
|
27490
27496
|
if (!canOffer()) {
|
|
27491
27497
|
return nothing;
|
|
27492
27498
|
}
|
|
27499
|
+
const lapsed = proxyStateCode() === "cf_reconnect_required";
|
|
27500
|
+
const busyLabel = lapsed ? "Reconnecting…" : "Connecting…";
|
|
27493
27501
|
return html`
|
|
27494
|
-
<div class="ai-managed-connect">
|
|
27495
|
-
<div
|
|
27502
|
+
<div class="ai-managed-connect" data-jx-recommended="cloudflare">
|
|
27503
|
+
<div class="ai-managed-connect-lede">
|
|
27504
|
+
${lapsed ? "Your Cloudflare connection has expired. Reconnect to keep using the assistant." : "Recommended — run the assistant on Workers AI in your own Cloudflare account. No API key to create, copy or rotate."}
|
|
27505
|
+
</div>
|
|
27496
27506
|
<sp-button
|
|
27497
27507
|
size="s"
|
|
27508
|
+
variant="accent"
|
|
27498
27509
|
?disabled=${busy}
|
|
27499
27510
|
@click=${() => {
|
|
27500
27511
|
connect();
|
|
27501
27512
|
}}
|
|
27502
27513
|
>
|
|
27503
|
-
${busy ? "
|
|
27514
|
+
${busy ? busyLabel : lapsed ? "Reconnect Cloudflare" : "Connect Cloudflare"}
|
|
27504
27515
|
</sp-button>
|
|
27505
27516
|
${connectError ? html`<div class="ai-managed-connect-error">${connectError}</div>` : nothing}
|
|
27506
27517
|
<div class="ai-managed-connect-divider">— or bring your own key —</div>
|
|
@@ -28900,6 +28911,7 @@ function createCloudPlatform(project) {
|
|
|
28900
28911
|
id: "cloud",
|
|
28901
28912
|
projectRoot: root,
|
|
28902
28913
|
canvasUrl: "/canvas.html",
|
|
28914
|
+
...base ? { documentBaseUrl: `${base}/raw/` } : {},
|
|
28903
28915
|
openProjectPicker: "repo-list",
|
|
28904
28916
|
createDestination: "repo",
|
|
28905
28917
|
async activate() {
|
|
@@ -58579,9 +58591,9 @@ function renderDefsEditor(container) {
|
|
|
58579
58591
|
|
|
58580
58592
|
// src/version.ts
|
|
58581
58593
|
var APP_NAME = "Jx Studio";
|
|
58582
|
-
var VERSION = "2.
|
|
58583
|
-
var BUILD_DATE = "2026-08-
|
|
58584
|
-
var GIT_COMMIT = "
|
|
58594
|
+
var VERSION = "2.4.1";
|
|
58595
|
+
var BUILD_DATE = "2026-08-24T11:52:26.010Z";
|
|
58596
|
+
var GIT_COMMIT = "eb4fe5d";
|
|
58585
58597
|
var LINKS = {
|
|
58586
58598
|
github: "https://github.com/jxsuite/jx",
|
|
58587
58599
|
docs: "https://github.com/jxsuite/jx#readme",
|
|
@@ -59658,7 +59670,7 @@ async function openProjectSettings(section) {
|
|
|
59658
59670
|
showSettingsDocument();
|
|
59659
59671
|
notifySettingsDocument();
|
|
59660
59672
|
try {
|
|
59661
|
-
const { syncExtensionSettingsSections } = await import("./chunks/extension-sections-
|
|
59673
|
+
const { syncExtensionSettingsSections } = await import("./chunks/extension-sections-mdgmqrry.js");
|
|
59662
59674
|
await syncExtensionSettingsSections();
|
|
59663
59675
|
} catch (error) {
|
|
59664
59676
|
notify.warn(`Could not load extension settings sections — ${errorMessage(error)}`, {
|
|
@@ -60282,7 +60294,7 @@ function publishCommands() {
|
|
|
60282
60294
|
name: "set_up_publishing"
|
|
60283
60295
|
},
|
|
60284
60296
|
run: async () => {
|
|
60285
|
-
const { openPublishPanel } = await import("./chunks/publish-panel-
|
|
60297
|
+
const { openPublishPanel } = await import("./chunks/publish-panel-b0xh7b4y.js");
|
|
60286
60298
|
openPublishPanel();
|
|
60287
60299
|
},
|
|
60288
60300
|
title: "Set Up Publishing"
|
|
@@ -61004,7 +61016,7 @@ function i18nCommands() {
|
|
|
61004
61016
|
});
|
|
61005
61017
|
return;
|
|
61006
61018
|
}
|
|
61007
|
-
const { openFileInTab: openFileInTab2 } = await import("./chunks/files-
|
|
61019
|
+
const { openFileInTab: openFileInTab2 } = await import("./chunks/files-dsh5g8j4.js");
|
|
61008
61020
|
await openFileInTab2(path);
|
|
61009
61021
|
},
|
|
61010
61022
|
title: "Open Translation"
|
|
@@ -61051,7 +61063,7 @@ function i18nCommands() {
|
|
|
61051
61063
|
return;
|
|
61052
61064
|
}
|
|
61053
61065
|
const cut = path.lastIndexOf("/");
|
|
61054
|
-
const { createFileIn: createFileIn2, openFileInTab: openFileInTab2 } = await import("./chunks/files-
|
|
61066
|
+
const { createFileIn: createFileIn2, openFileInTab: openFileInTab2 } = await import("./chunks/files-dsh5g8j4.js");
|
|
61055
61067
|
const created = await createFileIn2({
|
|
61056
61068
|
content,
|
|
61057
61069
|
dir: cut === -1 ? "." : path.slice(0, cut),
|
|
@@ -61864,5 +61876,5 @@ export {
|
|
|
61864
61876
|
hasUnsavedTabs
|
|
61865
61877
|
};
|
|
61866
61878
|
|
|
61867
|
-
//# debugId=
|
|
61879
|
+
//# debugId=C20E21297FE0976064756E2164756E21
|
|
61868
61880
|
//# sourceMappingURL=studio.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jxsuite/studio",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.1",
|
|
4
4
|
"description": "Jx Studio — visual builder for Jx documents",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -57,13 +57,13 @@
|
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"@atlaskit/pragmatic-drag-and-drop": "^3.0.0",
|
|
59
59
|
"@atlaskit/pragmatic-drag-and-drop-hitbox": "^2.1.0",
|
|
60
|
-
"@jxsuite/ai": "^0.36.
|
|
60
|
+
"@jxsuite/ai": "^0.36.2",
|
|
61
61
|
"@jxsuite/collab": "^0.8.1",
|
|
62
|
-
"@jxsuite/create": "^1.3.
|
|
63
|
-
"@jxsuite/formulas": "^0.0.
|
|
62
|
+
"@jxsuite/create": "^1.3.5",
|
|
63
|
+
"@jxsuite/formulas": "^0.0.11",
|
|
64
64
|
"@jxsuite/markup": "^0.4.5",
|
|
65
|
-
"@jxsuite/protocol": "^1.
|
|
66
|
-
"@jxsuite/runtime": "^2.0.
|
|
65
|
+
"@jxsuite/protocol": "^1.2.0",
|
|
66
|
+
"@jxsuite/runtime": "^2.0.4",
|
|
67
67
|
"@jxsuite/schema": "^1.8.0",
|
|
68
68
|
"@spectrum-web-components/accordion": "^1.12.2",
|
|
69
69
|
"@spectrum-web-components/action-bar": "1.12.2",
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
getEffectiveMedia,
|
|
20
20
|
resolveLayoutDoc,
|
|
21
21
|
} from "../site-context";
|
|
22
|
-
import {
|
|
22
|
+
import { documentBase } from "./canvas-origin";
|
|
23
23
|
import { componentRegistry, computeRelativePath } from "../files/components";
|
|
24
24
|
import { prepareForEditMode } from "../utils/edit-display";
|
|
25
25
|
import {
|
|
@@ -179,10 +179,8 @@ export async function resolveCanvasDocument(
|
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
-
const root = projectState?.projectRoot || "";
|
|
183
|
-
const docPrefix = root ? `${root}/` : "";
|
|
184
182
|
const docBase = S.documentPath
|
|
185
|
-
?
|
|
183
|
+
? new URL(S.documentPath, documentBase(projectState?.projectRoot)).href
|
|
186
184
|
: undefined;
|
|
187
185
|
|
|
188
186
|
// Substitute chosen dynamic route params ({$ref: "#/$params/x"} → literal), inject state.$page,
|
|
@@ -25,6 +25,31 @@ export function canvasBaseOrigin(): string {
|
|
|
25
25
|
return location.origin;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* The base the canvas fetches PROJECT FILES against — component `$ref`s, `$src` modules, images.
|
|
30
|
+
*
|
|
31
|
+
* Two shapes, and the platform chooses. Most hosts serve the project tree from their web root, so
|
|
32
|
+
* `<canvas origin>/<projectRoot>/` is a real URL: the dev server serves by path (absolute
|
|
33
|
+
* filesystem paths included) and the desktop loopback does the same. Those set nothing.
|
|
34
|
+
*
|
|
35
|
+
* A host whose `projectRoot` is an IDENTIFIER rather than a served path sets `documentBaseUrl`. Jx
|
|
36
|
+
* Cloud is one — its root is `owner/repo@branch`, and the default produced a URL nothing answered,
|
|
37
|
+
* so every `$ref` fetch fell through to the SPA fallback. That fallback returns the marketing page
|
|
38
|
+
* at **HTTP 200**, so `res.ok` passed and the runtime's `res.json()` died on `Unexpected token
|
|
39
|
+
* '<'`; images failed the same way and reported nothing.
|
|
40
|
+
*
|
|
41
|
+
* @param {string | undefined} projectRoot - The active project root, for the default shape.
|
|
42
|
+
* @returns {string} A base URL ending in `/`, safe to pass to `new URL(relativePath, base)`.
|
|
43
|
+
*/
|
|
44
|
+
export function documentBase(projectRoot?: string): string {
|
|
45
|
+
const declared = hasPlatform() ? getPlatform().documentBaseUrl : undefined;
|
|
46
|
+
if (declared) {
|
|
47
|
+
return declared.endsWith("/") ? declared : `${declared}/`;
|
|
48
|
+
}
|
|
49
|
+
const root = projectRoot || "";
|
|
50
|
+
return `${canvasBaseOrigin()}/${root ? `${root}/` : ""}`;
|
|
51
|
+
}
|
|
52
|
+
|
|
28
53
|
/**
|
|
29
54
|
* Build an absolute loopback-origin src for a PROJECT asset path referenced by a PARENT-realm
|
|
30
55
|
* (shell) preview <img>. On the views:// shell a relative "/images/foo.png" resolves to
|
|
@@ -49,6 +49,15 @@ export interface BeforeInputContext {
|
|
|
49
49
|
atBlockEnd: boolean;
|
|
50
50
|
/** The event's `data` (inserted text), empty for deletions. */
|
|
51
51
|
data: string;
|
|
52
|
+
/**
|
|
53
|
+
* The caret is in a PROP-BOUND nested host — text inside a component instance that is an
|
|
54
|
+
* invertible prop binding (studio.md §8.2.5), not a block of the page document.
|
|
55
|
+
*
|
|
56
|
+
* Such a host has no `data-jx-path` of its own, so `from`/`to` are always null for it. Without
|
|
57
|
+
* this flag the null-position rule below rejected every keystroke: the caret appeared, and
|
|
58
|
+
* nothing typed into a component slot ever landed.
|
|
59
|
+
*/
|
|
60
|
+
inPropHost: boolean;
|
|
52
61
|
}
|
|
53
62
|
|
|
54
63
|
/**
|
|
@@ -91,6 +100,20 @@ const INSERT_TEXT = new Set([
|
|
|
91
100
|
*/
|
|
92
101
|
const NATIVE_FORMAT_PREFIX = "format";
|
|
93
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Intents refused inside a prop-bound host, because a prop value is ONE PLAIN STRING.
|
|
105
|
+
*
|
|
106
|
+
* `docs/studio/editing/writing.md` puts it as "paragraph splits are off": there is no second block
|
|
107
|
+
* for Enter to make, and a `<br>` would serialise into a value that is supposed to be a single
|
|
108
|
+
* line. Everything else — insert, delete, paste, cut, IME — is ordinary text editing on a
|
|
109
|
+
* `plaintext-only` host and runs natively.
|
|
110
|
+
*
|
|
111
|
+
* These are refused rather than re-expressed: Enter FINISHES the edit (handled as a keystroke by
|
|
112
|
+
* the editing engine, not as an input event), so the chokepoint's only job is to stop the browser
|
|
113
|
+
* inserting the newline first.
|
|
114
|
+
*/
|
|
115
|
+
const PROP_STRUCTURAL = new Set(["insertParagraph", "insertLineBreak"]);
|
|
116
|
+
|
|
94
117
|
/**
|
|
95
118
|
* Classify one `beforeinput`.
|
|
96
119
|
*
|
|
@@ -124,7 +147,20 @@ export function classifyBeforeInput(ctx: BeforeInputContext): EditAction {
|
|
|
124
147
|
return { kind: "reject" };
|
|
125
148
|
}
|
|
126
149
|
|
|
127
|
-
|
|
150
|
+
/*
|
|
151
|
+
* 2. A prop-bound host is editable text with NO document path — it is written back as a prop
|
|
152
|
+
* value by its own commit (`editCommitProp`), not as a block. It must be judged before the
|
|
153
|
+
* null-position rule below, which would otherwise reject it for having no path: that is exactly
|
|
154
|
+
* what made a component slot show a caret and swallow every keystroke.
|
|
155
|
+
*
|
|
156
|
+
* Nothing here is structural, so nothing is re-expressed; the browser edits the text and the
|
|
157
|
+
* session commits the string.
|
|
158
|
+
*/
|
|
159
|
+
if (ctx.inPropHost) {
|
|
160
|
+
return PROP_STRUCTURAL.has(inputType) ? { kind: "reject" } : { kind: "native" };
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// 3. No resolvable position means the caret is in canvas chrome or a `contenteditable="false"`
|
|
128
164
|
// Island — there is no document node to write to.
|
|
129
165
|
if (!from || !to) {
|
|
130
166
|
return { kind: "reject" };
|