@archie/devtools 0.0.29 → 0.0.30

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.
@@ -615,6 +615,122 @@
615
615
  }
616
616
  }
617
617
 
618
+ // ARCH-1065 M3 (v2.3.0) — the nearest data-agent-row-bearing element
619
+ // SELF-outward. This is `nearestRowId` above but returning the ELEMENT
620
+ // (not just its id), because QUERY_COLLECTION_ORDER needs the row
621
+ // root's sibling `data-agent-entity`/`data-agent-collection-order`
622
+ // frame too, not only the row id. Nested collections resolve correctly
623
+ // "for free": walking self-outward finds the INNERMOST row root first,
624
+ // i.e. the nearest enclosing collection of the target node.
625
+ function nearestRowRootElement(el) {
626
+ var node = el
627
+ for (var depth = 0; node && depth < MAX_ANCHOR_CHAIN; depth++) {
628
+ if (node.nodeType === 1 && typeof node.getAttribute === "function") {
629
+ var rowId = node.getAttribute("data-agent-row")
630
+ if (typeof rowId === "string" && rowId !== "") return node
631
+ }
632
+ node = node.parentElement
633
+ }
634
+ return null
635
+ }
636
+
637
+ // The first row-root element stamped with the given entity name,
638
+ // anywhere in the document. Used when QUERY_COLLECTION_ORDER is
639
+ // addressed by `entity` alone (no `selector`) — the entity-name
640
+ // targeting mode.
641
+ function findFirstRowRootForEntity(entity) {
642
+ if (typeof entity !== "string" || entity === "") return null
643
+ try {
644
+ return safeQuerySelector(
645
+ '[data-agent-entity="' +
646
+ escapeAttributeSelectorValue(entity) +
647
+ '"][data-agent-row]'
648
+ )
649
+ } catch (e) {
650
+ return null
651
+ }
652
+ }
653
+
654
+ // Every row root that belongs to the SAME collection instantiation as
655
+ // `rowRootEl`: the babel codemod (M2) stamps each `.map()` row's root
656
+ // element as a DIRECT child of whatever wraps the `.map()` call, so
657
+ // siblings sharing `data-agent-entity` under `rowRootEl`'s parent ARE
658
+ // the collection, in DOM order. Falls back to `[rowRootEl]` alone when
659
+ // no parent is reachable (defensive — should not happen for an
660
+ // attached element).
661
+ function collectionRowElements(rowRootEl, entity) {
662
+ var parent = rowRootEl.parentElement
663
+ if (!parent) return [rowRootEl]
664
+ var siblings = []
665
+ var kids = parent.children
666
+ for (var i = 0; i < kids.length; i++) {
667
+ var kid = kids[i]
668
+ if (
669
+ kid.nodeType === 1 &&
670
+ typeof kid.getAttribute === "function" &&
671
+ kid.getAttribute("data-agent-entity") === entity &&
672
+ kid.hasAttribute("data-agent-row")
673
+ ) {
674
+ siblings.push(kid)
675
+ }
676
+ }
677
+ return siblings.length > 0 ? siblings : [rowRootEl]
678
+ }
679
+
680
+ // ARCH-1065 M3 (v2.3.0) — {entity, order, rowIds, rowCount} for the
681
+ // collection enclosing a target node, read live off the DOM
682
+ // (data-agent-entity/-row/-collection-order, D18) and cross-checked
683
+ // against window.__slice[entity].length when the slice is available.
684
+ //
685
+ // `order` fails CLOSED ("derived") on anything but an explicit
686
+ // "stable" attribute value. babel-plugin-collection-binding stamps
687
+ // entity/row/collection-order ATOMICALLY — three addAttr calls back to
688
+ // back with no branch between them — and no other emitter of
689
+ // data-agent-row exists. So data-agent-row present WITHOUT
690
+ // data-agent-collection-order can only mean the stamping contract
691
+ // never ran for this element: the order is UNKNOWN, not "stable".
692
+ // Defaulting unknown to "stable" would let the FE permit a drag whose
693
+ // Save can't be honored (silent, user-visible corruption); defaulting
694
+ // to "derived" only disables reorder on markup we can't vouch for.
695
+ function queryCollectionOrder(rowRootEl) {
696
+ if (!rowRootEl) return null
697
+ var entity = rowRootEl.getAttribute("data-agent-entity")
698
+ if (typeof entity !== "string" || entity === "") return null
699
+
700
+ var orderAttr = rowRootEl.getAttribute("data-agent-collection-order")
701
+ var order = orderAttr === "stable" ? "stable" : "derived"
702
+
703
+ var rowElements = collectionRowElements(rowRootEl, entity)
704
+ var rowIds = []
705
+ for (var i = 0; i < rowElements.length; i++) {
706
+ var rowId = rowElements[i].getAttribute("data-agent-row")
707
+ if (typeof rowId === "string" && rowId !== "") rowIds.push(rowId)
708
+ }
709
+ var domRowCount = rowIds.length
710
+
711
+ var sliceRows = resolveSliceEntityRows(entity)
712
+ var sliceRowCount = sliceRows ? sliceRows.length : null
713
+
714
+ // `rowCount` is the A17 primary field — DOM population, the same
715
+ // rows the FE samples values from. `domRowCount`/`sliceRowCount` are
716
+ // the divergence-diagnostic pair (identical to rowCount when the
717
+ // slice agrees, or absent from parity entirely when the slice is
718
+ // unavailable). Known limit: two same-entity `.map()`s that happen
719
+ // to share one DOM parent merge into a single reported collection —
720
+ // rare by construction (siblings of a `.map()` output share a
721
+ // parent by definition), and there is no collection-INSTANCE stamp
722
+ // (only per-row entity/row/order) to disambiguate two side-by-side
723
+ // instantiations of the same entity.
724
+ return {
725
+ entity: entity,
726
+ order: order,
727
+ rowIds: rowIds,
728
+ rowCount: domRowCount,
729
+ domRowCount: domRowCount,
730
+ sliceRowCount: sliceRowCount,
731
+ }
732
+ }
733
+
618
734
  if (window._inspectorSharedTargetObserver) {
619
735
  try {
620
736
  window._inspectorSharedTargetObserver.disconnect()
@@ -1231,7 +1347,10 @@
1231
1347
  // `QUERY_SLICE_FIELD` in the message protocol, and
1232
1348
  // `capabilities.bindingContract` below. No existing field changed
1233
1349
  // shape, so `protocolVersion` stays 1.
1234
- version: "2.2.0",
1350
+ // 2.3.0 (ARCH-1065 A17-support): additive only — `QUERY_COLLECTION_ORDER`
1351
+ // in the message protocol and `capabilities.collectionOrderQuery`
1352
+ // below. No existing field changed shape, so `protocolVersion` stays 1.
1353
+ version: "2.3.0",
1235
1354
  protocolVersion: 1,
1236
1355
  capabilities: {
1237
1356
  // 2.1.1: function-valued __editorMeta props are invoked before any
@@ -1257,6 +1376,12 @@
1257
1376
  // before relying on either — a frozen pre-1065 inspector has
1258
1377
  // neither.
1259
1378
  collectionBinding: true,
1379
+ // ARCH-1065 A17-support (v2.3.0): `QUERY_COLLECTION_ORDER` resolves
1380
+ // the enclosing collection's order ("stable"/"derived") and row
1381
+ // ids/count for a target node, off the same data-agent-* grammar
1382
+ // as `collectionBinding`. Hosts MUST feature-detect on this flag —
1383
+ // a frozen pre-2.3.0 inspector has no handler for the message.
1384
+ collectionOrderQuery: true,
1260
1385
  // The BUILD-TIME contract version this specific page was stamped
1261
1386
  // with, forwarded verbatim from `<meta name="archie-binding-contract">`
1262
1387
  // when the kit build emitted one — null on any page built before
@@ -3881,6 +4006,58 @@
3881
4006
  field: queryField,
3882
4007
  result: queryResult,
3883
4008
  })
4009
+ } else if (event.data && event.data.type === "QUERY_COLLECTION_ORDER") {
4010
+ // ARCH-1065 M3 (v2.3.0) — {order, rowIds, rowCount} for the
4011
+ // collection enclosing a target node, so the FE can refuse
4012
+ // reorder-at-drag on "derived" collections and drive the
4013
+ // repetition-aware enum threshold off rowCount. Mirrors
4014
+ // QUERY_SLICE_FIELD's request/response envelope and graceful
4015
+ // (result: null) failure shape.
4016
+ //
4017
+ // Targeting, in priority order:
4018
+ // 1. `selector` — a CSS selector for ANY element inside the
4019
+ // collection (a row, or a leaf nested inside one); resolved
4020
+ // the same way other selector-addressed messages resolve one
4021
+ // (`findElementBySelector`), then walked up to the nearest
4022
+ // enclosing row root.
4023
+ // 2. `entity` alone (no selector) — the first row root in the
4024
+ // document stamped with that entity name.
4025
+ // 3. neither — mirrors QUERY_SLICE_FIELD's no-rowId fallback:
4026
+ // the currently selected (else hovered) element.
4027
+ var collectionQuerySelector =
4028
+ typeof event.data.selector === "string" && event.data.selector !== ""
4029
+ ? event.data.selector
4030
+ : null
4031
+ var collectionQueryEntity =
4032
+ typeof event.data.entity === "string" && event.data.entity !== ""
4033
+ ? event.data.entity
4034
+ : null
4035
+
4036
+ var collectionRowRoot = null
4037
+ if (collectionQuerySelector) {
4038
+ var collectionTargetEl = findElementBySelector(collectionQuerySelector)
4039
+ collectionRowRoot = collectionTargetEl
4040
+ ? nearestRowRootElement(collectionTargetEl)
4041
+ : null
4042
+ } else if (collectionQueryEntity) {
4043
+ collectionRowRoot = findFirstRowRootForEntity(collectionQueryEntity)
4044
+ } else {
4045
+ var collectionContextEl = getSelectedElement() || highlightedElement
4046
+ collectionRowRoot = collectionContextEl
4047
+ ? nearestRowRootElement(collectionContextEl)
4048
+ : null
4049
+ }
4050
+
4051
+ var collectionQueryResult = queryCollectionOrder(collectionRowRoot)
4052
+
4053
+ postMessageToParent({
4054
+ type: "COLLECTION_ORDER_RESULT",
4055
+ requestId: event.data.requestId,
4056
+ entity: collectionQueryResult
4057
+ ? collectionQueryResult.entity
4058
+ : collectionQueryEntity,
4059
+ result: collectionQueryResult,
4060
+ })
3884
4061
  }
3885
4062
  }
3886
4063
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@archie/devtools",
3
- "version": "0.0.29",
3
+ "version": "0.0.30",
4
4
  "description": "DevTools for Archie generated applications - Route synchronization and editor communication",
5
5
  "repository": {
6
6
  "type": "git",