@archie/devtools 0.0.21 → 0.0.23
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 +6 -0
- package/dist/client/client.d.mts +3 -1
- package/dist/client/client.d.ts +3 -1
- package/dist/client/client.js +289 -142
- package/dist/client/client.mjs +252 -104
- package/dist/index.d.mts +182 -1
- package/dist/index.d.ts +182 -1
- package/dist/index.js +343 -47
- package/dist/index.mjs +343 -47
- package/dist/inspector.standalone.js +145 -6
- package/package.json +2 -3
|
@@ -95,6 +95,28 @@
|
|
|
95
95
|
var FIBER_KEY_PREFIX = "__reactFiber$"
|
|
96
96
|
var PROPS_KEY_PREFIX = "__reactProps$"
|
|
97
97
|
|
|
98
|
+
// ARCH-883 P0-1: babel-plugin-editor-meta.ts (TypeScript context) now
|
|
99
|
+
// emits __editorMeta as a zero-arg function, not the object literal
|
|
100
|
+
// directly, so React never writes it into the DOM. Every extraction
|
|
101
|
+
// site below must invoke the value when it is a function. Mirrors
|
|
102
|
+
// readEditorMetaValue in fiber-bridge.ts — if this changes, update
|
|
103
|
+
// that copy to maintain parity.
|
|
104
|
+
function resolveEditorMetaValue(value) {
|
|
105
|
+
if (typeof value === "function") {
|
|
106
|
+
// Each call re-evaluates the plugin-emitted `() => ({...})`
|
|
107
|
+
// closure and returns a FRESH object literal — never rely on
|
|
108
|
+
// meta object identity (`===`) across two separate reads, even
|
|
109
|
+
// within the same render (mirrors readEditorMetaValue in
|
|
110
|
+
// fiber-bridge.ts).
|
|
111
|
+
return value()
|
|
112
|
+
}
|
|
113
|
+
// Twin parity with fiber-bridge.ts's readEditorMetaValue: only
|
|
114
|
+
// undefined/null is a miss, not "any falsy value" — __editorMeta is
|
|
115
|
+
// always an object or a function in practice, so this is a no-op
|
|
116
|
+
// today, but keeps the two implementations provably equivalent.
|
|
117
|
+
return value === undefined || value === null ? null : value
|
|
118
|
+
}
|
|
119
|
+
|
|
98
120
|
function hasEditorMetaInFiberChain(fiber) {
|
|
99
121
|
var current = fiber
|
|
100
122
|
while (current) {
|
|
@@ -195,7 +217,7 @@
|
|
|
195
217
|
var fiber = getFiberFromElement(el)
|
|
196
218
|
while (fiber) {
|
|
197
219
|
if (fiber.memoizedProps && fiber.memoizedProps.__editorMeta) {
|
|
198
|
-
return fiber.memoizedProps.__editorMeta
|
|
220
|
+
return resolveEditorMetaValue(fiber.memoizedProps.__editorMeta)
|
|
199
221
|
}
|
|
200
222
|
fiber = fiber["return"]
|
|
201
223
|
}
|
|
@@ -205,7 +227,7 @@
|
|
|
205
227
|
function getDirectEditorMetaFromElement(el) {
|
|
206
228
|
var fiber = getFiberFromElement(el)
|
|
207
229
|
if (fiber && fiber.memoizedProps && fiber.memoizedProps.__editorMeta) {
|
|
208
|
-
return fiber.memoizedProps.__editorMeta
|
|
230
|
+
return resolveEditorMetaValue(fiber.memoizedProps.__editorMeta)
|
|
209
231
|
}
|
|
210
232
|
return null
|
|
211
233
|
}
|
|
@@ -231,7 +253,7 @@
|
|
|
231
253
|
break
|
|
232
254
|
}
|
|
233
255
|
if (current.memoizedProps && current.memoizedProps.__editorMeta) {
|
|
234
|
-
return current.memoizedProps.__editorMeta
|
|
256
|
+
return resolveEditorMetaValue(current.memoizedProps.__editorMeta)
|
|
235
257
|
}
|
|
236
258
|
current = current["return"]
|
|
237
259
|
}
|
|
@@ -400,6 +422,12 @@
|
|
|
400
422
|
return normalizedTarget
|
|
401
423
|
}
|
|
402
424
|
|
|
425
|
+
// Palette-inserted elements have no React fiber and no source ref, so
|
|
426
|
+
// the source-signature walk below would skip past them and select the
|
|
427
|
+
// nearest ancestor with a source ref (the original <section>/<main>).
|
|
428
|
+
// We tag them with `data-dnd-force-allow` precisely to claim their
|
|
429
|
+
// own identity for selection/arrange; honor that tag here so a click
|
|
430
|
+
// on an inserted Card / Hero / Table targets the insert itself.
|
|
403
431
|
var current = normalizedTarget
|
|
404
432
|
while (
|
|
405
433
|
current &&
|
|
@@ -407,6 +435,9 @@
|
|
|
407
435
|
current !== document.documentElement &&
|
|
408
436
|
!isInspectorElement(current)
|
|
409
437
|
) {
|
|
438
|
+
if (current.hasAttribute && current.hasAttribute("data-dnd-force-allow")) {
|
|
439
|
+
return current
|
|
440
|
+
}
|
|
410
441
|
if (getExactSourceSignatureFromElement(current)) {
|
|
411
442
|
return current
|
|
412
443
|
}
|
|
@@ -855,9 +886,14 @@
|
|
|
855
886
|
postMessageToParent({
|
|
856
887
|
type: "INSPECTOR_SCRIPT_LOADED",
|
|
857
888
|
timestamp: Date.now(),
|
|
858
|
-
version: "2.
|
|
889
|
+
version: "2.1.1",
|
|
859
890
|
protocolVersion: 1,
|
|
860
891
|
capabilities: {
|
|
892
|
+
// 2.1.1: function-valued __editorMeta props are invoked before any
|
|
893
|
+
// postMessage, so meta payloads stay structured-cloneable. Hosts can
|
|
894
|
+
// gate on this bit to confirm the deployed CDN artifact carries the
|
|
895
|
+
// fix (the 2.1.0 URL is overwritten in place on publish).
|
|
896
|
+
functionValuedEditorMeta: true,
|
|
861
897
|
inspect: true,
|
|
862
898
|
dndMove: true,
|
|
863
899
|
dndResize: true,
|
|
@@ -865,6 +901,11 @@
|
|
|
865
901
|
hostControlledHistory: true,
|
|
866
902
|
arrangeStructuredHistory: true,
|
|
867
903
|
arrangeStrongNodeIdentity: true,
|
|
904
|
+
// Unified mode: SET_EDITOR_MODE "inspect" also enables the arrange
|
|
905
|
+
// (design) runtime — selection and drag/resize coexist. Hosts MUST
|
|
906
|
+
// feature-detect on this flag: a frozen 2.0.x inspector disables
|
|
907
|
+
// design mode on "inspect" and needs the legacy "design" mode.
|
|
908
|
+
unifiedInspectArrange: true,
|
|
868
909
|
},
|
|
869
910
|
})
|
|
870
911
|
|
|
@@ -902,6 +943,35 @@
|
|
|
902
943
|
var inspectorCleanupMap = new WeakMap()
|
|
903
944
|
var BADGE_UPDATE_DELAY_MS = 50
|
|
904
945
|
|
|
946
|
+
/**
|
|
947
|
+
* Bridge to design-mode store: publish current inspector selection as
|
|
948
|
+
* DND nodeIds so arrange overlay knows when to show resize handles +
|
|
949
|
+
* enable drag (single-select only). If the design-mode bundle hasn't
|
|
950
|
+
* mounted yet, buffer the latest selection for it to drain on mount.
|
|
951
|
+
*/
|
|
952
|
+
function publishSelectionToDesignMode() {
|
|
953
|
+
var ids = []
|
|
954
|
+
for (var i = 0; i < selectedElements.length; i += 1) {
|
|
955
|
+
var el = selectedElements[i]
|
|
956
|
+
if (!el || typeof el.getAttribute !== "function") continue
|
|
957
|
+
var nodeId = el.getAttribute("data-dnd-node-id")
|
|
958
|
+
if (nodeId) ids.push(nodeId)
|
|
959
|
+
}
|
|
960
|
+
var bridge = window.__ARCHIE_DESIGN_MODE__
|
|
961
|
+
if (bridge && typeof bridge.setInspectorSelection === "function") {
|
|
962
|
+
try {
|
|
963
|
+
bridge.setInspectorSelection(ids)
|
|
964
|
+
} catch (err) {
|
|
965
|
+
// Defensive: never let a bridge error break inspector selection.
|
|
966
|
+
if (window._inspectorDebug) {
|
|
967
|
+
console.warn("[archie-inspector] design-mode bridge error", err)
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
} else {
|
|
971
|
+
window.__ARCHIE_DESIGN_MODE_PENDING__ = ids
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
|
|
905
975
|
if (!window._inspectorSelectedElement) {
|
|
906
976
|
window._inspectorSelectedElement = null
|
|
907
977
|
}
|
|
@@ -925,7 +995,12 @@
|
|
|
925
995
|
element === overlay ||
|
|
926
996
|
element === selectedElementBadge ||
|
|
927
997
|
element.id === "inspector-ping-effect" ||
|
|
928
|
-
(element.closest && element.closest("[data-inspector-badge]"))
|
|
998
|
+
(element.closest && element.closest("[data-inspector-badge]")) ||
|
|
999
|
+
// Design-mode (arrange) overlay elements: HitArea, resize handles,
|
|
1000
|
+
// drop-line, etc. These belong to the unified visual editor and must
|
|
1001
|
+
// pass mousedown/click events through to React (dnd-kit) instead of
|
|
1002
|
+
// being treated as inspect targets.
|
|
1003
|
+
(element.closest && element.closest("[data-design-mode-ui]"))
|
|
929
1004
|
)
|
|
930
1005
|
}
|
|
931
1006
|
|
|
@@ -1366,6 +1441,7 @@
|
|
|
1366
1441
|
window._inspectorSelectedElement = null
|
|
1367
1442
|
lastMultiSelectIntent = false
|
|
1368
1443
|
isInspecting = true
|
|
1444
|
+
publishSelectionToDesignMode()
|
|
1369
1445
|
|
|
1370
1446
|
const applyCursorStyles = () => {
|
|
1371
1447
|
if (document.body) {
|
|
@@ -1396,6 +1472,7 @@
|
|
|
1396
1472
|
window.__ARCHIE_INSPECTOR__.selectedElement = null
|
|
1397
1473
|
}
|
|
1398
1474
|
lastMultiSelectIntent = false
|
|
1475
|
+
publishSelectionToDesignMode()
|
|
1399
1476
|
try {
|
|
1400
1477
|
safeQuerySelectorAll('[data-inspector-editing="true"]').forEach(
|
|
1401
1478
|
function (el) {
|
|
@@ -1422,6 +1499,12 @@
|
|
|
1422
1499
|
)
|
|
1423
1500
|
}
|
|
1424
1501
|
|
|
1502
|
+
// Last mode explicitly commanded by the host via SET_EDITOR_MODE. Used
|
|
1503
|
+
// to (a) make repeated "inspect" commands selection-preserving no-ops
|
|
1504
|
+
// and (b) suppress design-mode runtime echoes that would otherwise be
|
|
1505
|
+
// misread by the host as a stale mode (see runtimeBridgeHandler).
|
|
1506
|
+
var hostCommandedEditorMode = "off"
|
|
1507
|
+
|
|
1425
1508
|
function setEditorModeFromHost(mode, options) {
|
|
1426
1509
|
var historyMode =
|
|
1427
1510
|
options && options.hostControlledHistory ? "host" : "local"
|
|
@@ -1439,14 +1522,30 @@
|
|
|
1439
1522
|
historyMode: historyMode,
|
|
1440
1523
|
})
|
|
1441
1524
|
|
|
1525
|
+
hostCommandedEditorMode = mode === "inspect" || mode === "design" ? mode : "off"
|
|
1526
|
+
|
|
1442
1527
|
if (mode === "inspect") {
|
|
1443
|
-
|
|
1528
|
+
// Unified mode: visual editor (inspect) + arrange (design) coexist.
|
|
1529
|
+
// The arrange overlay stays passive until the inspector publishes a
|
|
1530
|
+
// single-element selection (via publishSelectionToDesignMode), at
|
|
1531
|
+
// which point it lights up the resize/drag controls on that element.
|
|
1532
|
+
dispatchHostCommand({ type: "set-design-mode", enabled: true })
|
|
1533
|
+
if (isInspecting) {
|
|
1534
|
+
// Recovery re-send (focus/visibility/online): the session is
|
|
1535
|
+
// already live. Activating again would wipe the user's current
|
|
1536
|
+
// selection and retract the arrange handles mid-session — echo
|
|
1537
|
+
// confirmation only.
|
|
1538
|
+
postMessageToParent({ type: "EDITOR_MODE_CHANGED", mode: "inspect" })
|
|
1539
|
+
return
|
|
1540
|
+
}
|
|
1444
1541
|
activateInspectionMode()
|
|
1445
1542
|
postMessageToParent({ type: "EDITOR_MODE_CHANGED", mode: "inspect" })
|
|
1446
1543
|
return
|
|
1447
1544
|
}
|
|
1448
1545
|
|
|
1449
1546
|
if (mode === "design") {
|
|
1547
|
+
// Legacy "design-only" mode kept for backwards compatibility with
|
|
1548
|
+
// hosts that haven't migrated to the unified flow.
|
|
1450
1549
|
deactivateInspectionMode({ notifyParent: false })
|
|
1451
1550
|
dispatchHostCommand({ type: "set-design-mode", enabled: true })
|
|
1452
1551
|
postMessageToParent({ type: "EDITOR_MODE_CHANGED", mode: "design" })
|
|
@@ -1948,6 +2047,19 @@
|
|
|
1948
2047
|
: null,
|
|
1949
2048
|
attributes: attributes,
|
|
1950
2049
|
inspectorSource: inspectorInfo,
|
|
2050
|
+
// ARCH-883 F1 — FORWARD THE META WHOLE. The plugin now also emits
|
|
2051
|
+
// `slot`, `propBindings` and `propOwner` (SDD §2.3/§2.6) and the editor
|
|
2052
|
+
// host routes edits off them; field-picking here would silently strip
|
|
2053
|
+
// them and turn every kit-internal edit into a gap. `inspectorSource`
|
|
2054
|
+
// above is the deliberately narrow structure — this one is not.
|
|
2055
|
+
//
|
|
2056
|
+
// Unlike P0-1 this needs no deploy ordering: the extra keys are plain
|
|
2057
|
+
// data, so an already-published standalone.js forwards them unchanged
|
|
2058
|
+
// through `postMessage`'s structured clone. Whether a given PAGE has
|
|
2059
|
+
// them depends on the plugin that built it, which the host resolves via
|
|
2060
|
+
// `deriveEditorCapabilities(kitRuntimeVersion)` (SDD §2.5) — never from
|
|
2061
|
+
// this script's version. The slot string is opaque here; validating it
|
|
2062
|
+
// against kit-runtime's `slot-vocabulary` is the host's job.
|
|
1951
2063
|
editorMeta: editorMeta ? editorMeta.meta : null,
|
|
1952
2064
|
computedStyles: {
|
|
1953
2065
|
display: computed.display,
|
|
@@ -2399,6 +2511,16 @@
|
|
|
2399
2511
|
}
|
|
2400
2512
|
|
|
2401
2513
|
if (detail.type === "design-mode-changed") {
|
|
2514
|
+
// In unified inspect the arrange overlay flips its internal
|
|
2515
|
+
// design-mode store as a side effect ("design" on mount, "off" on
|
|
2516
|
+
// teardown). Forwarding those flips while the host commanded
|
|
2517
|
+
// "inspect" makes the host see a stale mode and re-send
|
|
2518
|
+
// SET_EDITOR_MODE, which wipes the in-iframe selection. The host
|
|
2519
|
+
// only needs runtime-originated mode changes in the legacy
|
|
2520
|
+
// design-only flow.
|
|
2521
|
+
if (hostCommandedEditorMode === "inspect") {
|
|
2522
|
+
return
|
|
2523
|
+
}
|
|
2402
2524
|
postMessageToParent({
|
|
2403
2525
|
type: "EDITOR_MODE_CHANGED",
|
|
2404
2526
|
mode: detail.mode || "off",
|
|
@@ -3090,6 +3212,7 @@
|
|
|
3090
3212
|
}
|
|
3091
3213
|
|
|
3092
3214
|
updateSharedHighlights()
|
|
3215
|
+
publishSelectionToDesignMode()
|
|
3093
3216
|
postMessageToParent({
|
|
3094
3217
|
type: "ELEMENT_REMOVED",
|
|
3095
3218
|
requestId: event.data.requestId,
|
|
@@ -3344,6 +3467,20 @@
|
|
|
3344
3467
|
const inspectorClickHandler = function (e) {
|
|
3345
3468
|
if (!isInspecting) return
|
|
3346
3469
|
|
|
3470
|
+
// If the event originated on a design-mode (arrange) overlay element —
|
|
3471
|
+
// HitArea, resize handle, drop-line — let it propagate untouched so
|
|
3472
|
+
// dnd-kit can pick it up. Without this early-return, getElementFromPoint
|
|
3473
|
+
// below would resolve to the real element underneath the overlay and
|
|
3474
|
+
// the inspector would swallow the pointerdown via stopImmediatePropagation,
|
|
3475
|
+
// breaking arrange drag/resize on the selected element.
|
|
3476
|
+
if (
|
|
3477
|
+
e.target &&
|
|
3478
|
+
typeof e.target.closest === "function" &&
|
|
3479
|
+
e.target.closest("[data-design-mode-ui]")
|
|
3480
|
+
) {
|
|
3481
|
+
return
|
|
3482
|
+
}
|
|
3483
|
+
|
|
3347
3484
|
// Prefer e.target: browser already set it to the element under the pointer (e.g. input).
|
|
3348
3485
|
// getElementFromPoint is fallback when overlay or stacking returns something else.
|
|
3349
3486
|
let target = null
|
|
@@ -3469,6 +3606,7 @@
|
|
|
3469
3606
|
type: "ELEMENT_SELECTED",
|
|
3470
3607
|
metadata: metadataPayload,
|
|
3471
3608
|
})
|
|
3609
|
+
publishSelectionToDesignMode()
|
|
3472
3610
|
// Keep inspector active - don't set isInspecting = false
|
|
3473
3611
|
// User can continue navigating between elements
|
|
3474
3612
|
}
|
|
@@ -3515,6 +3653,7 @@
|
|
|
3515
3653
|
if (window.__ARCHIE_INSPECTOR__)
|
|
3516
3654
|
window.__ARCHIE_INSPECTOR__.selectedElement = null
|
|
3517
3655
|
updateSharedHighlights()
|
|
3656
|
+
publishSelectionToDesignMode()
|
|
3518
3657
|
postMessageToParent({ type: "INSPECTION_CANCELLED" })
|
|
3519
3658
|
}
|
|
3520
3659
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@archie/devtools",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.23",
|
|
4
4
|
"description": "DevTools for Archie generated applications - Route synchronization and editor communication",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -29,9 +29,8 @@
|
|
|
29
29
|
"scripts": {
|
|
30
30
|
"test": "vitest run",
|
|
31
31
|
"test:watch": "vitest",
|
|
32
|
-
"inspector:local": "node scripts/generate-inspector-local.js",
|
|
33
32
|
"build": "tsup",
|
|
34
|
-
"
|
|
33
|
+
"build:local": "ARCHIE_INSPECTOR_INCLUDE_STANDALONE=1 tsup",
|
|
35
34
|
"typecheck": "tsc --noEmit",
|
|
36
35
|
"release": "node publish.js"
|
|
37
36
|
},
|