@jxsuite/studio 6.0.0 → 6.1.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/2020-va2wwra4.js +4 -0
- package/dist/chunks/adapter-f93pafd7.js +4 -0
- package/dist/chunks/{cf-account-picker-bb2yq946.js → cf-account-picker-af1h381v.js} +3 -3
- package/dist/chunks/cf-settings-125tdm0w.js +4 -0
- package/dist/chunks/components-ax2f1fnn.js +4 -0
- package/dist/chunks/content-source-108aqtk1.js +4 -0
- package/dist/chunks/{convert-to-repeater-vqkt7s3s.js → convert-to-repeater-ry5rmppr.js} +3 -3
- package/dist/chunks/editor-pfgdmkb0.js +4 -0
- package/dist/chunks/entry-commands-t0k1q0kx.js +4 -0
- package/dist/chunks/{extension-sections-8beq9ac3.js → extension-sections-6mwh2hf8.js} +3 -3
- package/dist/chunks/file-ops-meej5mqf.js +4 -0
- package/dist/chunks/files-44vp8a2s.js +4 -0
- package/dist/chunks/format-host-7q1petb9.js +4 -0
- package/dist/chunks/fs-events-h2mwnxaz.js +4 -0
- package/dist/chunks/git-panel-zngbymvd.js +4 -0
- package/dist/chunks/{grid-view-ca10def6.js → grid-view-sx9vynsp.js} +15 -15
- package/dist/chunks/icons-p44xhjf0.js +4 -0
- package/dist/chunks/iframe-host-qk3ycq87.js +4 -0
- package/dist/chunks/{index-9ydfe04y.js → index-2veqmnhr.js} +3 -3
- package/dist/chunks/index-wkyfjeqz.js +4 -0
- package/dist/chunks/{javascript-d9pqgc2p.js → javascript-8nbvs12s.js} +3 -3
- package/dist/chunks/jsonMode-s8kt9dsj.js +13 -0
- package/dist/chunks/jx-validate-psgd7vsx.js +4 -0
- package/dist/chunks/layers-panel-1kq2jyfk.js +4 -0
- package/dist/chunks/layers-xd92fg8d.js +4 -0
- package/dist/chunks/lit-html-ac4cwwr4.js +4 -0
- package/dist/chunks/media-picker-0svzkdyb.js +4 -0
- package/dist/chunks/menu-5c55ea3d.js +4 -0
- package/dist/chunks/{monaco-binding-62dtmgbf.js → monaco-binding-z6r70pdt.js} +3 -3
- package/dist/chunks/monaco-buffer-fz6gq5y7.js +4 -0
- package/dist/chunks/monaco-setup-q4axkgj7.js +4 -0
- package/dist/chunks/notify-0xgtn8q1.js +4 -0
- package/dist/chunks/platform-v1qctbe6.js +4 -0
- package/dist/chunks/publish-panel-ym1fmgq5.js +4 -0
- package/dist/chunks/quick-search-a54e6t5n.js +4 -0
- package/dist/chunks/references-gmqp82fs.js +4 -0
- package/dist/chunks/right-panel-v7t9awbk.js +4 -0
- package/dist/chunks/section-registry-vhyf3zsr.js +4 -0
- package/dist/chunks/studio-0bhx5hz6.js +5 -0
- package/dist/chunks/studio-0k1ddnyy.js +6 -0
- package/dist/chunks/studio-1b04pd0j.js +64 -0
- package/dist/chunks/{studio-sxc0zvpt.js → studio-1q1sh2ax.js} +3 -3
- package/dist/chunks/studio-4dwbj6gb.js +5 -0
- package/dist/chunks/studio-4tanh828.js +5 -0
- package/dist/chunks/{studio-fqq890ap.js → studio-55h4mstj.js} +3 -3
- package/dist/chunks/studio-5tnvjkz4.js +5 -0
- package/dist/chunks/studio-60dqgb0c.js +5 -0
- package/dist/chunks/studio-61dp09qg.js +9 -0
- package/dist/chunks/studio-63epcrj2.js +5 -0
- package/dist/chunks/studio-74k29dy9.js +5 -0
- package/dist/chunks/{studio-qa73881a.js → studio-7vg6jcd3.js} +4 -4
- package/dist/chunks/studio-7zx31knw.js +9 -0
- package/dist/chunks/studio-8bxk97km.js +5 -0
- package/dist/chunks/{studio-edbtvcd1.js → studio-8grwxtqk.js} +4 -4
- package/dist/chunks/studio-933e30n4.js +5 -0
- package/dist/chunks/{studio-rr4xkv81.js → studio-98wnwhbg.js} +4 -4
- package/dist/chunks/studio-9mccjwjh.js +14 -0
- package/dist/chunks/studio-a2ke1e4t.js +5 -0
- package/dist/chunks/studio-e3a2a6v3.js +4 -0
- package/dist/chunks/{studio-pwqfmt4p.js → studio-e81q1vb9.js} +4 -4
- package/dist/chunks/{studio-7pgy3xaf.js → studio-epgrmqqm.js} +4 -4
- package/dist/chunks/studio-g1shz58g.js +5 -0
- package/dist/chunks/studio-gf0fz03c.js +5 -0
- package/dist/chunks/studio-gjtpe62q.js +6 -0
- package/dist/chunks/{studio-tzegmy4w.js → studio-gkskhg7m.js} +4 -4
- package/dist/chunks/studio-gx4dnjzd.js +5 -0
- package/dist/chunks/{studio-8xcwewjq.js → studio-h46vtzk8.js} +4 -4
- package/dist/chunks/studio-j03zga3y.js +9 -0
- package/dist/chunks/{studio-4r0sjtx8.js → studio-jhpxeckz.js} +4 -4
- package/dist/chunks/{studio-zd4kayn2.js → studio-k01r7ykp.js} +4 -4
- package/dist/chunks/{studio-03wwfvyt.js → studio-kggey1jt.js} +4 -4
- package/dist/chunks/{studio-hnvnfbdv.js → studio-kk7h30ne.js} +6 -6
- package/dist/chunks/{studio-01qza1n3.js → studio-kt1zqney.js} +4 -4
- package/dist/chunks/{studio-r3kaka4d.js → studio-m3cwhvye.js} +4 -4
- package/dist/chunks/{studio-evwgp1ym.js → studio-mcayt6hz.js} +4 -4
- package/dist/chunks/{studio-5vy2wfm5.js → studio-myjcghv3.js} +4 -4
- package/dist/chunks/studio-n8bxwc3y.js +4 -0
- package/dist/chunks/{studio-ztvcxm3w.js → studio-ngm8gvpb.js} +4 -4
- package/dist/chunks/{studio-01kbbqg3.js → studio-nj5a01jy.js} +196 -196
- package/dist/chunks/{studio-xkfs0dp2.js → studio-pcgz8heb.js} +4 -4
- package/dist/chunks/{studio-0bbxhhce.js → studio-pre0skq6.js} +4 -4
- package/dist/chunks/{studio-n78gjfy8.js → studio-qcsq0t15.js} +4 -4
- package/dist/chunks/studio-qkstvve9.js +5 -0
- package/dist/chunks/studio-qv1pwd3c.js +5 -0
- package/dist/chunks/{studio-rmn2dz59.js → studio-rc6dvxjb.js} +5 -5
- package/dist/chunks/{studio-st75kn99.js → studio-rv11kfwa.js} +7 -7
- package/dist/chunks/studio-s8dmmz66.js +5 -0
- package/dist/chunks/studio-sp5xzbj4.js +6 -0
- package/dist/chunks/{studio-tmeq6mjb.js → studio-szsjbj0g.js} +4 -4
- package/dist/chunks/studio-t1xzawhr.js +16 -0
- package/dist/chunks/{studio-mk00zd5d.js → studio-t6b6qe31.js} +4 -4
- package/dist/chunks/{studio-bftp4n4b.js → studio-tdcprbqb.js} +4 -4
- package/dist/chunks/{studio-ge5fqjth.js → studio-vrmcjf9g.js} +5 -5
- package/dist/chunks/studio-vyc0b4he.js +10 -0
- package/dist/chunks/{studio-semd1s8s.js → studio-w0cgf6jg.js} +4 -4
- package/dist/chunks/{studio-gp02nqnw.js → studio-w3hskzqk.js} +4 -4
- package/dist/chunks/{studio-1wvfxkyy.js → studio-wszjyh0j.js} +4 -4
- package/dist/chunks/studio-xgrgcdyh.js +9 -0
- package/dist/chunks/{studio-y7jehjrp.js → studio-xz2yxfcb.js} +4 -4
- package/dist/chunks/{studio-aje966s9.js → studio-y6n42tgs.js} +4 -4
- package/dist/chunks/{studio-yr04mv2j.js → studio-yb560vxr.js} +4 -4
- package/dist/chunks/{studio-tp642n5g.js → studio-yn9f8vtx.js} +4 -4
- package/dist/chunks/studio-yw05w8f0.js +7 -0
- package/dist/chunks/{studio-cbr9czkn.js → studio-z16sgavc.js} +4 -4
- package/dist/chunks/studio-zey7zsdw.js +12 -0
- package/dist/chunks/{studio-1q6amtph.js → studio-zyqn40w4.js} +4 -4
- package/dist/chunks/tsMode-2frah6h1.js +14 -0
- package/dist/chunks/workspace-zt81g1ms.js +4 -0
- package/dist/chunks/ws-client-n2bh4hkf.js +4 -0
- package/dist/iframe-entry.js +13 -13
- package/dist/manifest.json +62 -62
- package/dist/studio.js +87 -87
- package/dist/workers/ts.worker.js +3 -3
- package/package.json +10 -10
- package/src/canvas/canvas-render.ts +4 -1
- package/src/canvas/canvas-utils.ts +73 -15
- package/src/canvas/iframe-host.ts +67 -21
- package/src/canvas/iframe-inline-edit.ts +22 -4
- package/src/canvas/iframe-interaction.ts +7 -1
- package/src/canvas/iframe-protocol.ts +3 -0
- package/src/canvas/iframe-render.ts +5 -2
- package/src/commands/defaults.ts +4 -1
- package/src/commands/live-context.ts +3 -1
- package/src/editor/shortcuts.ts +55 -27
- package/src/files/media-paths.ts +3 -1
- package/src/new-project/add-repo-modal.ts +459 -59
- package/src/panels/editors.ts +3 -1
- package/src/panels/style-panel.ts +36 -11
- package/src/platforms/cloud.ts +95 -18
- package/src/platforms/devserver.ts +47 -12
- package/src/publish/pages-service.ts +7 -0
- package/src/publish/publish-panel.ts +16 -2
- package/src/studio.ts +14 -2
- package/src/surfaces/add-repo.json +721 -224
- package/src/surfaces/add-repo.ts +196 -31
- package/src/surfaces/library-pane.ts +6 -0
- package/src/surfaces/rail.json +126 -73
- package/src/surfaces/rail.ts +31 -5
- package/src/tabs/typing.ts +31 -0
- package/src/types.ts +42 -3
- package/src/utils/edit-display.ts +30 -1
- package/src/utils/project-dir.ts +24 -0
- package/src/workspace/workspace.ts +7 -0
- package/dist/chunks/2020-cs2sb9t1.js +0 -4
- package/dist/chunks/adapter-y5gdq19c.js +0 -4
- package/dist/chunks/cf-settings-20dznc3j.js +0 -4
- package/dist/chunks/components-q037dya7.js +0 -4
- package/dist/chunks/content-source-t0q184js.js +0 -4
- package/dist/chunks/editor-j5sq149q.js +0 -4
- package/dist/chunks/entry-commands-fxzgcc4k.js +0 -4
- package/dist/chunks/file-ops-2n77759h.js +0 -4
- package/dist/chunks/files-fjy7zpxt.js +0 -4
- package/dist/chunks/format-host-wj3mf3n8.js +0 -4
- package/dist/chunks/fs-events-7kcgn4e9.js +0 -4
- package/dist/chunks/git-panel-7z2mpt2d.js +0 -4
- package/dist/chunks/icons-qbh8akb1.js +0 -4
- package/dist/chunks/iframe-host-a0zjd6xp.js +0 -4
- package/dist/chunks/index-m0x5ztax.js +0 -4
- package/dist/chunks/jsonMode-800yvbem.js +0 -13
- package/dist/chunks/jx-validate-zc9zp77s.js +0 -4
- package/dist/chunks/layers-p677nrh5.js +0 -4
- package/dist/chunks/layers-panel-y4w1dq90.js +0 -4
- package/dist/chunks/lit-html-cfn61dn7.js +0 -4
- package/dist/chunks/media-picker-xg7yjpz9.js +0 -4
- package/dist/chunks/menu-fpekzj6w.js +0 -4
- package/dist/chunks/monaco-buffer-nn4dtx27.js +0 -4
- package/dist/chunks/monaco-setup-tj13ndtm.js +0 -4
- package/dist/chunks/notify-ahs57a2z.js +0 -4
- package/dist/chunks/platform-v9xyfkbx.js +0 -4
- package/dist/chunks/publish-panel-xtbfgg2r.js +0 -4
- package/dist/chunks/quick-search-d3a6m7j3.js +0 -4
- package/dist/chunks/references-99ws0b0m.js +0 -4
- package/dist/chunks/right-panel-31vbk5xp.js +0 -4
- package/dist/chunks/section-registry-b2yzp9sw.js +0 -4
- package/dist/chunks/studio-1a99w39s.js +0 -5
- package/dist/chunks/studio-3ck2a5c4.js +0 -10
- package/dist/chunks/studio-4fde4a0x.js +0 -5
- package/dist/chunks/studio-4jj9gme2.js +0 -6
- package/dist/chunks/studio-4m50vh74.js +0 -16
- package/dist/chunks/studio-4xppwncr.js +0 -4
- package/dist/chunks/studio-5d7wfmnp.js +0 -5
- package/dist/chunks/studio-5e9zsamh.js +0 -9
- package/dist/chunks/studio-5gs9th4b.js +0 -5
- package/dist/chunks/studio-7qvs7v0m.js +0 -5
- package/dist/chunks/studio-84rtc120.js +0 -5
- package/dist/chunks/studio-aekhcdzw.js +0 -7
- package/dist/chunks/studio-aqmph6k4.js +0 -5
- package/dist/chunks/studio-c6zdm25z.js +0 -9
- package/dist/chunks/studio-capk0583.js +0 -9
- package/dist/chunks/studio-chdmwwzw.js +0 -5
- package/dist/chunks/studio-cp1gbff9.js +0 -14
- package/dist/chunks/studio-cqmtbg2p.js +0 -5
- package/dist/chunks/studio-e47215hh.js +0 -5
- package/dist/chunks/studio-fbx6twps.js +0 -6
- package/dist/chunks/studio-fthwn4kf.js +0 -5
- package/dist/chunks/studio-g8dsj3d2.js +0 -6
- package/dist/chunks/studio-gjknvzam.js +0 -9
- package/dist/chunks/studio-hjbg8d5y.js +0 -12
- package/dist/chunks/studio-nbxqcgvf.js +0 -5
- package/dist/chunks/studio-t1eedsyx.js +0 -4
- package/dist/chunks/studio-vavmwshr.js +0 -5
- package/dist/chunks/studio-x5g1xk77.js +0 -5
- package/dist/chunks/studio-x92tgnee.js +0 -64
- package/dist/chunks/studio-xg1942as.js +0 -5
- package/dist/chunks/studio-zev8ssp1.js +0 -5
- package/dist/chunks/tsMode-k9s9fcag.js +0 -14
- package/dist/chunks/workspace-5vmgsagj.js +0 -4
- package/dist/chunks/ws-client-0ja08haa.js +0 -4
|
@@ -563,6 +563,9 @@ export type IframeToParent =
|
|
|
563
563
|
// Inline editing started in the iframe (the parent shows the format toolbar from here). `prop`
|
|
564
564
|
// Names the component-instance prop when the session edits prop-bound text (plain sessions).
|
|
565
565
|
| { kind: "editStart"; path: (string | number)[]; prop?: string }
|
|
566
|
+
// The first keystroke of a typing burst, ahead of the idle tick's commit: the parent marks the tab
|
|
567
|
+
// Dirty now, so Save is enabled the instant there is text a save would keep.
|
|
568
|
+
| { kind: "editInput" }
|
|
566
569
|
// Committed inline-edit content (rich `children` else `textContent`) for the parent to persist.
|
|
567
570
|
| {
|
|
568
571
|
kind: "editCommit";
|
|
@@ -1018,8 +1018,11 @@ export async function renderResolvedDocument(opts: {
|
|
|
1018
1018
|
// Sections feeding back into an ever-growing height. Set every render (the iframe always wants it).
|
|
1019
1019
|
setCanvasViewportTranspose(true);
|
|
1020
1020
|
// De-link `<a href>` in design/edit so clicks select the anchor instead of navigating the iframe;
|
|
1021
|
-
// Preview keeps real links live (mirrors the server-function gate above).
|
|
1022
|
-
|
|
1021
|
+
// Preview keeps real links live (mirrors the server-function gate above). So does Project Styles:
|
|
1022
|
+
// An `<a>` without `href` is not a link, so `:link`, `:any-link` and the UA's link colour could
|
|
1023
|
+
// Never match its specimen, and a project could not see the link styles it was setting there.
|
|
1024
|
+
// Its clicks are refused in the frame instead (`iframe-interaction.ts`).
|
|
1025
|
+
setCanvasDelinkAnchors(opts.mode !== "preview" && opts.mode !== "stylebook");
|
|
1023
1026
|
/* De-popover in the same modes and for the same reason: an OPEN popover is in the top layer,
|
|
1024
1027
|
whose containing block is the viewport — a fiction here, since the frame is sized to its own
|
|
1025
1028
|
content — and which contributes to no ancestor's scrollable overflow, so the artboard could
|
package/src/commands/defaults.ts
CHANGED
|
@@ -236,7 +236,10 @@ export function defaultCommands(deps: CommandDeps): AnyCommand[] {
|
|
|
236
236
|
group: "1_file",
|
|
237
237
|
undo: "none",
|
|
238
238
|
when: documentOpen,
|
|
239
|
-
|
|
239
|
+
// Nothing to save is a disabled button, not a no-op one. A disabled chord is still claimed,
|
|
240
|
+
// So ⌘S on a clean document never falls through to the browser's own Save Page.
|
|
241
|
+
enablement: (ctx) => ctx.document.dirty,
|
|
242
|
+
requires: "unsaved changes",
|
|
240
243
|
run: () => deps.saveDocument(),
|
|
241
244
|
},
|
|
242
245
|
{
|
|
@@ -32,6 +32,7 @@ import { shell } from "../shell";
|
|
|
32
32
|
import { activeTab, workspace } from "../workspace/workspace";
|
|
33
33
|
import { primarySelection } from "../tabs/selection";
|
|
34
34
|
import { canRedo, canUndo } from "../tabs/transact";
|
|
35
|
+
import { hasTyping } from "../tabs/typing";
|
|
35
36
|
import { collabState } from "../collab/collab-state";
|
|
36
37
|
|
|
37
38
|
import { canvasViewForMode, editorKindForMode, emptyContext } from "./context";
|
|
@@ -133,7 +134,8 @@ export function createLiveContext(sources: LiveContextSources): () => CommandCon
|
|
|
133
134
|
ctx.git.dirtyCount = shell.git.status?.files.length ?? 0;
|
|
134
135
|
|
|
135
136
|
ctx.document.open = tab !== null;
|
|
136
|
-
|
|
137
|
+
// Typing still in a source buffer is unsaved work too, though the document has not seen it.
|
|
138
|
+
ctx.document.dirty = tab ? tab.doc.dirty === true || hasTyping(tab.id) : false;
|
|
137
139
|
ctx.document.mode = tab?.doc.mode ?? "";
|
|
138
140
|
ctx.document.canUndo = tab ? canUndo(tab) : false;
|
|
139
141
|
ctx.document.canRedo = tab ? canRedo(tab) : false;
|
package/src/editor/shortcuts.ts
CHANGED
|
@@ -51,16 +51,16 @@ import {
|
|
|
51
51
|
} from "../tabs/transact";
|
|
52
52
|
import {
|
|
53
53
|
applyEditZoom,
|
|
54
|
-
markExplicitZoom,
|
|
55
54
|
requestEditZoom,
|
|
56
55
|
setEditZoom,
|
|
56
|
+
setUserZoom,
|
|
57
|
+
stageZoom,
|
|
57
58
|
} from "../canvas/canvas-utils";
|
|
58
59
|
import { openQuickSearch } from "../panels/quick-search";
|
|
59
60
|
import { inspectorTab } from "../panels/right-panel";
|
|
60
61
|
import { requestClose } from "../panels/tab-strip";
|
|
61
62
|
import { layerHost } from "../ui/layers";
|
|
62
63
|
import { openDialogSurface } from "../surfaces/dialog";
|
|
63
|
-
import { rectOf } from "../utils/geometry";
|
|
64
64
|
import {
|
|
65
65
|
DOCK_IDS,
|
|
66
66
|
requireNavigatorPanelId,
|
|
@@ -78,6 +78,8 @@ import { hasElementSelection, hasSelection, inCanvas, keyScopeStack } from "../c
|
|
|
78
78
|
import { defaultCommands } from "../commands/defaults";
|
|
79
79
|
import { setActiveRegistry } from "../commands/active-registry";
|
|
80
80
|
import { runReported } from "../commands/run-reported";
|
|
81
|
+
import { pointerAnchor } from "../canvas/iframe-host";
|
|
82
|
+
import type { PointerAnchor } from "../canvas/iframe-host";
|
|
81
83
|
import type { CommandContext } from "../commands/context";
|
|
82
84
|
import type { DockId as CommandDockId } from "../commands/defaults";
|
|
83
85
|
import type { AnyCommand, CommandRegistry } from "../commands/registry";
|
|
@@ -314,11 +316,15 @@ function redoDocument(): void {
|
|
|
314
316
|
|
|
315
317
|
// ─── Canvas zoom ──────────────────────────────────────────────────────────────
|
|
316
318
|
|
|
317
|
-
/**
|
|
318
|
-
const ZOOM_MIN = 0.05;
|
|
319
|
-
const ZOOM_MAX = 5;
|
|
319
|
+
/** One chord step. Both zooms clamp inside `canvas-utils`. */
|
|
320
320
|
const ZOOM_STEP = 1.2;
|
|
321
321
|
|
|
322
|
+
/** How long after an Edit zoom step its anchor is measured again: the zoom's frame, then a reflow. */
|
|
323
|
+
const EDIT_ZOOM_SETTLE_MS = 34;
|
|
324
|
+
|
|
325
|
+
/** How long an Edit zoom burst must be idle before its anchor is let go. */
|
|
326
|
+
const EDIT_ZOOM_RELEASE_MS = 300;
|
|
327
|
+
|
|
322
328
|
/** Whether the zoom verbs address the reflowing content zoom rather than the artboard transform. */
|
|
323
329
|
function isContentZoom(ctx: CommandContext): boolean {
|
|
324
330
|
return ctx.canvas.view === "edit";
|
|
@@ -346,8 +352,8 @@ function zoomBy(ctx: CommandContext, factor: number, redraw: () => void): void {
|
|
|
346
352
|
setEditZoom((tab.session.ui.editZoom ?? 1) * factor);
|
|
347
353
|
return;
|
|
348
354
|
}
|
|
349
|
-
|
|
350
|
-
|
|
355
|
+
// Around the stage's middle, like the zoom pod's buttons.
|
|
356
|
+
setUserZoom(stageZoom() * factor);
|
|
351
357
|
redraw();
|
|
352
358
|
}
|
|
353
359
|
|
|
@@ -1074,6 +1080,26 @@ let _stageContext: StageContext | null = null;
|
|
|
1074
1080
|
*/
|
|
1075
1081
|
export function installStageGestures(surface: CanvasSurface): () => void {
|
|
1076
1082
|
const canvasWrap = surface.wrap;
|
|
1083
|
+
/* An Edit zoom burst's anchor: the element under the cursor when the burst began. The frame
|
|
1084
|
+
reflows at every step, so after each one the element is measured again and the scroller takes
|
|
1085
|
+
back whatever it moved; the anchor is let go once the burst has been idle a while. */
|
|
1086
|
+
let zoomAnchor: PointerAnchor | null = null;
|
|
1087
|
+
let zoomRelease: ReturnType<typeof setTimeout> | undefined;
|
|
1088
|
+
let zoomCorrecting = false;
|
|
1089
|
+
const correctEditZoom = () => {
|
|
1090
|
+
const anchor = zoomAnchor;
|
|
1091
|
+
if (!anchor || zoomCorrecting) {
|
|
1092
|
+
return;
|
|
1093
|
+
}
|
|
1094
|
+
zoomCorrecting = true;
|
|
1095
|
+
void anchor.settle().then((top) => {
|
|
1096
|
+
zoomCorrecting = false;
|
|
1097
|
+
const sc = canvasWrap.querySelector<HTMLElement>('[part="edit-canvas"]');
|
|
1098
|
+
if (top !== null && sc) {
|
|
1099
|
+
sc.scrollTop += top - anchor.top;
|
|
1100
|
+
}
|
|
1101
|
+
});
|
|
1102
|
+
};
|
|
1077
1103
|
const getContext = () => _stageContext?.(surface) ?? stageless();
|
|
1078
1104
|
const controller = new AbortController();
|
|
1079
1105
|
const { signal } = controller;
|
|
@@ -1093,7 +1119,16 @@ export function installStageGestures(surface: CanvasSurface): () => void {
|
|
|
1093
1119
|
if (e.ctrlKey || e.metaKey) {
|
|
1094
1120
|
e.preventDefault();
|
|
1095
1121
|
const editZoom = paneTab?.session.ui.editZoom ?? 1;
|
|
1096
|
-
|
|
1122
|
+
const canvasEl = surface.panels[0]?.canvas;
|
|
1123
|
+
zoomAnchor ??= canvasEl ? pointerAnchor(canvasEl) : null;
|
|
1124
|
+
requestEditZoom(editZoom * (1 + -e.deltaY * 0.005), surface, e.clientY);
|
|
1125
|
+
// Measured after the zoom's own frame has applied, and the frame has had one to reflow.
|
|
1126
|
+
setTimeout(correctEditZoom, EDIT_ZOOM_SETTLE_MS);
|
|
1127
|
+
clearTimeout(zoomRelease);
|
|
1128
|
+
zoomRelease = setTimeout(() => {
|
|
1129
|
+
correctEditZoom();
|
|
1130
|
+
zoomAnchor = null;
|
|
1131
|
+
}, EDIT_ZOOM_RELEASE_MS);
|
|
1097
1132
|
return;
|
|
1098
1133
|
}
|
|
1099
1134
|
/* The stage's own scroller, by the `part` the stage document draws it with — the same
|
|
@@ -1125,24 +1160,14 @@ export function installStageGestures(surface: CanvasSurface): () => void {
|
|
|
1125
1160
|
}
|
|
1126
1161
|
e.preventDefault();
|
|
1127
1162
|
if (e.ctrlKey || e.metaKey) {
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
const newZoom = Math.min(ZOOM_MAX, Math.max(ZOOM_MIN, oldZoom * (1 + delta)));
|
|
1137
|
-
const ratio = newZoom / oldZoom;
|
|
1138
|
-
// Adjust pan so the point under cursor stays stationary
|
|
1139
|
-
setPan(cursorX - (cursorX - panX) * ratio, cursorY - (cursorY - panY) * ratio);
|
|
1140
|
-
if (paneTab) {
|
|
1141
|
-
paneTab.session.ui.zoom = newZoom;
|
|
1142
|
-
}
|
|
1143
|
-
// The author chose this zoom, so re-entering Design keeps it instead of auto-fitting.
|
|
1144
|
-
// On THIS stage: the declared fit is a fact about the document under the cursor.
|
|
1145
|
-
markExplicitZoom(surface);
|
|
1163
|
+
/* Zoom toward the cursor, on THIS stage (a lens pane carries its own scale). The author
|
|
1164
|
+
chose this zoom, so it is declared as the document's fit and re-entering Design keeps
|
|
1165
|
+
it instead of auto-fitting. */
|
|
1166
|
+
setUserZoom(stageZoom(surface) * (1 + -e.deltaY * 0.005), surface, {
|
|
1167
|
+
clientX: e.clientX,
|
|
1168
|
+
clientY: e.clientY,
|
|
1169
|
+
});
|
|
1170
|
+
return;
|
|
1146
1171
|
} else if (e.shiftKey) {
|
|
1147
1172
|
// Shift+scroll = horizontal pan
|
|
1148
1173
|
setPan(panX - e.deltaY, panY);
|
|
@@ -1206,7 +1231,10 @@ export function installStageGestures(surface: CanvasSurface): () => void {
|
|
|
1206
1231
|
{ signal },
|
|
1207
1232
|
);
|
|
1208
1233
|
|
|
1209
|
-
return () =>
|
|
1234
|
+
return () => {
|
|
1235
|
+
clearTimeout(zoomRelease);
|
|
1236
|
+
controller.abort();
|
|
1237
|
+
};
|
|
1210
1238
|
}
|
|
1211
1239
|
|
|
1212
1240
|
/** The context a stage answers with before the bootstrap has published a reader. */
|
package/src/files/media-paths.ts
CHANGED
|
@@ -134,5 +134,7 @@ export function previewFileSrc(path: string): string {
|
|
|
134
134
|
if (space === "repo") {
|
|
135
135
|
return withVersion(`${fileBaseUrl}${encodeProjectPath(normalized)}`, versionOf(normalized));
|
|
136
136
|
}
|
|
137
|
-
|
|
137
|
+
/* Encoded per segment for the `src` only. `mediaSiteUrl` is also what an author's document is
|
|
138
|
+
given, and stays as typed; a `#` or `?` in a filename would cut this URL short. */
|
|
139
|
+
return loopbackAssetSrc(`/${encodeProjectPath(mediaSiteUrl(normalized).slice(1))}`);
|
|
138
140
|
}
|