@archie/devtools 0.1.14 → 0.1.16

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.
@@ -2503,37 +2503,37 @@ function getInitialState() {
2503
2503
  }
2504
2504
  };
2505
2505
  }
2506
- function reducer(state, action) {
2506
+ function reducer(state2, action) {
2507
2507
  switch (action.type) {
2508
2508
  case Action.DragStart:
2509
2509
  return {
2510
- ...state,
2510
+ ...state2,
2511
2511
  draggable: {
2512
- ...state.draggable,
2512
+ ...state2.draggable,
2513
2513
  initialCoordinates: action.initialCoordinates,
2514
2514
  active: action.active
2515
2515
  }
2516
2516
  };
2517
2517
  case Action.DragMove:
2518
- if (state.draggable.active == null) {
2519
- return state;
2518
+ if (state2.draggable.active == null) {
2519
+ return state2;
2520
2520
  }
2521
2521
  return {
2522
- ...state,
2522
+ ...state2,
2523
2523
  draggable: {
2524
- ...state.draggable,
2524
+ ...state2.draggable,
2525
2525
  translate: {
2526
- x: action.coordinates.x - state.draggable.initialCoordinates.x,
2527
- y: action.coordinates.y - state.draggable.initialCoordinates.y
2526
+ x: action.coordinates.x - state2.draggable.initialCoordinates.x,
2527
+ y: action.coordinates.y - state2.draggable.initialCoordinates.y
2528
2528
  }
2529
2529
  }
2530
2530
  };
2531
2531
  case Action.DragEnd:
2532
2532
  case Action.DragCancel:
2533
2533
  return {
2534
- ...state,
2534
+ ...state2,
2535
2535
  draggable: {
2536
- ...state.draggable,
2536
+ ...state2.draggable,
2537
2537
  active: null,
2538
2538
  initialCoordinates: {
2539
2539
  x: 0,
@@ -2552,12 +2552,12 @@ function reducer(state, action) {
2552
2552
  const {
2553
2553
  id
2554
2554
  } = element;
2555
- const containers = new DroppableContainersMap(state.droppable.containers);
2555
+ const containers = new DroppableContainersMap(state2.droppable.containers);
2556
2556
  containers.set(id, element);
2557
2557
  return {
2558
- ...state,
2558
+ ...state2,
2559
2559
  droppable: {
2560
- ...state.droppable,
2560
+ ...state2.droppable,
2561
2561
  containers
2562
2562
  }
2563
2563
  };
@@ -2568,19 +2568,19 @@ function reducer(state, action) {
2568
2568
  key: key2,
2569
2569
  disabled
2570
2570
  } = action;
2571
- const element = state.droppable.containers.get(id);
2571
+ const element = state2.droppable.containers.get(id);
2572
2572
  if (!element || key2 !== element.key) {
2573
- return state;
2573
+ return state2;
2574
2574
  }
2575
- const containers = new DroppableContainersMap(state.droppable.containers);
2575
+ const containers = new DroppableContainersMap(state2.droppable.containers);
2576
2576
  containers.set(id, {
2577
2577
  ...element,
2578
2578
  disabled
2579
2579
  });
2580
2580
  return {
2581
- ...state,
2581
+ ...state2,
2582
2582
  droppable: {
2583
- ...state.droppable,
2583
+ ...state2.droppable,
2584
2584
  containers
2585
2585
  }
2586
2586
  };
@@ -2590,22 +2590,22 @@ function reducer(state, action) {
2590
2590
  id,
2591
2591
  key: key2
2592
2592
  } = action;
2593
- const element = state.droppable.containers.get(id);
2593
+ const element = state2.droppable.containers.get(id);
2594
2594
  if (!element || key2 !== element.key) {
2595
- return state;
2595
+ return state2;
2596
2596
  }
2597
- const containers = new DroppableContainersMap(state.droppable.containers);
2597
+ const containers = new DroppableContainersMap(state2.droppable.containers);
2598
2598
  containers.delete(id);
2599
2599
  return {
2600
- ...state,
2600
+ ...state2,
2601
2601
  droppable: {
2602
- ...state.droppable,
2602
+ ...state2.droppable,
2603
2603
  containers
2604
2604
  }
2605
2605
  };
2606
2606
  }
2607
2607
  default: {
2608
- return state;
2608
+ return state2;
2609
2609
  }
2610
2610
  }
2611
2611
  }
@@ -2763,7 +2763,7 @@ var DndContext = /* @__PURE__ */ (0, import_react3.memo)(function DndContext2(_r
2763
2763
  ...props
2764
2764
  } = _ref;
2765
2765
  const store = (0, import_react3.useReducer)(reducer, void 0, getInitialState);
2766
- const [state, dispatch] = store;
2766
+ const [state2, dispatch] = store;
2767
2767
  const [dispatchMonitorEvent, registerMonitorListener] = useDndMonitorProvider();
2768
2768
  const [status, setStatus] = (0, import_react3.useState)(Status.Uninitialized);
2769
2769
  const isInitialized = status === Status.Initialized;
@@ -2776,7 +2776,7 @@ var DndContext = /* @__PURE__ */ (0, import_react3.memo)(function DndContext2(_r
2776
2776
  droppable: {
2777
2777
  containers: droppableContainers
2778
2778
  }
2779
- } = state;
2779
+ } = state2;
2780
2780
  const node = activeId != null ? draggableNodes.get(activeId) : null;
2781
2781
  const activeRects = (0, import_react3.useRef)({
2782
2782
  initial: null,
@@ -3937,24 +3937,24 @@ function isAfter(a, b) {
3937
3937
 
3938
3938
  // node_modules/zustand/esm/vanilla.mjs
3939
3939
  var createStoreImpl = (createState) => {
3940
- let state;
3940
+ let state2;
3941
3941
  const listeners = /* @__PURE__ */ new Set();
3942
3942
  const setState = (partial, replace) => {
3943
- const nextState = typeof partial === "function" ? partial(state) : partial;
3944
- if (!Object.is(nextState, state)) {
3945
- const previousState = state;
3946
- state = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
3947
- listeners.forEach((listener) => listener(state, previousState));
3943
+ const nextState = typeof partial === "function" ? partial(state2) : partial;
3944
+ if (!Object.is(nextState, state2)) {
3945
+ const previousState = state2;
3946
+ state2 = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state2, nextState);
3947
+ listeners.forEach((listener) => listener(state2, previousState));
3948
3948
  }
3949
3949
  };
3950
- const getState = () => state;
3950
+ const getState = () => state2;
3951
3951
  const getInitialState2 = () => initialState;
3952
3952
  const subscribe = (listener) => {
3953
3953
  listeners.add(listener);
3954
3954
  return () => listeners.delete(listener);
3955
3955
  };
3956
3956
  const api = { setState, getState, getInitialState: getInitialState2, subscribe };
3957
- const initialState = state = createState(setState, getState, api);
3957
+ const initialState = state2 = createState(setState, getState, api);
3958
3958
  return api;
3959
3959
  };
3960
3960
  var createStore = ((createState) => createState ? createStoreImpl(createState) : createStoreImpl);
@@ -3988,33 +3988,33 @@ var useDndStore = create((set) => ({
3988
3988
  overlayRenderers: /* @__PURE__ */ new Map(),
3989
3989
  dragEndHandlers: /* @__PURE__ */ new Map(),
3990
3990
  setActive: (id, data, element) => set({ activeId: id, activeData: data, activeElement: element ?? null }),
3991
- registerContainer: (container) => set((state) => {
3992
- const next = new Map(state.containers);
3991
+ registerContainer: (container) => set((state2) => {
3992
+ const next = new Map(state2.containers);
3993
3993
  next.set(container.id, container);
3994
3994
  return { containers: next };
3995
3995
  }),
3996
- unregisterContainer: (id) => set((state) => {
3997
- const next = new Map(state.containers);
3996
+ unregisterContainer: (id) => set((state2) => {
3997
+ const next = new Map(state2.containers);
3998
3998
  next.delete(id);
3999
3999
  return { containers: next };
4000
4000
  }),
4001
- registerOverlayRenderer: (type, renderer) => set((state) => {
4002
- const next = new Map(state.overlayRenderers);
4001
+ registerOverlayRenderer: (type, renderer) => set((state2) => {
4002
+ const next = new Map(state2.overlayRenderers);
4003
4003
  next.set(type, renderer);
4004
4004
  return { overlayRenderers: next };
4005
4005
  }),
4006
- unregisterOverlayRenderer: (type) => set((state) => {
4007
- const next = new Map(state.overlayRenderers);
4006
+ unregisterOverlayRenderer: (type) => set((state2) => {
4007
+ const next = new Map(state2.overlayRenderers);
4008
4008
  next.delete(type);
4009
4009
  return { overlayRenderers: next };
4010
4010
  }),
4011
- registerDragEndHandler: (key2, handler) => set((state) => {
4012
- const next = new Map(state.dragEndHandlers);
4011
+ registerDragEndHandler: (key2, handler) => set((state2) => {
4012
+ const next = new Map(state2.dragEndHandlers);
4013
4013
  next.set(key2, handler);
4014
4014
  return { dragEndHandlers: next };
4015
4015
  }),
4016
- unregisterDragEndHandler: (key2) => set((state) => {
4017
- const next = new Map(state.dragEndHandlers);
4016
+ unregisterDragEndHandler: (key2) => set((state2) => {
4017
+ const next = new Map(state2.dragEndHandlers);
4018
4018
  next.delete(key2);
4019
4019
  return { dragEndHandlers: next };
4020
4020
  })
@@ -10271,7 +10271,7 @@ function isPreviewOrigin(origin) {
10271
10271
  var DEFAULT_SCRIPT_ID = "archie-inspector-script";
10272
10272
  var R2_INSPECTOR_BASE_URL = "https://pub-bf238c278d9644b39ec34ecaca1d315c.r2.dev";
10273
10273
  function readBuildVersion() {
10274
- return "0.1.14" ? "0.1.14" : null;
10274
+ return "0.1.16" ? "0.1.16" : null;
10275
10275
  }
10276
10276
  var REMOTE_INSPECTOR_VERSION = readBuildVersion();
10277
10277
  var isRemoteInspectorUrlVersioned = REMOTE_INSPECTOR_VERSION !== null;
@@ -10351,6 +10351,163 @@ function injectInspector(opts = {}) {
10351
10351
  document.head.appendChild(script);
10352
10352
  }
10353
10353
 
10354
+ // src/client/route-listener/pageSettle.ts
10355
+ var QUIET_MS = 300;
10356
+ var POLL_MS = 50;
10357
+ var PAGE_QUIET_TIMEOUT_MS = 5e3;
10358
+ var MAX_TRACKED_REQUEST_AGE_MS = 4e3;
10359
+ var IGNORED_URL_RE = /^wss?:|\/@vite\/|\/@react-refresh|\/__vite|\.hot-update\.|\/_next\/webpack-hmr|\/sockjs-node|\/__webpack_hmr/;
10360
+ var LOADING_SELECTOR = [
10361
+ '[aria-busy="true"]',
10362
+ '[role="progressbar"]',
10363
+ '[class*="animate-spin"]',
10364
+ '[class*="animate-pulse"]',
10365
+ '[class*="skeleton" i]'
10366
+ ].join(",");
10367
+ var LOADING_TEXT_RE = /^(loading|cargando)(\.{3}|…)?$/i;
10368
+ var NON_RENDERED_TAGS = /* @__PURE__ */ new Set(["SCRIPT", "STYLE", "NOSCRIPT", "TEMPLATE"]);
10369
+ var state = {
10370
+ refs: 0,
10371
+ inflight: /* @__PURE__ */ new Map(),
10372
+ nextId: 0,
10373
+ lastActivityAt: 0
10374
+ };
10375
+ function urlOf(input) {
10376
+ if (typeof input === "string") return input;
10377
+ if (input instanceof URL) return input.href;
10378
+ return input?.url ?? "";
10379
+ }
10380
+ function begin(url) {
10381
+ if (IGNORED_URL_RE.test(url)) return void 0;
10382
+ const id = state.nextId++;
10383
+ state.inflight.set(id, Date.now());
10384
+ state.lastActivityAt = Date.now();
10385
+ return () => {
10386
+ if (state.inflight.delete(id)) state.lastActivityAt = Date.now();
10387
+ };
10388
+ }
10389
+ function patchNetwork() {
10390
+ const originalFetch = window.fetch;
10391
+ const xhrProto = window.XMLHttpRequest?.prototype;
10392
+ const originalOpen = xhrProto?.open;
10393
+ const originalSend = xhrProto?.send;
10394
+ const patchedFetch = function(...args) {
10395
+ const end = begin(urlOf(args[0]));
10396
+ let result;
10397
+ try {
10398
+ result = originalFetch.apply(this, args);
10399
+ } catch (error) {
10400
+ end?.();
10401
+ throw error;
10402
+ }
10403
+ if (end) result.then(end, end);
10404
+ return result;
10405
+ };
10406
+ if (typeof originalFetch === "function") window.fetch = patchedFetch;
10407
+ if (xhrProto && originalOpen && originalSend) {
10408
+ xhrProto.open = function(...args) {
10409
+ this.__archieUrl = urlOf(args[1]);
10410
+ return originalOpen.apply(this, args);
10411
+ };
10412
+ xhrProto.send = function(body) {
10413
+ const end = begin(this.__archieUrl ?? "");
10414
+ if (end) this.addEventListener("loadend", end, { once: true });
10415
+ try {
10416
+ return originalSend.call(this, body);
10417
+ } catch (error) {
10418
+ end?.();
10419
+ throw error;
10420
+ }
10421
+ };
10422
+ }
10423
+ return () => {
10424
+ if (window.fetch === patchedFetch) window.fetch = originalFetch;
10425
+ if (xhrProto && originalOpen && originalSend) {
10426
+ xhrProto.open = originalOpen;
10427
+ xhrProto.send = originalSend;
10428
+ }
10429
+ };
10430
+ }
10431
+ function installPageActivityTracker() {
10432
+ if (state.refs++ === 0) {
10433
+ state.lastActivityAt = Date.now();
10434
+ state.restore = patchNetwork();
10435
+ state.observer = new MutationObserver(() => {
10436
+ state.lastActivityAt = Date.now();
10437
+ });
10438
+ state.observer.observe(document, {
10439
+ subtree: true,
10440
+ childList: true,
10441
+ attributes: true,
10442
+ characterData: true
10443
+ });
10444
+ }
10445
+ let released = false;
10446
+ return () => {
10447
+ if (released) return;
10448
+ released = true;
10449
+ if (--state.refs === 0) {
10450
+ state.restore?.();
10451
+ state.observer?.disconnect();
10452
+ state.restore = void 0;
10453
+ state.observer = void 0;
10454
+ state.inflight.clear();
10455
+ }
10456
+ };
10457
+ }
10458
+ function isVisible(el) {
10459
+ if (el.closest('[hidden],[aria-hidden="true"]')) return false;
10460
+ try {
10461
+ const style = getComputedStyle(el);
10462
+ return style.display !== "none" && style.visibility !== "hidden";
10463
+ } catch {
10464
+ return true;
10465
+ }
10466
+ }
10467
+ function hasLoadingIndicator() {
10468
+ const root = document.body;
10469
+ if (!root) return false;
10470
+ for (const el of Array.from(root.querySelectorAll(LOADING_SELECTOR))) {
10471
+ if (isVisible(el)) return true;
10472
+ }
10473
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
10474
+ for (let node = walker.nextNode(); node; node = walker.nextNode()) {
10475
+ const parent = node.parentElement;
10476
+ if (!parent || NON_RENDERED_TAGS.has(parent.tagName)) continue;
10477
+ if (LOADING_TEXT_RE.test((node.textContent ?? "").trim()) && isVisible(parent)) {
10478
+ return true;
10479
+ }
10480
+ }
10481
+ return false;
10482
+ }
10483
+ function hasPendingRequests(now) {
10484
+ for (const startedAt of state.inflight.values()) {
10485
+ if (now - startedAt < MAX_TRACKED_REQUEST_AGE_MS) return true;
10486
+ }
10487
+ return false;
10488
+ }
10489
+ function waitForPageQuiet(timeoutMs = PAGE_QUIET_TIMEOUT_MS) {
10490
+ return new Promise((resolve) => {
10491
+ const startedAt = Date.now();
10492
+ const untracked = state.refs === 0;
10493
+ const isQuiet = (now) => !hasPendingRequests(now) && now - (untracked ? startedAt : state.lastActivityAt) >= QUIET_MS && !hasLoadingIndicator();
10494
+ if (isQuiet(startedAt) && !untracked) {
10495
+ resolve(true);
10496
+ return;
10497
+ }
10498
+ const timer = setInterval(() => {
10499
+ const now = Date.now();
10500
+ if (isQuiet(now)) {
10501
+ clearInterval(timer);
10502
+ resolve(true);
10503
+ } else if (now - startedAt >= timeoutMs) {
10504
+ clearInterval(timer);
10505
+ resolve(false);
10506
+ }
10507
+ }, POLL_MS);
10508
+ });
10509
+ }
10510
+
10354
10511
  // src/client/route-listener/domSnapshot.ts
10355
10512
  var STRIP_SELECTOR = [
10356
10513
  "script",
@@ -10433,6 +10590,7 @@ async function captureDomSnapshot() {
10433
10590
  if (document.fonts?.ready) {
10434
10591
  await document.fonts.ready;
10435
10592
  }
10593
+ const settled = await waitForPageQuiet();
10436
10594
  await waitForIdle();
10437
10595
  const inlinedHrefs = /* @__PURE__ */ new Set();
10438
10596
  const css = await collectDocumentCss(inlinedHrefs);
@@ -10470,7 +10628,8 @@ async function captureDomSnapshot() {
10470
10628
  html: "<!doctype html>" + clone.outerHTML,
10471
10629
  path: location.pathname + location.search + location.hash,
10472
10630
  viewport: { width: window.innerWidth, height: window.innerHeight },
10473
- capturedAt: Date.now()
10631
+ capturedAt: Date.now(),
10632
+ settled
10474
10633
  };
10475
10634
  }
10476
10635
 
@@ -10601,15 +10760,15 @@ function extractAllRoutes(routes, parentPath = "", parentId = null, inheritedGua
10601
10760
  }
10602
10761
  return result;
10603
10762
  }
10604
- function broadcastRouteState(target, state, routes) {
10763
+ function broadcastRouteState(target, state2, routes) {
10605
10764
  try {
10606
10765
  const message = {
10607
10766
  type: "ARCHIE_ROUTE_UPDATE",
10608
10767
  payload: {
10609
- path: state.location.pathname,
10610
- search: state.location.search,
10611
- hash: state.location.hash,
10612
- matches: state.matches.map((m) => {
10768
+ path: state2.location.pathname,
10769
+ search: state2.location.search,
10770
+ hash: state2.location.hash,
10771
+ matches: state2.matches.map((m) => {
10613
10772
  const handle = pickRouteHandle(m.route.handle);
10614
10773
  return {
10615
10774
  id: m.route.id,
@@ -10632,7 +10791,7 @@ var SETTLE_QUIET_MS = 400;
10632
10791
  var SETTLE_TIMEOUT_MS = 8e3;
10633
10792
  var SETTLE_POLL_MS = 50;
10634
10793
  function readPackageVersion() {
10635
- return true ? "0.1.14" : "unknown";
10794
+ return true ? "0.1.16" : "unknown";
10636
10795
  }
10637
10796
  var DEFAULT_ARCHIE_COMMAND_ORIGINS = getAllowedOrigins(true);
10638
10797
  function originPatternToRegExp(pattern) {
@@ -10766,11 +10925,12 @@ function setupArchieRouteListener(router, options = {}) {
10766
10925
  return () => {
10767
10926
  };
10768
10927
  }
10928
+ const releaseTracker = installPageActivityTracker();
10769
10929
  broadcastRouteState(target, router.state, extractAllRoutes(router.routes));
10770
10930
  broadcastCapabilities(router, target);
10771
- const unsubscribe = router.subscribe((state) => {
10931
+ const unsubscribe = router.subscribe((state2) => {
10772
10932
  const currentRoutes = extractAllRoutes(router.routes);
10773
- broadcastRouteState(target, state, currentRoutes);
10933
+ broadcastRouteState(target, state2, currentRoutes);
10774
10934
  });
10775
10935
  const handleMessage = (event) => {
10776
10936
  if (event.source !== target) return;
@@ -10802,6 +10962,7 @@ function setupArchieRouteListener(router, options = {}) {
10802
10962
  return () => {
10803
10963
  unsubscribe();
10804
10964
  window.removeEventListener("message", handleMessage);
10965
+ releaseTracker();
10805
10966
  };
10806
10967
  }
10807
10968
 
@@ -2468,37 +2468,37 @@ function getInitialState() {
2468
2468
  }
2469
2469
  };
2470
2470
  }
2471
- function reducer(state, action) {
2471
+ function reducer(state2, action) {
2472
2472
  switch (action.type) {
2473
2473
  case Action.DragStart:
2474
2474
  return {
2475
- ...state,
2475
+ ...state2,
2476
2476
  draggable: {
2477
- ...state.draggable,
2477
+ ...state2.draggable,
2478
2478
  initialCoordinates: action.initialCoordinates,
2479
2479
  active: action.active
2480
2480
  }
2481
2481
  };
2482
2482
  case Action.DragMove:
2483
- if (state.draggable.active == null) {
2484
- return state;
2483
+ if (state2.draggable.active == null) {
2484
+ return state2;
2485
2485
  }
2486
2486
  return {
2487
- ...state,
2487
+ ...state2,
2488
2488
  draggable: {
2489
- ...state.draggable,
2489
+ ...state2.draggable,
2490
2490
  translate: {
2491
- x: action.coordinates.x - state.draggable.initialCoordinates.x,
2492
- y: action.coordinates.y - state.draggable.initialCoordinates.y
2491
+ x: action.coordinates.x - state2.draggable.initialCoordinates.x,
2492
+ y: action.coordinates.y - state2.draggable.initialCoordinates.y
2493
2493
  }
2494
2494
  }
2495
2495
  };
2496
2496
  case Action.DragEnd:
2497
2497
  case Action.DragCancel:
2498
2498
  return {
2499
- ...state,
2499
+ ...state2,
2500
2500
  draggable: {
2501
- ...state.draggable,
2501
+ ...state2.draggable,
2502
2502
  active: null,
2503
2503
  initialCoordinates: {
2504
2504
  x: 0,
@@ -2517,12 +2517,12 @@ function reducer(state, action) {
2517
2517
  const {
2518
2518
  id
2519
2519
  } = element;
2520
- const containers = new DroppableContainersMap(state.droppable.containers);
2520
+ const containers = new DroppableContainersMap(state2.droppable.containers);
2521
2521
  containers.set(id, element);
2522
2522
  return {
2523
- ...state,
2523
+ ...state2,
2524
2524
  droppable: {
2525
- ...state.droppable,
2525
+ ...state2.droppable,
2526
2526
  containers
2527
2527
  }
2528
2528
  };
@@ -2533,19 +2533,19 @@ function reducer(state, action) {
2533
2533
  key: key2,
2534
2534
  disabled
2535
2535
  } = action;
2536
- const element = state.droppable.containers.get(id);
2536
+ const element = state2.droppable.containers.get(id);
2537
2537
  if (!element || key2 !== element.key) {
2538
- return state;
2538
+ return state2;
2539
2539
  }
2540
- const containers = new DroppableContainersMap(state.droppable.containers);
2540
+ const containers = new DroppableContainersMap(state2.droppable.containers);
2541
2541
  containers.set(id, {
2542
2542
  ...element,
2543
2543
  disabled
2544
2544
  });
2545
2545
  return {
2546
- ...state,
2546
+ ...state2,
2547
2547
  droppable: {
2548
- ...state.droppable,
2548
+ ...state2.droppable,
2549
2549
  containers
2550
2550
  }
2551
2551
  };
@@ -2555,22 +2555,22 @@ function reducer(state, action) {
2555
2555
  id,
2556
2556
  key: key2
2557
2557
  } = action;
2558
- const element = state.droppable.containers.get(id);
2558
+ const element = state2.droppable.containers.get(id);
2559
2559
  if (!element || key2 !== element.key) {
2560
- return state;
2560
+ return state2;
2561
2561
  }
2562
- const containers = new DroppableContainersMap(state.droppable.containers);
2562
+ const containers = new DroppableContainersMap(state2.droppable.containers);
2563
2563
  containers.delete(id);
2564
2564
  return {
2565
- ...state,
2565
+ ...state2,
2566
2566
  droppable: {
2567
- ...state.droppable,
2567
+ ...state2.droppable,
2568
2568
  containers
2569
2569
  }
2570
2570
  };
2571
2571
  }
2572
2572
  default: {
2573
- return state;
2573
+ return state2;
2574
2574
  }
2575
2575
  }
2576
2576
  }
@@ -2728,7 +2728,7 @@ var DndContext = /* @__PURE__ */ memo(function DndContext2(_ref) {
2728
2728
  ...props
2729
2729
  } = _ref;
2730
2730
  const store = useReducer(reducer, void 0, getInitialState);
2731
- const [state, dispatch] = store;
2731
+ const [state2, dispatch] = store;
2732
2732
  const [dispatchMonitorEvent, registerMonitorListener] = useDndMonitorProvider();
2733
2733
  const [status, setStatus] = useState2(Status.Uninitialized);
2734
2734
  const isInitialized = status === Status.Initialized;
@@ -2741,7 +2741,7 @@ var DndContext = /* @__PURE__ */ memo(function DndContext2(_ref) {
2741
2741
  droppable: {
2742
2742
  containers: droppableContainers
2743
2743
  }
2744
- } = state;
2744
+ } = state2;
2745
2745
  const node = activeId != null ? draggableNodes.get(activeId) : null;
2746
2746
  const activeRects = useRef2({
2747
2747
  initial: null,
@@ -3902,24 +3902,24 @@ function isAfter(a, b) {
3902
3902
 
3903
3903
  // node_modules/zustand/esm/vanilla.mjs
3904
3904
  var createStoreImpl = (createState) => {
3905
- let state;
3905
+ let state2;
3906
3906
  const listeners = /* @__PURE__ */ new Set();
3907
3907
  const setState = (partial, replace) => {
3908
- const nextState = typeof partial === "function" ? partial(state) : partial;
3909
- if (!Object.is(nextState, state)) {
3910
- const previousState = state;
3911
- state = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
3912
- listeners.forEach((listener) => listener(state, previousState));
3908
+ const nextState = typeof partial === "function" ? partial(state2) : partial;
3909
+ if (!Object.is(nextState, state2)) {
3910
+ const previousState = state2;
3911
+ state2 = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state2, nextState);
3912
+ listeners.forEach((listener) => listener(state2, previousState));
3913
3913
  }
3914
3914
  };
3915
- const getState = () => state;
3915
+ const getState = () => state2;
3916
3916
  const getInitialState2 = () => initialState;
3917
3917
  const subscribe = (listener) => {
3918
3918
  listeners.add(listener);
3919
3919
  return () => listeners.delete(listener);
3920
3920
  };
3921
3921
  const api = { setState, getState, getInitialState: getInitialState2, subscribe };
3922
- const initialState = state = createState(setState, getState, api);
3922
+ const initialState = state2 = createState(setState, getState, api);
3923
3923
  return api;
3924
3924
  };
3925
3925
  var createStore = ((createState) => createState ? createStoreImpl(createState) : createStoreImpl);
@@ -3953,33 +3953,33 @@ var useDndStore = create((set) => ({
3953
3953
  overlayRenderers: /* @__PURE__ */ new Map(),
3954
3954
  dragEndHandlers: /* @__PURE__ */ new Map(),
3955
3955
  setActive: (id, data, element) => set({ activeId: id, activeData: data, activeElement: element ?? null }),
3956
- registerContainer: (container) => set((state) => {
3957
- const next = new Map(state.containers);
3956
+ registerContainer: (container) => set((state2) => {
3957
+ const next = new Map(state2.containers);
3958
3958
  next.set(container.id, container);
3959
3959
  return { containers: next };
3960
3960
  }),
3961
- unregisterContainer: (id) => set((state) => {
3962
- const next = new Map(state.containers);
3961
+ unregisterContainer: (id) => set((state2) => {
3962
+ const next = new Map(state2.containers);
3963
3963
  next.delete(id);
3964
3964
  return { containers: next };
3965
3965
  }),
3966
- registerOverlayRenderer: (type, renderer) => set((state) => {
3967
- const next = new Map(state.overlayRenderers);
3966
+ registerOverlayRenderer: (type, renderer) => set((state2) => {
3967
+ const next = new Map(state2.overlayRenderers);
3968
3968
  next.set(type, renderer);
3969
3969
  return { overlayRenderers: next };
3970
3970
  }),
3971
- unregisterOverlayRenderer: (type) => set((state) => {
3972
- const next = new Map(state.overlayRenderers);
3971
+ unregisterOverlayRenderer: (type) => set((state2) => {
3972
+ const next = new Map(state2.overlayRenderers);
3973
3973
  next.delete(type);
3974
3974
  return { overlayRenderers: next };
3975
3975
  }),
3976
- registerDragEndHandler: (key2, handler) => set((state) => {
3977
- const next = new Map(state.dragEndHandlers);
3976
+ registerDragEndHandler: (key2, handler) => set((state2) => {
3977
+ const next = new Map(state2.dragEndHandlers);
3978
3978
  next.set(key2, handler);
3979
3979
  return { dragEndHandlers: next };
3980
3980
  }),
3981
- unregisterDragEndHandler: (key2) => set((state) => {
3982
- const next = new Map(state.dragEndHandlers);
3981
+ unregisterDragEndHandler: (key2) => set((state2) => {
3982
+ const next = new Map(state2.dragEndHandlers);
3983
3983
  next.delete(key2);
3984
3984
  return { dragEndHandlers: next };
3985
3985
  })
@@ -10236,7 +10236,7 @@ function isPreviewOrigin(origin) {
10236
10236
  var DEFAULT_SCRIPT_ID = "archie-inspector-script";
10237
10237
  var R2_INSPECTOR_BASE_URL = "https://pub-bf238c278d9644b39ec34ecaca1d315c.r2.dev";
10238
10238
  function readBuildVersion() {
10239
- return "0.1.14" ? "0.1.14" : null;
10239
+ return "0.1.16" ? "0.1.16" : null;
10240
10240
  }
10241
10241
  var REMOTE_INSPECTOR_VERSION = readBuildVersion();
10242
10242
  var isRemoteInspectorUrlVersioned = REMOTE_INSPECTOR_VERSION !== null;
@@ -10316,6 +10316,163 @@ function injectInspector(opts = {}) {
10316
10316
  document.head.appendChild(script);
10317
10317
  }
10318
10318
 
10319
+ // src/client/route-listener/pageSettle.ts
10320
+ var QUIET_MS = 300;
10321
+ var POLL_MS = 50;
10322
+ var PAGE_QUIET_TIMEOUT_MS = 5e3;
10323
+ var MAX_TRACKED_REQUEST_AGE_MS = 4e3;
10324
+ var IGNORED_URL_RE = /^wss?:|\/@vite\/|\/@react-refresh|\/__vite|\.hot-update\.|\/_next\/webpack-hmr|\/sockjs-node|\/__webpack_hmr/;
10325
+ var LOADING_SELECTOR = [
10326
+ '[aria-busy="true"]',
10327
+ '[role="progressbar"]',
10328
+ '[class*="animate-spin"]',
10329
+ '[class*="animate-pulse"]',
10330
+ '[class*="skeleton" i]'
10331
+ ].join(",");
10332
+ var LOADING_TEXT_RE = /^(loading|cargando)(\.{3}|…)?$/i;
10333
+ var NON_RENDERED_TAGS = /* @__PURE__ */ new Set(["SCRIPT", "STYLE", "NOSCRIPT", "TEMPLATE"]);
10334
+ var state = {
10335
+ refs: 0,
10336
+ inflight: /* @__PURE__ */ new Map(),
10337
+ nextId: 0,
10338
+ lastActivityAt: 0
10339
+ };
10340
+ function urlOf(input) {
10341
+ if (typeof input === "string") return input;
10342
+ if (input instanceof URL) return input.href;
10343
+ return input?.url ?? "";
10344
+ }
10345
+ function begin(url) {
10346
+ if (IGNORED_URL_RE.test(url)) return void 0;
10347
+ const id = state.nextId++;
10348
+ state.inflight.set(id, Date.now());
10349
+ state.lastActivityAt = Date.now();
10350
+ return () => {
10351
+ if (state.inflight.delete(id)) state.lastActivityAt = Date.now();
10352
+ };
10353
+ }
10354
+ function patchNetwork() {
10355
+ const originalFetch = window.fetch;
10356
+ const xhrProto = window.XMLHttpRequest?.prototype;
10357
+ const originalOpen = xhrProto?.open;
10358
+ const originalSend = xhrProto?.send;
10359
+ const patchedFetch = function(...args) {
10360
+ const end = begin(urlOf(args[0]));
10361
+ let result;
10362
+ try {
10363
+ result = originalFetch.apply(this, args);
10364
+ } catch (error) {
10365
+ end?.();
10366
+ throw error;
10367
+ }
10368
+ if (end) result.then(end, end);
10369
+ return result;
10370
+ };
10371
+ if (typeof originalFetch === "function") window.fetch = patchedFetch;
10372
+ if (xhrProto && originalOpen && originalSend) {
10373
+ xhrProto.open = function(...args) {
10374
+ this.__archieUrl = urlOf(args[1]);
10375
+ return originalOpen.apply(this, args);
10376
+ };
10377
+ xhrProto.send = function(body) {
10378
+ const end = begin(this.__archieUrl ?? "");
10379
+ if (end) this.addEventListener("loadend", end, { once: true });
10380
+ try {
10381
+ return originalSend.call(this, body);
10382
+ } catch (error) {
10383
+ end?.();
10384
+ throw error;
10385
+ }
10386
+ };
10387
+ }
10388
+ return () => {
10389
+ if (window.fetch === patchedFetch) window.fetch = originalFetch;
10390
+ if (xhrProto && originalOpen && originalSend) {
10391
+ xhrProto.open = originalOpen;
10392
+ xhrProto.send = originalSend;
10393
+ }
10394
+ };
10395
+ }
10396
+ function installPageActivityTracker() {
10397
+ if (state.refs++ === 0) {
10398
+ state.lastActivityAt = Date.now();
10399
+ state.restore = patchNetwork();
10400
+ state.observer = new MutationObserver(() => {
10401
+ state.lastActivityAt = Date.now();
10402
+ });
10403
+ state.observer.observe(document, {
10404
+ subtree: true,
10405
+ childList: true,
10406
+ attributes: true,
10407
+ characterData: true
10408
+ });
10409
+ }
10410
+ let released = false;
10411
+ return () => {
10412
+ if (released) return;
10413
+ released = true;
10414
+ if (--state.refs === 0) {
10415
+ state.restore?.();
10416
+ state.observer?.disconnect();
10417
+ state.restore = void 0;
10418
+ state.observer = void 0;
10419
+ state.inflight.clear();
10420
+ }
10421
+ };
10422
+ }
10423
+ function isVisible(el) {
10424
+ if (el.closest('[hidden],[aria-hidden="true"]')) return false;
10425
+ try {
10426
+ const style = getComputedStyle(el);
10427
+ return style.display !== "none" && style.visibility !== "hidden";
10428
+ } catch {
10429
+ return true;
10430
+ }
10431
+ }
10432
+ function hasLoadingIndicator() {
10433
+ const root = document.body;
10434
+ if (!root) return false;
10435
+ for (const el of Array.from(root.querySelectorAll(LOADING_SELECTOR))) {
10436
+ if (isVisible(el)) return true;
10437
+ }
10438
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
10439
+ for (let node = walker.nextNode(); node; node = walker.nextNode()) {
10440
+ const parent = node.parentElement;
10441
+ if (!parent || NON_RENDERED_TAGS.has(parent.tagName)) continue;
10442
+ if (LOADING_TEXT_RE.test((node.textContent ?? "").trim()) && isVisible(parent)) {
10443
+ return true;
10444
+ }
10445
+ }
10446
+ return false;
10447
+ }
10448
+ function hasPendingRequests(now) {
10449
+ for (const startedAt of state.inflight.values()) {
10450
+ if (now - startedAt < MAX_TRACKED_REQUEST_AGE_MS) return true;
10451
+ }
10452
+ return false;
10453
+ }
10454
+ function waitForPageQuiet(timeoutMs = PAGE_QUIET_TIMEOUT_MS) {
10455
+ return new Promise((resolve) => {
10456
+ const startedAt = Date.now();
10457
+ const untracked = state.refs === 0;
10458
+ const isQuiet = (now) => !hasPendingRequests(now) && now - (untracked ? startedAt : state.lastActivityAt) >= QUIET_MS && !hasLoadingIndicator();
10459
+ if (isQuiet(startedAt) && !untracked) {
10460
+ resolve(true);
10461
+ return;
10462
+ }
10463
+ const timer = setInterval(() => {
10464
+ const now = Date.now();
10465
+ if (isQuiet(now)) {
10466
+ clearInterval(timer);
10467
+ resolve(true);
10468
+ } else if (now - startedAt >= timeoutMs) {
10469
+ clearInterval(timer);
10470
+ resolve(false);
10471
+ }
10472
+ }, POLL_MS);
10473
+ });
10474
+ }
10475
+
10319
10476
  // src/client/route-listener/domSnapshot.ts
10320
10477
  var STRIP_SELECTOR = [
10321
10478
  "script",
@@ -10398,6 +10555,7 @@ async function captureDomSnapshot() {
10398
10555
  if (document.fonts?.ready) {
10399
10556
  await document.fonts.ready;
10400
10557
  }
10558
+ const settled = await waitForPageQuiet();
10401
10559
  await waitForIdle();
10402
10560
  const inlinedHrefs = /* @__PURE__ */ new Set();
10403
10561
  const css = await collectDocumentCss(inlinedHrefs);
@@ -10435,7 +10593,8 @@ async function captureDomSnapshot() {
10435
10593
  html: "<!doctype html>" + clone.outerHTML,
10436
10594
  path: location.pathname + location.search + location.hash,
10437
10595
  viewport: { width: window.innerWidth, height: window.innerHeight },
10438
- capturedAt: Date.now()
10596
+ capturedAt: Date.now(),
10597
+ settled
10439
10598
  };
10440
10599
  }
10441
10600
 
@@ -10566,15 +10725,15 @@ function extractAllRoutes(routes, parentPath = "", parentId = null, inheritedGua
10566
10725
  }
10567
10726
  return result;
10568
10727
  }
10569
- function broadcastRouteState(target, state, routes) {
10728
+ function broadcastRouteState(target, state2, routes) {
10570
10729
  try {
10571
10730
  const message = {
10572
10731
  type: "ARCHIE_ROUTE_UPDATE",
10573
10732
  payload: {
10574
- path: state.location.pathname,
10575
- search: state.location.search,
10576
- hash: state.location.hash,
10577
- matches: state.matches.map((m) => {
10733
+ path: state2.location.pathname,
10734
+ search: state2.location.search,
10735
+ hash: state2.location.hash,
10736
+ matches: state2.matches.map((m) => {
10578
10737
  const handle = pickRouteHandle(m.route.handle);
10579
10738
  return {
10580
10739
  id: m.route.id,
@@ -10597,7 +10756,7 @@ var SETTLE_QUIET_MS = 400;
10597
10756
  var SETTLE_TIMEOUT_MS = 8e3;
10598
10757
  var SETTLE_POLL_MS = 50;
10599
10758
  function readPackageVersion() {
10600
- return true ? "0.1.14" : "unknown";
10759
+ return true ? "0.1.16" : "unknown";
10601
10760
  }
10602
10761
  var DEFAULT_ARCHIE_COMMAND_ORIGINS = getAllowedOrigins(true);
10603
10762
  function originPatternToRegExp(pattern) {
@@ -10731,11 +10890,12 @@ function setupArchieRouteListener(router, options = {}) {
10731
10890
  return () => {
10732
10891
  };
10733
10892
  }
10893
+ const releaseTracker = installPageActivityTracker();
10734
10894
  broadcastRouteState(target, router.state, extractAllRoutes(router.routes));
10735
10895
  broadcastCapabilities(router, target);
10736
- const unsubscribe = router.subscribe((state) => {
10896
+ const unsubscribe = router.subscribe((state2) => {
10737
10897
  const currentRoutes = extractAllRoutes(router.routes);
10738
- broadcastRouteState(target, state, currentRoutes);
10898
+ broadcastRouteState(target, state2, currentRoutes);
10739
10899
  });
10740
10900
  const handleMessage = (event) => {
10741
10901
  if (event.source !== target) return;
@@ -10767,6 +10927,7 @@ function setupArchieRouteListener(router, options = {}) {
10767
10927
  return () => {
10768
10928
  unsubscribe();
10769
10929
  window.removeEventListener("message", handleMessage);
10930
+ releaseTracker();
10770
10931
  };
10771
10932
  }
10772
10933
 
@@ -3976,6 +3976,13 @@
3976
3976
  })
3977
3977
  }
3978
3978
 
3979
+ // SVG-as-image never advances animations, so entrance animations would
3980
+ // rasterize at their first frame; a huge negative delay renders the end.
3981
+ var CAPTURE_FREEZE_ANIMATIONS_CSS =
3982
+ "*,*::before,*::after{animation-delay:-1e6s!important;" +
3983
+ "animation-duration:1s!important;animation-iteration-count:1!important;" +
3984
+ "transition:none!important}"
3985
+
3979
3986
  /**
3980
3987
  * CSS text for the capture clone: same-origin sheets have their
3981
3988
  * `@media` flattened against the LIVE viewport (see `flattenStyleRules`)
@@ -4048,7 +4055,11 @@
4048
4055
  CSS_INLINE_TIMEOUT_MS,
4049
4056
  null
4050
4057
  ).then(function () {
4051
- return renderNodes(topNodes, pieces).replace(/:root\b/g, "html")
4058
+ return (
4059
+ renderNodes(topNodes, pieces).replace(/:root\b/g, "html") +
4060
+ "\n" +
4061
+ CAPTURE_FREEZE_ANIMATIONS_CSS
4062
+ )
4052
4063
  })
4053
4064
  }
4054
4065
 
@@ -3976,6 +3976,13 @@
3976
3976
  })
3977
3977
  }
3978
3978
 
3979
+ // SVG-as-image never advances animations, so entrance animations would
3980
+ // rasterize at their first frame; a huge negative delay renders the end.
3981
+ var CAPTURE_FREEZE_ANIMATIONS_CSS =
3982
+ "*,*::before,*::after{animation-delay:-1e6s!important;" +
3983
+ "animation-duration:1s!important;animation-iteration-count:1!important;" +
3984
+ "transition:none!important}"
3985
+
3979
3986
  /**
3980
3987
  * CSS text for the capture clone: same-origin sheets have their
3981
3988
  * `@media` flattened against the LIVE viewport (see `flattenStyleRules`)
@@ -4048,7 +4055,11 @@
4048
4055
  CSS_INLINE_TIMEOUT_MS,
4049
4056
  null
4050
4057
  ).then(function () {
4051
- return renderNodes(topNodes, pieces).replace(/:root\b/g, "html")
4058
+ return (
4059
+ renderNodes(topNodes, pieces).replace(/:root\b/g, "html") +
4060
+ "\n" +
4061
+ CAPTURE_FREEZE_ANIMATIONS_CSS
4062
+ )
4052
4063
  })
4053
4064
  }
4054
4065
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@archie/devtools",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "description": "DevTools for Archie generated applications - Route synchronization and editor communication",
5
5
  "sideEffects": false,
6
6
  "repository": {