opendevbrowser 0.0.16 → 0.0.17
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/README.md +51 -27
- package/dist/browser/annotation-manager.d.ts +3 -0
- package/dist/browser/annotation-manager.d.ts.map +1 -1
- package/dist/browser/browser-manager.d.ts +6 -1
- package/dist/browser/browser-manager.d.ts.map +1 -1
- package/dist/browser/canvas-client.d.ts +53 -0
- package/dist/browser/canvas-client.d.ts.map +1 -0
- package/dist/browser/canvas-code-sync-manager.d.ts +79 -0
- package/dist/browser/canvas-code-sync-manager.d.ts.map +1 -0
- package/dist/browser/canvas-manager.d.ts +94 -0
- package/dist/browser/canvas-manager.d.ts.map +1 -0
- package/dist/browser/canvas-runtime-preview-bridge.d.ts +20 -0
- package/dist/browser/canvas-runtime-preview-bridge.d.ts.map +1 -0
- package/dist/browser/canvas-session-sync-manager.d.ts +21 -0
- package/dist/browser/canvas-session-sync-manager.d.ts.map +1 -0
- package/dist/browser/manager-types.d.ts +13 -1
- package/dist/browser/manager-types.d.ts.map +1 -1
- package/dist/browser/ops-browser-manager.d.ts +11 -1
- package/dist/browser/ops-browser-manager.d.ts.map +1 -1
- package/dist/canvas/code-sync/apply-tsx.d.ts +23 -0
- package/dist/canvas/code-sync/apply-tsx.d.ts.map +1 -0
- package/dist/canvas/code-sync/graph.d.ts +5 -0
- package/dist/canvas/code-sync/graph.d.ts.map +1 -0
- package/dist/canvas/code-sync/hash.d.ts +3 -0
- package/dist/canvas/code-sync/hash.d.ts.map +1 -0
- package/dist/canvas/code-sync/import.d.ts +18 -0
- package/dist/canvas/code-sync/import.d.ts.map +1 -0
- package/dist/canvas/code-sync/manifest.d.ts +5 -0
- package/dist/canvas/code-sync/manifest.d.ts.map +1 -0
- package/dist/canvas/code-sync/tsx-adapter.d.ts +8 -0
- package/dist/canvas/code-sync/tsx-adapter.d.ts.map +1 -0
- package/dist/canvas/code-sync/types.d.ts +152 -0
- package/dist/canvas/code-sync/types.d.ts.map +1 -0
- package/dist/canvas/code-sync/write.d.ts +9 -0
- package/dist/canvas/code-sync/write.d.ts.map +1 -0
- package/dist/canvas/document-store.d.ts +81 -0
- package/dist/canvas/document-store.d.ts.map +1 -0
- package/dist/canvas/export.d.ts +12 -0
- package/dist/canvas/export.d.ts.map +1 -0
- package/dist/canvas/repo-store.d.ts +10 -0
- package/dist/canvas/repo-store.d.ts.map +1 -0
- package/dist/canvas/surface-palette.d.ts +15 -0
- package/dist/canvas/surface-palette.d.ts.map +1 -0
- package/dist/canvas/types.d.ts +255 -0
- package/dist/canvas/types.d.ts.map +1 -0
- package/dist/canvas-runtime-preview-bridge-HBEHXM4T.js +7 -0
- package/dist/canvas-runtime-preview-bridge-HBEHXM4T.js.map +1 -0
- package/dist/{chunk-ST7CO5FA.js → chunk-5J3IFL3X.js} +11577 -13539
- package/dist/chunk-5J3IFL3X.js.map +1 -0
- package/dist/chunk-D633UO34.js +8149 -0
- package/dist/chunk-D633UO34.js.map +1 -0
- package/dist/{chunk-7W3SPXIB.js → chunk-FUSXMW3G.js} +4 -1
- package/dist/chunk-TBUCZX4A.js +34 -0
- package/dist/chunk-TBUCZX4A.js.map +1 -0
- package/dist/chunk-V7KUDHDG.js +276 -0
- package/dist/chunk-V7KUDHDG.js.map +1 -0
- package/dist/chunk-Y2KL55OG.js +59 -0
- package/dist/chunk-Y2KL55OG.js.map +1 -0
- package/dist/cli/args.d.ts +3 -3
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/commands/annotate.d.ts +11 -0
- package/dist/cli/commands/annotate.d.ts.map +1 -1
- package/dist/cli/commands/canvas.d.ts +45 -0
- package/dist/cli/commands/canvas.d.ts.map +1 -0
- package/dist/cli/commands/devtools/perf.d.ts.map +1 -1
- package/dist/cli/commands/devtools/screenshot.d.ts +1 -0
- package/dist/cli/commands/devtools/screenshot.d.ts.map +1 -1
- package/dist/cli/commands/dom/attr.d.ts.map +1 -1
- package/dist/cli/commands/dom/checked.d.ts.map +1 -1
- package/dist/cli/commands/dom/enabled.d.ts.map +1 -1
- package/dist/cli/commands/dom/html.d.ts.map +1 -1
- package/dist/cli/commands/dom/text.d.ts.map +1 -1
- package/dist/cli/commands/dom/value.d.ts.map +1 -1
- package/dist/cli/commands/dom/visible.d.ts.map +1 -1
- package/dist/cli/commands/export/clone-component.d.ts +9 -0
- package/dist/cli/commands/export/clone-component.d.ts.map +1 -1
- package/dist/cli/commands/export/clone-page.d.ts +8 -0
- package/dist/cli/commands/export/clone-page.d.ts.map +1 -1
- package/dist/cli/commands/interact/check.d.ts.map +1 -1
- package/dist/cli/commands/interact/click.d.ts.map +1 -1
- package/dist/cli/commands/interact/hover.d.ts.map +1 -1
- package/dist/cli/commands/interact/press.d.ts.map +1 -1
- package/dist/cli/commands/interact/scroll-into-view.d.ts.map +1 -1
- package/dist/cli/commands/interact/scroll.d.ts.map +1 -1
- package/dist/cli/commands/interact/select.d.ts.map +1 -1
- package/dist/cli/commands/interact/type.d.ts.map +1 -1
- package/dist/cli/commands/interact/uncheck.d.ts.map +1 -1
- package/dist/cli/commands/native.d.ts +12 -1
- package/dist/cli/commands/native.d.ts.map +1 -1
- package/dist/cli/commands/nav/goto.d.ts.map +1 -1
- package/dist/cli/commands/nav/snapshot.d.ts.map +1 -1
- package/dist/cli/commands/nav/wait.d.ts.map +1 -1
- package/dist/cli/commands/serve.d.ts +5 -0
- package/dist/cli/commands/serve.d.ts.map +1 -1
- package/dist/cli/commands/session/connect.d.ts.map +1 -1
- package/dist/cli/commands/status.d.ts +5 -0
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/daemon-commands.d.ts.map +1 -1
- package/dist/cli/help.d.ts +5 -0
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/index.js +724 -163
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/remote-canvas-manager.d.ts +8 -0
- package/dist/cli/remote-canvas-manager.d.ts.map +1 -0
- package/dist/cli/remote-manager.d.ts +3 -1
- package/dist/cli/remote-manager.d.ts.map +1 -1
- package/dist/cli/remote-relay.d.ts +2 -0
- package/dist/cli/remote-relay.d.ts.map +1 -1
- package/dist/cli/utils/parse.d.ts +1 -0
- package/dist/cli/utils/parse.d.ts.map +1 -1
- package/dist/core/bootstrap.d.ts.map +1 -1
- package/dist/core/types.d.ts +2 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/fs-UMRKOBNN.js +7 -0
- package/dist/fs-UMRKOBNN.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +192 -67
- package/dist/index.js.map +1 -1
- package/dist/{macros-NUBRM44Y.js → macros-ND2M7LWU.js} +2 -2
- package/dist/opendevbrowser.d.ts.map +1 -1
- package/dist/opendevbrowser.js +192 -67
- package/dist/opendevbrowser.js.map +1 -1
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/shopping/index.d.ts.map +1 -1
- package/dist/providers-G3LRHQXX.js +121 -0
- package/dist/providers-G3LRHQXX.js.map +1 -0
- package/dist/relay/protocol.d.ts +85 -3
- package/dist/relay/protocol.d.ts.map +1 -1
- package/dist/relay/relay-server.d.ts +14 -1
- package/dist/relay/relay-server.d.ts.map +1 -1
- package/dist/relay/relay-types.d.ts +3 -0
- package/dist/relay/relay-types.d.ts.map +1 -1
- package/dist/runtime-factory-BICHDPE7.js +13 -0
- package/dist/runtime-factory-BICHDPE7.js.map +1 -0
- package/dist/tools/annotate.d.ts.map +1 -1
- package/dist/tools/canvas.d.ts +4 -0
- package/dist/tools/canvas.d.ts.map +1 -0
- package/dist/tools/check.d.ts.map +1 -1
- package/dist/tools/click.d.ts.map +1 -1
- package/dist/tools/clone_component.d.ts.map +1 -1
- package/dist/tools/clone_page.d.ts.map +1 -1
- package/dist/tools/connect.d.ts.map +1 -1
- package/dist/tools/deps.d.ts +2 -0
- package/dist/tools/deps.d.ts.map +1 -1
- package/dist/tools/dom_get_html.d.ts.map +1 -1
- package/dist/tools/dom_get_text.d.ts.map +1 -1
- package/dist/tools/get_attr.d.ts.map +1 -1
- package/dist/tools/get_value.d.ts.map +1 -1
- package/dist/tools/goto.d.ts.map +1 -1
- package/dist/tools/hover.d.ts.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/is_checked.d.ts.map +1 -1
- package/dist/tools/is_enabled.d.ts.map +1 -1
- package/dist/tools/is_visible.d.ts.map +1 -1
- package/dist/tools/launch.d.ts.map +1 -1
- package/dist/tools/macro_resolve.d.ts.map +1 -1
- package/dist/tools/perf.d.ts.map +1 -1
- package/dist/tools/press.d.ts.map +1 -1
- package/dist/tools/product_video_run.d.ts.map +1 -1
- package/dist/tools/research_run.d.ts.map +1 -1
- package/dist/tools/response.d.ts +4 -1
- package/dist/tools/response.d.ts.map +1 -1
- package/dist/tools/screenshot.d.ts.map +1 -1
- package/dist/tools/scroll.d.ts.map +1 -1
- package/dist/tools/scroll_into_view.d.ts.map +1 -1
- package/dist/tools/select.d.ts.map +1 -1
- package/dist/tools/shopping_run.d.ts.map +1 -1
- package/dist/tools/snapshot.d.ts.map +1 -1
- package/dist/tools/type.d.ts.map +1 -1
- package/dist/tools/uncheck.d.ts.map +1 -1
- package/dist/tools/wait.d.ts.map +1 -1
- package/dist/tools/workflow-runtime.d.ts +1 -2
- package/dist/tools/workflow-runtime.d.ts.map +1 -1
- package/extension/canvas.html +636 -0
- package/extension/dist/annotate-content.css +15 -6
- package/extension/dist/annotate-content.js +119 -9
- package/extension/dist/annotation-payload.js +163 -0
- package/extension/dist/background.js +148 -18
- package/extension/dist/canvas/canvas-runtime.js +1061 -0
- package/extension/dist/canvas/model.js +213 -0
- package/extension/dist/canvas/viewport-fit.js +67 -0
- package/extension/dist/canvas-page.js +1801 -0
- package/extension/dist/ops/dom-bridge.js +116 -3
- package/extension/dist/ops/ops-runtime.js +508 -44
- package/extension/dist/ops/ops-session-store.js +21 -114
- package/extension/dist/ops/target-session-coordinator.js +157 -0
- package/extension/dist/popup.js +155 -31
- package/extension/dist/services/ConnectionManager.js +17 -0
- package/extension/dist/services/RelayClient.js +9 -0
- package/extension/dist/services/TabManager.js +35 -12
- package/extension/dist/types.js +2 -0
- package/extension/manifest.json +1 -1
- package/extension/popup.html +52 -0
- package/package.json +6 -4
- package/skills/AGENTS.md +5 -2
- package/skills/opendevbrowser-best-practices/SKILL.md +71 -3
- package/skills/opendevbrowser-best-practices/artifacts/canvas-governance-playbook.md +141 -0
- package/skills/opendevbrowser-best-practices/artifacts/command-channel-reference.md +113 -17
- package/skills/opendevbrowser-best-practices/assets/templates/canvas-blocker-checklist.json +70 -0
- package/skills/opendevbrowser-best-practices/assets/templates/canvas-feedback-eval.json +73 -0
- package/skills/opendevbrowser-best-practices/assets/templates/canvas-generation-plan.v1.json +67 -0
- package/skills/opendevbrowser-best-practices/assets/templates/canvas-handshake-example.json +126 -0
- package/skills/opendevbrowser-best-practices/assets/templates/robustness-checklist.json +57 -0
- package/skills/opendevbrowser-best-practices/assets/templates/surface-audit-checklist.json +7 -3
- package/skills/opendevbrowser-best-practices/scripts/odb-workflow.sh +26 -0
- package/skills/opendevbrowser-best-practices/scripts/run-robustness-audit.sh +82 -1
- package/skills/opendevbrowser-best-practices/scripts/validate-skill-assets.sh +225 -84
- package/dist/chunk-ST7CO5FA.js.map +0 -1
- /package/dist/{chunk-7W3SPXIB.js.map → chunk-FUSXMW3G.js.map} +0 -0
- /package/dist/{macros-NUBRM44Y.js.map → macros-ND2M7LWU.js.map} +0 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
const CODE_SYNC_STATES = new Set([
|
|
2
|
+
"idle",
|
|
3
|
+
"session_join_pending",
|
|
4
|
+
"pull_pending",
|
|
5
|
+
"push_pending",
|
|
6
|
+
"in_sync",
|
|
7
|
+
"drift_detected",
|
|
8
|
+
"conflict",
|
|
9
|
+
"unsupported",
|
|
10
|
+
"lease_lost",
|
|
11
|
+
"projection_fallback"
|
|
12
|
+
]);
|
|
13
|
+
const CODE_SYNC_DRIFT_STATES = new Set([
|
|
14
|
+
"clean",
|
|
15
|
+
"source_changed",
|
|
16
|
+
"document_changed",
|
|
17
|
+
"conflict"
|
|
18
|
+
]);
|
|
19
|
+
const CODE_SYNC_WATCH_STATES = new Set(["idle", "watching", "stopped"]);
|
|
20
|
+
const CODE_SYNC_PROJECTIONS = new Set(["canvas_html", "bound_app_runtime"]);
|
|
21
|
+
const CODE_SYNC_FALLBACK_REASONS = new Set([
|
|
22
|
+
"runtime_bridge_unavailable",
|
|
23
|
+
"runtime_projection_unsupported",
|
|
24
|
+
"runtime_projection_failed",
|
|
25
|
+
"runtime_instrumentation_missing",
|
|
26
|
+
"fallback_canvas_html"
|
|
27
|
+
]);
|
|
28
|
+
const ATTACHED_CLIENT_ROLES = new Set(["lease_holder", "observer"]);
|
|
29
|
+
export function normalizeCanvasSessionSummary(value) {
|
|
30
|
+
const summary = isRecord(value) ? { ...value } : {};
|
|
31
|
+
return {
|
|
32
|
+
...summary,
|
|
33
|
+
canvasSessionId: optionalString(summary.canvasSessionId) ?? undefined,
|
|
34
|
+
mode: optionalString(summary.mode) ?? undefined,
|
|
35
|
+
planStatus: optionalString(summary.planStatus) ?? undefined,
|
|
36
|
+
preflightState: optionalString(summary.preflightState) ?? undefined,
|
|
37
|
+
libraryPolicy: isRecord(summary.libraryPolicy) ? summary.libraryPolicy : undefined,
|
|
38
|
+
componentInventoryCount: optionalNumber(summary.componentInventoryCount) ?? undefined,
|
|
39
|
+
componentSourceKinds: readStringArray(summary.componentSourceKinds),
|
|
40
|
+
attachedClients: Array.isArray(summary.attachedClients)
|
|
41
|
+
? summary.attachedClients.flatMap((entry) => normalizeAttachedClient(entry))
|
|
42
|
+
: [],
|
|
43
|
+
leaseHolderClientId: optionalString(summary.leaseHolderClientId),
|
|
44
|
+
watchState: isCodeSyncWatchState(summary.watchState) ? summary.watchState : undefined,
|
|
45
|
+
codeSyncState: isCodeSyncState(summary.codeSyncState) ? summary.codeSyncState : undefined,
|
|
46
|
+
boundFiles: readStringArray(summary.boundFiles),
|
|
47
|
+
conflictCount: optionalNumber(summary.conflictCount) ?? undefined,
|
|
48
|
+
driftState: isCodeSyncDriftState(summary.driftState) ? summary.driftState : undefined,
|
|
49
|
+
lastImportAt: optionalString(summary.lastImportAt) ?? undefined,
|
|
50
|
+
lastPushAt: optionalString(summary.lastPushAt) ?? undefined,
|
|
51
|
+
bindings: Array.isArray(summary.bindings)
|
|
52
|
+
? summary.bindings.flatMap((entry) => normalizeCodeSyncBindingStatus(entry))
|
|
53
|
+
: []
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export function normalizeCanvasTargetStateSummaries(value) {
|
|
57
|
+
if (!Array.isArray(value)) {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
return value.flatMap((entry) => {
|
|
61
|
+
if (!isRecord(entry)) {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
const targetId = optionalString(entry.targetId);
|
|
65
|
+
const previewMode = normalizePreviewState(entry.previewMode);
|
|
66
|
+
const previewState = normalizePreviewState(entry.previewState);
|
|
67
|
+
if (!targetId || !previewMode || !previewState) {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
return [{
|
|
71
|
+
targetId,
|
|
72
|
+
prototypeId: optionalString(entry.prototypeId),
|
|
73
|
+
previewMode,
|
|
74
|
+
previewState,
|
|
75
|
+
renderStatus: normalizeRenderStatus(entry.renderStatus) ?? undefined,
|
|
76
|
+
degradeReason: optionalString(entry.degradeReason),
|
|
77
|
+
lastRenderedAt: optionalString(entry.lastRenderedAt) ?? undefined,
|
|
78
|
+
projection: isCodeSyncProjectionMode(entry.projection) ? entry.projection : undefined,
|
|
79
|
+
fallbackReason: isCodeSyncFallbackReason(entry.fallbackReason) ? entry.fallbackReason : null,
|
|
80
|
+
parityArtifact: normalizeParityArtifact(entry.parityArtifact)
|
|
81
|
+
}];
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
export function summarizeCanvasProjectionState(summary, targets) {
|
|
85
|
+
const activeProjections = uniqueStrings([
|
|
86
|
+
...targets.flatMap((entry) => entry.projection ? [entry.projection] : []),
|
|
87
|
+
...summary.bindings.flatMap((entry) => entry.projection ? [entry.projection] : [])
|
|
88
|
+
]);
|
|
89
|
+
const fallbackReasons = uniqueStrings(targets.flatMap((entry) => entry.fallbackReason ? [entry.fallbackReason] : []));
|
|
90
|
+
const conflictCount = typeof summary.conflictCount === "number"
|
|
91
|
+
? summary.conflictCount
|
|
92
|
+
: summary.bindings.reduce((sum, entry) => sum + entry.conflictCount, 0);
|
|
93
|
+
return {
|
|
94
|
+
activeProjections,
|
|
95
|
+
fallbackReasons,
|
|
96
|
+
conflictCount,
|
|
97
|
+
watchConflict: summary.watchState === "watching" && (summary.driftState === "conflict" || conflictCount > 0)
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function normalizeAttachedClient(value) {
|
|
101
|
+
if (!isRecord(value)) {
|
|
102
|
+
return [];
|
|
103
|
+
}
|
|
104
|
+
const clientId = optionalString(value.clientId);
|
|
105
|
+
const attachedAt = optionalString(value.attachedAt);
|
|
106
|
+
const lastSeenAt = optionalString(value.lastSeenAt);
|
|
107
|
+
if (!clientId || !attachedAt || !lastSeenAt) {
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
return [{
|
|
111
|
+
clientId,
|
|
112
|
+
role: ATTACHED_CLIENT_ROLES.has(value.role)
|
|
113
|
+
? value.role
|
|
114
|
+
: "observer",
|
|
115
|
+
attachedAt,
|
|
116
|
+
lastSeenAt
|
|
117
|
+
}];
|
|
118
|
+
}
|
|
119
|
+
function normalizeCodeSyncBindingStatus(value) {
|
|
120
|
+
if (!isRecord(value)) {
|
|
121
|
+
return [];
|
|
122
|
+
}
|
|
123
|
+
const bindingId = optionalString(value.bindingId);
|
|
124
|
+
const nodeId = optionalString(value.nodeId);
|
|
125
|
+
const repoPath = optionalString(value.repoPath);
|
|
126
|
+
const adapter = optionalString(value.adapter);
|
|
127
|
+
const syncMode = optionalString(value.syncMode);
|
|
128
|
+
const projection = isCodeSyncProjectionMode(value.projection) ? value.projection : null;
|
|
129
|
+
const state = isCodeSyncState(value.state) ? value.state : null;
|
|
130
|
+
const driftState = isCodeSyncDriftState(value.driftState) ? value.driftState : null;
|
|
131
|
+
if (!bindingId || !nodeId || !repoPath || !adapter || !syncMode || !projection || !state || !driftState) {
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
return [{
|
|
135
|
+
bindingId,
|
|
136
|
+
nodeId,
|
|
137
|
+
repoPath,
|
|
138
|
+
adapter,
|
|
139
|
+
syncMode,
|
|
140
|
+
projection,
|
|
141
|
+
state,
|
|
142
|
+
driftState,
|
|
143
|
+
watchEnabled: value.watchEnabled === true,
|
|
144
|
+
lastImportedAt: optionalString(value.lastImportedAt) ?? undefined,
|
|
145
|
+
lastPushedAt: optionalString(value.lastPushedAt) ?? undefined,
|
|
146
|
+
conflictCount: optionalNumber(value.conflictCount) ?? 0,
|
|
147
|
+
unsupportedCount: optionalNumber(value.unsupportedCount) ?? 0
|
|
148
|
+
}];
|
|
149
|
+
}
|
|
150
|
+
function normalizeParityArtifact(value) {
|
|
151
|
+
if (!isRecord(value)) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
const projection = isCodeSyncProjectionMode(value.projection) ? value.projection : null;
|
|
155
|
+
const rootBindingId = optionalString(value.rootBindingId);
|
|
156
|
+
const capturedAt = optionalString(value.capturedAt);
|
|
157
|
+
const hierarchyHash = optionalString(value.hierarchyHash);
|
|
158
|
+
if (!projection || !rootBindingId || !capturedAt || !hierarchyHash) {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
const nodeCount = Array.isArray(value.nodes)
|
|
162
|
+
? value.nodes.length
|
|
163
|
+
: optionalNumber(value.nodeCount) ?? 0;
|
|
164
|
+
return {
|
|
165
|
+
projection,
|
|
166
|
+
rootBindingId,
|
|
167
|
+
capturedAt,
|
|
168
|
+
hierarchyHash,
|
|
169
|
+
nodeCount
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
function normalizePreviewState(value) {
|
|
173
|
+
return value === "focused" || value === "pinned" || value === "background" || value === "degraded"
|
|
174
|
+
? value
|
|
175
|
+
: null;
|
|
176
|
+
}
|
|
177
|
+
function normalizeRenderStatus(value) {
|
|
178
|
+
return value === "idle" || value === "rendered" || value === "degraded"
|
|
179
|
+
? value
|
|
180
|
+
: null;
|
|
181
|
+
}
|
|
182
|
+
function isCodeSyncState(value) {
|
|
183
|
+
return typeof value === "string" && CODE_SYNC_STATES.has(value);
|
|
184
|
+
}
|
|
185
|
+
function isCodeSyncDriftState(value) {
|
|
186
|
+
return typeof value === "string" && CODE_SYNC_DRIFT_STATES.has(value);
|
|
187
|
+
}
|
|
188
|
+
function isCodeSyncWatchState(value) {
|
|
189
|
+
return typeof value === "string" && CODE_SYNC_WATCH_STATES.has(value);
|
|
190
|
+
}
|
|
191
|
+
function isCodeSyncProjectionMode(value) {
|
|
192
|
+
return typeof value === "string" && CODE_SYNC_PROJECTIONS.has(value);
|
|
193
|
+
}
|
|
194
|
+
function isCodeSyncFallbackReason(value) {
|
|
195
|
+
return typeof value === "string" && CODE_SYNC_FALLBACK_REASONS.has(value);
|
|
196
|
+
}
|
|
197
|
+
function readStringArray(value) {
|
|
198
|
+
return Array.isArray(value)
|
|
199
|
+
? value.filter((entry) => typeof entry === "string" && entry.trim().length > 0)
|
|
200
|
+
: [];
|
|
201
|
+
}
|
|
202
|
+
function uniqueStrings(values) {
|
|
203
|
+
return [...new Set(values)];
|
|
204
|
+
}
|
|
205
|
+
function optionalString(value) {
|
|
206
|
+
return typeof value === "string" && value.trim().length > 0 ? value : null;
|
|
207
|
+
}
|
|
208
|
+
function optionalNumber(value) {
|
|
209
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
210
|
+
}
|
|
211
|
+
function isRecord(value) {
|
|
212
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
213
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export const DEFAULT_EDITOR_VIEWPORT = {
|
|
2
|
+
x: 120,
|
|
3
|
+
y: 96,
|
|
4
|
+
zoom: 1
|
|
5
|
+
};
|
|
6
|
+
const MIN_ZOOM = 0.35;
|
|
7
|
+
const MAX_ZOOM = 2.4;
|
|
8
|
+
const DEFAULT_STAGE_WIDTH = 960;
|
|
9
|
+
const DEFAULT_STAGE_HEIGHT = 640;
|
|
10
|
+
const FIT_PADDING = 48;
|
|
11
|
+
const clamp = (value, min, max) => {
|
|
12
|
+
return Math.min(Math.max(value, min), max);
|
|
13
|
+
};
|
|
14
|
+
const roundZoom = (value) => {
|
|
15
|
+
return Math.round(value * 100) / 100;
|
|
16
|
+
};
|
|
17
|
+
const resolveStageSize = (value, fallback) => {
|
|
18
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
|
|
19
|
+
};
|
|
20
|
+
export const isDefaultEditorViewport = (viewport) => {
|
|
21
|
+
return viewport.x === DEFAULT_EDITOR_VIEWPORT.x
|
|
22
|
+
&& viewport.y === DEFAULT_EDITOR_VIEWPORT.y
|
|
23
|
+
&& viewport.zoom === DEFAULT_EDITOR_VIEWPORT.zoom;
|
|
24
|
+
};
|
|
25
|
+
export const computeViewportCanvasCenter = (viewport, stageWidth, stageHeight) => {
|
|
26
|
+
const safeStageWidth = resolveStageSize(stageWidth, DEFAULT_STAGE_WIDTH);
|
|
27
|
+
const safeStageHeight = resolveStageSize(stageHeight, DEFAULT_STAGE_HEIGHT);
|
|
28
|
+
return {
|
|
29
|
+
x: (safeStageWidth / 2 - viewport.x) / viewport.zoom,
|
|
30
|
+
y: (safeStageHeight / 2 - viewport.y) / viewport.zoom
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
const computeNodeBounds = (nodes) => {
|
|
34
|
+
if (nodes.length === 0) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const minX = Math.min(...nodes.map((node) => node.rect.x));
|
|
38
|
+
const minY = Math.min(...nodes.map((node) => node.rect.y));
|
|
39
|
+
const maxX = Math.max(...nodes.map((node) => node.rect.x + node.rect.width));
|
|
40
|
+
const maxY = Math.max(...nodes.map((node) => node.rect.y + node.rect.height));
|
|
41
|
+
return {
|
|
42
|
+
minX,
|
|
43
|
+
minY,
|
|
44
|
+
width: Math.max(maxX - minX, 1),
|
|
45
|
+
height: Math.max(maxY - minY, 1)
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
export const computeFittedViewport = (nodes, stageWidth, stageHeight) => {
|
|
49
|
+
const bounds = computeNodeBounds(nodes);
|
|
50
|
+
if (!bounds) {
|
|
51
|
+
return { ...DEFAULT_EDITOR_VIEWPORT };
|
|
52
|
+
}
|
|
53
|
+
const safeStageWidth = resolveStageSize(stageWidth, DEFAULT_STAGE_WIDTH);
|
|
54
|
+
const safeStageHeight = resolveStageSize(stageHeight, DEFAULT_STAGE_HEIGHT);
|
|
55
|
+
const availableWidth = Math.max(safeStageWidth - FIT_PADDING * 2, 160);
|
|
56
|
+
const availableHeight = Math.max(safeStageHeight - FIT_PADDING * 2, 160);
|
|
57
|
+
const nextZoom = clamp(Math.min(availableWidth / bounds.width, availableHeight / bounds.height, 1), MIN_ZOOM, MAX_ZOOM);
|
|
58
|
+
const zoom = roundZoom(nextZoom);
|
|
59
|
+
const centeredX = (safeStageWidth - bounds.width * zoom) / 2 - bounds.minX * zoom;
|
|
60
|
+
const centeredY = (safeStageHeight - bounds.height * zoom) / 2 - bounds.minY * zoom;
|
|
61
|
+
const anchoredY = DEFAULT_EDITOR_VIEWPORT.y - bounds.minY * zoom;
|
|
62
|
+
return {
|
|
63
|
+
x: Math.round(centeredX),
|
|
64
|
+
y: Math.round(Math.min(centeredY, anchoredY)),
|
|
65
|
+
zoom
|
|
66
|
+
};
|
|
67
|
+
};
|