uidex 0.6.0 → 0.7.0

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.
Files changed (39) hide show
  1. package/README.md +3 -3
  2. package/dist/cli/cli.cjs +1510 -1244
  3. package/dist/cli/cli.cjs.map +1 -1
  4. package/dist/cloud/index.cjs +385 -175
  5. package/dist/cloud/index.cjs.map +1 -1
  6. package/dist/cloud/index.d.cts +192 -4
  7. package/dist/cloud/index.d.ts +192 -4
  8. package/dist/cloud/index.js +377 -177
  9. package/dist/cloud/index.js.map +1 -1
  10. package/dist/headless/index.cjs +82 -255
  11. package/dist/headless/index.cjs.map +1 -1
  12. package/dist/headless/index.d.cts +5 -11
  13. package/dist/headless/index.d.ts +5 -11
  14. package/dist/headless/index.js +82 -257
  15. package/dist/headless/index.js.map +1 -1
  16. package/dist/index.cjs +721 -1053
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +149 -160
  19. package/dist/index.d.ts +149 -160
  20. package/dist/index.js +741 -1068
  21. package/dist/index.js.map +1 -1
  22. package/dist/react/index.cjs +729 -1000
  23. package/dist/react/index.cjs.map +1 -1
  24. package/dist/react/index.d.cts +99 -86
  25. package/dist/react/index.d.ts +99 -86
  26. package/dist/react/index.js +745 -1015
  27. package/dist/react/index.js.map +1 -1
  28. package/dist/scan/index.cjs +1518 -1237
  29. package/dist/scan/index.cjs.map +1 -1
  30. package/dist/scan/index.d.cts +209 -12
  31. package/dist/scan/index.d.ts +209 -12
  32. package/dist/scan/index.js +1515 -1236
  33. package/dist/scan/index.js.map +1 -1
  34. package/package.json +22 -21
  35. package/templates/claude/SKILL.md +71 -0
  36. package/templates/claude/references/audit.md +43 -0
  37. package/templates/claude/{rules.md → references/conventions.md} +25 -28
  38. package/templates/claude/audit.md +0 -43
  39. /package/templates/claude/{api.md → references/api.md} +0 -0
@@ -44,11 +44,6 @@ function isMetaEntity(entity) {
44
44
  function entityKey(entity) {
45
45
  return entity.kind === "route" ? entity.path : entity.id;
46
46
  }
47
- function sameRef(a, b) {
48
- if (a === b) return true;
49
- if (a === null || b === null) return false;
50
- return a.kind === b.kind && a.id === b.id;
51
- }
52
47
  var UnknownEntityKindError = class extends Error {
53
48
  kind;
54
49
  constructor(kind) {
@@ -113,13 +108,14 @@ function createRegistry() {
113
108
  };
114
109
  const getPatternsForKind = (kind) => {
115
110
  const cached = patternCache.get(kind);
116
- if (cached !== void 0)
117
- return cached;
111
+ if (cached !== void 0) return cached;
118
112
  const patterns = [];
119
113
  for (const [key, entity] of store[kind]) {
120
- if (key.endsWith("*")) {
114
+ if (key.includes("*")) {
115
+ const segments = key.split("*");
121
116
  patterns.push({
122
- prefix: key.slice(0, -1),
117
+ segments,
118
+ staticLength: segments.reduce((n, s) => n + s.length, 0),
123
119
  entity
124
120
  });
125
121
  }
@@ -130,13 +126,25 @@ function createRegistry() {
130
126
  );
131
127
  return patterns;
132
128
  };
129
+ const matchesSegments = (segments, id) => {
130
+ const first = segments[0];
131
+ const last = segments[segments.length - 1];
132
+ if (!id.startsWith(first)) return false;
133
+ let pos = first.length;
134
+ for (let i = 1; i < segments.length - 1; i++) {
135
+ const idx = id.indexOf(segments[i], pos);
136
+ if (idx === -1) return false;
137
+ pos = idx + segments[i].length;
138
+ }
139
+ return id.endsWith(last) && id.length - last.length >= pos;
140
+ };
133
141
  const matchPattern = (kind, id) => {
134
142
  assertEntityKind(kind);
135
143
  const patterns = getPatternsForKind(kind);
136
144
  if (patterns.length === 0) return void 0;
137
145
  let best;
138
146
  for (const entry of patterns) {
139
- if (id.startsWith(entry.prefix) && (best === void 0 || entry.prefix.length > best.prefix.length)) {
147
+ if (matchesSegments(entry.segments, id) && (best === void 0 || entry.staticLength > best.staticLength)) {
140
148
  best = entry;
141
149
  }
142
150
  }
@@ -318,8 +326,7 @@ var COMMAND_PALETTE_ENTRY = {
318
326
  function createModeStore(options) {
319
327
  const { nav, bindings } = options;
320
328
  const store = (0, import_vanilla.createStore)(() => ({
321
- mode: "idle",
322
- inspectorActive: false
329
+ mode: "idle"
323
330
  }));
324
331
  const transition = {
325
332
  openPalette() {
@@ -328,17 +335,17 @@ function createModeStore(options) {
328
335
  bindings?.destroyInspector?.();
329
336
  }
330
337
  nav.nav.reset([COMMAND_PALETTE_ENTRY]);
331
- store.setState({ mode: "palette", inspectorActive: false });
338
+ store.setState({ mode: "palette" });
332
339
  },
333
340
  openInspector() {
334
341
  bindings?.mountInspector?.();
335
342
  nav.nav.clear();
336
- store.setState({ mode: "inspecting", inspectorActive: true });
343
+ store.setState({ mode: "inspecting" });
337
344
  },
338
345
  closeInspector() {
339
346
  bindings?.destroyInspector?.();
340
347
  nav.nav.clear();
341
- store.setState({ mode: "idle", inspectorActive: false });
348
+ store.setState({ mode: "idle" });
342
349
  },
343
350
  toggleInspector() {
344
351
  if (store.getState().mode === "inspecting") {
@@ -353,7 +360,7 @@ function createModeStore(options) {
353
360
  bindings?.destroyInspector?.();
354
361
  }
355
362
  nav.nav.reset(initialStack);
356
- store.setState({ mode: "viewing", inspectorActive: false });
363
+ store.setState({ mode: "viewing" });
357
364
  },
358
365
  dismiss() {
359
366
  const prev = store.getState();
@@ -361,7 +368,7 @@ function createModeStore(options) {
361
368
  bindings?.destroyInspector?.();
362
369
  }
363
370
  nav.nav.clear();
364
- store.setState({ mode: "idle", inspectorActive: false });
371
+ store.setState({ mode: "idle" });
365
372
  },
366
373
  popOrTransition() {
367
374
  const { stack } = nav.getState();
@@ -369,12 +376,12 @@ function createModeStore(options) {
369
376
  nav.nav.pop();
370
377
  } else if (stack.length === 2 && stack[0]?.id === "command-palette") {
371
378
  nav.nav.reset([COMMAND_PALETTE_ENTRY]);
372
- store.setState({ mode: "palette", inspectorActive: false });
379
+ store.setState({ mode: "palette" });
373
380
  } else if (stack.length === 2) {
374
381
  nav.nav.pop();
375
382
  } else {
376
383
  nav.nav.clear();
377
- store.setState({ mode: "idle", inspectorActive: false });
384
+ store.setState({ mode: "idle" });
378
385
  }
379
386
  },
380
387
  pushView(entry) {
@@ -391,7 +398,7 @@ function createModeStore(options) {
391
398
  case "inspecting":
392
399
  bindings?.destroyInspector?.();
393
400
  nav.nav.reset([entry]);
394
- store.setState({ mode: "viewing", inspectorActive: false });
401
+ store.setState({ mode: "viewing" });
395
402
  break;
396
403
  case "palette":
397
404
  case "viewing":
@@ -426,14 +433,6 @@ function createNavigationStore() {
426
433
  store.setState({ stack: s.slice(0, -1) });
427
434
  }
428
435
  },
429
- replace(entry) {
430
- const s = store.getState().stack;
431
- if (s.length === 0) {
432
- store.setState({ stack: [entry] });
433
- } else {
434
- store.setState({ stack: [...s.slice(0, -1), entry] });
435
- }
436
- },
437
436
  clear() {
438
437
  store.setState({ stack: [] });
439
438
  },
@@ -448,14 +447,11 @@ function createNavigationStore() {
448
447
 
449
448
  // src/browser/session/store.ts
450
449
  var defaultSnapshot = {
451
- hover: null,
452
- selection: null,
453
450
  stack: [],
454
451
  pinnedHighlight: null,
455
- inspectorActive: false,
452
+ mode: "idle",
456
453
  theme: "auto",
457
454
  resolvedTheme: "light",
458
- ingestActive: false,
459
455
  user: null
460
456
  };
461
457
  function resolveTheme(preference, detect) {
@@ -506,7 +502,6 @@ function createSession(options = {}) {
506
502
  } else if (highlightMode === "transient") {
507
503
  onUpdateOverlay?.(hlCtx);
508
504
  }
509
- store.setState({ hover: ref });
510
505
  },
511
506
  unhover() {
512
507
  if (highlightMode === "transient") {
@@ -516,7 +511,6 @@ function createSession(options = {}) {
516
511
  hlCtx.color = null;
517
512
  onHideOverlay?.();
518
513
  }
519
- store.setState({ hover: null });
520
514
  },
521
515
  pin(ref) {
522
516
  const pinRef = ref ?? hlCtx.ref;
@@ -544,14 +538,11 @@ function createSession(options = {}) {
544
538
  };
545
539
  const store = (0, import_vanilla3.createStore)(() => ({
546
540
  ...defaultSnapshot,
547
- hover: overrides.hover ?? null,
548
- selection: overrides.selection ?? null,
549
541
  stack: [],
550
542
  pinnedHighlight: null,
551
- inspectorActive: false,
543
+ mode: "idle",
552
544
  theme: initialPref,
553
545
  resolvedTheme: initialResolved,
554
- ingestActive: overrides.ingestActive ?? false,
555
546
  user: overrides.user ?? null
556
547
  }));
557
548
  nav.subscribe(() => {
@@ -561,29 +552,21 @@ function createSession(options = {}) {
561
552
  }
562
553
  });
563
554
  modeStore.subscribe(() => {
564
- const { inspectorActive } = modeStore.getState();
565
- if (store.getState().inspectorActive !== inspectorActive) {
566
- store.setState({ inspectorActive });
555
+ const { mode } = modeStore.getState();
556
+ if (store.getState().mode !== mode) {
557
+ store.setState({ mode });
567
558
  }
568
559
  });
569
560
  const session = store;
570
561
  session.nav = nav;
571
562
  session.mode = modeStore;
572
563
  session.highlight = highlightActions;
573
- session.select = (ref) => {
574
- if (sameRef(store.getState().selection, ref)) return;
575
- store.setState({ selection: ref });
576
- };
577
564
  session.setTheme = (theme, resolved) => {
578
565
  const state = store.getState();
579
566
  const nextResolved = resolved ?? resolveTheme(theme, detectTheme);
580
567
  if (state.theme === theme && state.resolvedTheme === nextResolved) return;
581
568
  store.setState({ theme, resolvedTheme: nextResolved });
582
569
  };
583
- session.setIngest = (active) => {
584
- if (store.getState().ingestActive === active) return;
585
- store.setState({ ingestActive: active });
586
- };
587
570
  if (initialStack.length > 0) {
588
571
  modeStore.transition.openPalette();
589
572
  for (let i = 1; i < initialStack.length; i++) {
@@ -896,9 +879,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
896
879
  .right-0 {
897
880
  right: calc(var(--spacing) * 0);
898
881
  }
899
- .right-2 {
900
- right: calc(var(--spacing) * 2);
901
- }
902
882
  .bottom-full {
903
883
  bottom: 100%;
904
884
  }
@@ -941,9 +921,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
941
921
  .mx-2 {
942
922
  margin-inline: calc(var(--spacing) * 2);
943
923
  }
944
- .my-1 {
945
- margin-block: calc(var(--spacing) * 1);
946
- }
947
924
  .ms-auto {
948
925
  margin-inline-start: auto;
949
926
  }
@@ -980,9 +957,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
980
957
  .inline-flex {
981
958
  display: inline-flex;
982
959
  }
983
- .list-item {
984
- display: list-item;
985
- }
986
960
  .table {
987
961
  display: table;
988
962
  }
@@ -990,10 +964,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
990
964
  width: calc(var(--spacing) * 2);
991
965
  height: calc(var(--spacing) * 2);
992
966
  }
993
- .size-3 {
994
- width: calc(var(--spacing) * 3);
995
- height: calc(var(--spacing) * 3);
996
- }
997
967
  .size-3\\.5 {
998
968
  width: calc(var(--spacing) * 3.5);
999
969
  height: calc(var(--spacing) * 3.5);
@@ -1051,15 +1021,9 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1051
1021
  .h-\\[26rem\\] {
1052
1022
  height: 26rem;
1053
1023
  }
1054
- .h-auto {
1055
- height: auto;
1056
- }
1057
1024
  .h-full {
1058
1025
  height: 100%;
1059
1026
  }
1060
- .h-px {
1061
- height: 1px;
1062
- }
1063
1027
  .max-h-32 {
1064
1028
  max-height: calc(var(--spacing) * 32);
1065
1029
  }
@@ -1069,9 +1033,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1069
1033
  .min-h-0 {
1070
1034
  min-height: calc(var(--spacing) * 0);
1071
1035
  }
1072
- .min-h-7 {
1073
- min-height: calc(var(--spacing) * 7);
1074
- }
1075
1036
  .min-h-8 {
1076
1037
  min-height: calc(var(--spacing) * 8);
1077
1038
  }
@@ -1096,9 +1057,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1096
1057
  .w-56 {
1097
1058
  width: calc(var(--spacing) * 56);
1098
1059
  }
1099
- .w-auto {
1100
- width: auto;
1101
- }
1102
1060
  .w-full {
1103
1061
  width: 100%;
1104
1062
  }
@@ -1173,9 +1131,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1173
1131
  .animate-spin {
1174
1132
  animation: var(--animate-spin);
1175
1133
  }
1176
- .cursor-default {
1177
- cursor: default;
1178
- }
1179
1134
  .cursor-pointer {
1180
1135
  cursor: pointer;
1181
1136
  }
@@ -1185,9 +1140,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1185
1140
  .scroll-py-2 {
1186
1141
  scroll-padding-block: calc(var(--spacing) * 2);
1187
1142
  }
1188
- .list-none {
1189
- list-style-type: none;
1190
- }
1191
1143
  .appearance-none {
1192
1144
  appearance: none;
1193
1145
  }
@@ -1209,9 +1161,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1209
1161
  .justify-center {
1210
1162
  justify-content: center;
1211
1163
  }
1212
- .justify-start {
1213
- justify-content: flex-start;
1214
- }
1215
1164
  .gap-0 {
1216
1165
  gap: calc(var(--spacing) * 0);
1217
1166
  }
@@ -1236,9 +1185,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1236
1185
  .gap-6 {
1237
1186
  gap: calc(var(--spacing) * 6);
1238
1187
  }
1239
- .self-start {
1240
- align-self: flex-start;
1241
- }
1242
1188
  .truncate {
1243
1189
  overflow: hidden;
1244
1190
  text-overflow: ellipsis;
@@ -1453,9 +1399,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1453
1399
  .p-6 {
1454
1400
  padding: calc(var(--spacing) * 6);
1455
1401
  }
1456
- .px-0 {
1457
- padding-inline: calc(var(--spacing) * 0);
1458
- }
1459
1402
  .px-1 {
1460
1403
  padding-inline: calc(var(--spacing) * 1);
1461
1404
  }
@@ -1480,9 +1423,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1480
1423
  .px-6 {
1481
1424
  padding-inline: calc(var(--spacing) * 6);
1482
1425
  }
1483
- .py-0 {
1484
- padding-block: calc(var(--spacing) * 0);
1485
- }
1486
1426
  .py-1 {
1487
1427
  padding-block: calc(var(--spacing) * 1);
1488
1428
  }
@@ -1555,9 +1495,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1555
1495
  .text-\\[9px\\] {
1556
1496
  font-size: 9px;
1557
1497
  }
1558
- .text-\\[10px\\] {
1559
- font-size: 10px;
1560
- }
1561
1498
  .text-\\[11px\\] {
1562
1499
  font-size: 11px;
1563
1500
  }
@@ -1797,10 +1734,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1797
1734
  outline-style: var(--tw-outline-style);
1798
1735
  outline-width: 1px;
1799
1736
  }
1800
- .blur {
1801
- --tw-blur: blur(8px);
1802
- filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
1803
- }
1804
1737
  .filter {
1805
1738
  filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
1806
1739
  }
@@ -1966,25 +1899,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1966
1899
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
1967
1900
  }
1968
1901
  }
1969
- .focus-within\\:border-ring {
1970
- &:focus-within {
1971
- border-color: var(--ring);
1972
- }
1973
- }
1974
- .focus-within\\:ring-\\[3px\\] {
1975
- &:focus-within {
1976
- --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
1977
- box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
1978
- }
1979
- }
1980
- .focus-within\\:ring-ring\\/30 {
1981
- &:focus-within {
1982
- --tw-ring-color: var(--ring);
1983
- @supports (color: color-mix(in lab, red, red)) {
1984
- --tw-ring-color: color-mix(in oklab, var(--ring) 30%, transparent);
1985
- }
1986
- }
1987
- }
1988
1902
  .hover\\:border-destructive\\/30 {
1989
1903
  &:hover {
1990
1904
  @media (hover: hover) {
@@ -2128,11 +2042,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
2128
2042
  pointer-events: none;
2129
2043
  }
2130
2044
  }
2131
- .disabled\\:cursor-not-allowed {
2132
- &:disabled {
2133
- cursor: not-allowed;
2134
- }
2135
- }
2136
2045
  .disabled\\:opacity-50 {
2137
2046
  &:disabled {
2138
2047
  opacity: 50%;
@@ -2143,11 +2052,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
2143
2052
  opacity: 60%;
2144
2053
  }
2145
2054
  }
2146
- .has-disabled\\:opacity-60 {
2147
- &:has(*:disabled) {
2148
- opacity: 60%;
2149
- }
2150
- }
2151
2055
  .aria-invalid\\:border-destructive\\/40 {
2152
2056
  &[aria-invalid="true"] {
2153
2057
  border-color: var(--destructive);
@@ -2554,32 +2458,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
2554
2458
  height: calc(var(--spacing) * 4.5);
2555
2459
  }
2556
2460
  }
2557
- .\\[\\&\\>svg\\]\\:pointer-events-none {
2558
- &>svg {
2559
- pointer-events: none;
2560
- }
2561
- }
2562
- .\\[\\&\\>svg\\]\\:-mx-0\\.5 {
2563
- &>svg {
2564
- margin-inline: calc(var(--spacing) * -0.5);
2565
- }
2566
- }
2567
- .\\[\\&\\>svg\\]\\:shrink-0 {
2568
- &>svg {
2569
- flex-shrink: 0;
2570
- }
2571
- }
2572
- .\\[\\&\\>svg\\:not\\(\\[class\\*\\=\\'opacity-\\'\\]\\)\\]\\:opacity-80 {
2573
- &>svg:not([class*='opacity-']) {
2574
- opacity: 80%;
2575
- }
2576
- }
2577
- .\\[\\&\\>svg\\:not\\(\\[class\\*\\=\\'size-\\'\\]\\)\\]\\:size-4 {
2578
- &>svg:not([class*='size-']) {
2579
- width: calc(var(--spacing) * 4);
2580
- height: calc(var(--spacing) * 4);
2581
- }
2582
- }
2583
2461
  .\\[\\[data-kbd-nav\\]_\\&\\]\\:focus-within\\:bg-accent {
2584
2462
  [data-kbd-nav] & {
2585
2463
  &:focus-within {
@@ -3141,11 +3019,10 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
3141
3019
 
3142
3020
  // src/browser/surface/constants.ts
3143
3021
  var SURFACE_HOST_CLASS = "uidex-surface-host";
3144
- var SURFACE_CONTAINER_CLASS = "uidex-container";
3145
3022
  var Z_BASE = 2147483630;
3146
3023
  var Z_OVERLAY = 2147483635;
3147
3024
  var Z_CHROME = 2147483645;
3148
- var SURFACE_IGNORE_SELECTOR = `.${SURFACE_HOST_CLASS},.${SURFACE_CONTAINER_CLASS}`;
3025
+ var SURFACE_IGNORE_SELECTOR = `.${SURFACE_HOST_CLASS}`;
3149
3026
  var UIDEX_ATTR_TO_KIND = [
3150
3027
  ["data-uidex", "element"],
3151
3028
  ["data-uidex-region", "region"],
@@ -3432,7 +3309,6 @@ function createInspector(options) {
3432
3309
  e.preventDefault();
3433
3310
  e.stopPropagation();
3434
3311
  const match = stack[layerIndex];
3435
- session.select(match.ref);
3436
3312
  onSelect?.(match, { x: e.clientX, y: e.clientY });
3437
3313
  };
3438
3314
  const onContextMenu = (e) => {
@@ -3629,49 +3505,12 @@ function createMenuBar(options) {
3629
3505
  },
3630
3506
  pinIcon
3631
3507
  );
3632
- const commitCycler = el("div", {
3633
- class: "relative z-1 inline-flex items-center gap-0.5",
3634
- attrs: { "data-uidex-menubar-commit-cycler": "" }
3635
- });
3636
- commitCycler.hidden = true;
3637
- const prevIcon = (0, import_lucide3.createElement)(import_lucide3.ChevronLeft);
3638
- prevIcon.setAttribute("class", "size-3");
3639
- prevIcon.setAttribute("aria-hidden", "true");
3640
- const prevBtn = el(
3641
- "button",
3642
- {
3643
- class: BUTTON_CLASS,
3644
- attrs: { type: "button", "aria-label": "Previous commit" },
3645
- style: { width: "18px", height: "18px" }
3646
- },
3647
- prevIcon
3648
- );
3649
- const commitLabel = el("span", {
3650
- class: "relative z-1 whitespace-nowrap px-1 text-[10px] font-mono text-muted-foreground",
3651
- attrs: { "data-uidex-menubar-commit-label": "" }
3652
- });
3653
- const nextIcon = (0, import_lucide3.createElement)(import_lucide3.ChevronRight);
3654
- nextIcon.setAttribute("class", "size-3");
3655
- nextIcon.setAttribute("aria-hidden", "true");
3656
- const nextBtn = el(
3657
- "button",
3658
- {
3659
- class: BUTTON_CLASS,
3660
- attrs: { type: "button", "aria-label": "Next commit" },
3661
- style: { width: "18px", height: "18px" }
3662
- },
3663
- nextIcon
3664
- );
3665
- commitCycler.appendChild(prevBtn);
3666
- commitCycler.appendChild(commitLabel);
3667
- commitCycler.appendChild(nextBtn);
3668
3508
  const pinWrapper = el("div", {
3669
3509
  class: "relative z-1 inline-flex items-center gap-0.5",
3670
3510
  attrs: { "data-uidex-menubar-pin-wrapper": "" }
3671
3511
  });
3672
3512
  pinWrapper.hidden = true;
3673
3513
  pinWrapper.appendChild(pinBtn);
3674
- pinWrapper.appendChild(commitCycler);
3675
3514
  root.appendChild(pinWrapper);
3676
3515
  const updatePinUI = () => {
3677
3516
  if (!activePinLayer) {
@@ -3679,16 +3518,7 @@ function createMenuBar(options) {
3679
3518
  return;
3680
3519
  }
3681
3520
  const pinsVisible = activePinLayer.visible;
3682
- const state = activePinLayer.filterState;
3683
- const hasCommits = state.commits.length > 0;
3684
3521
  pinWrapper.hidden = false;
3685
- commitCycler.hidden = !pinsVisible || !hasCommits;
3686
- if (state.commitIndex === -1 || !state.commits[state.commitIndex]) {
3687
- commitLabel.textContent = `all (${state.commits.length})`;
3688
- } else {
3689
- const sha = state.commits[state.commitIndex] ?? "";
3690
- commitLabel.textContent = sha.slice(0, 7);
3691
- }
3692
3522
  pinBtn.className = cn(BUTTON_CLASS, pinsVisible && BUTTON_ACTIVE_CLASS);
3693
3523
  };
3694
3524
  pinBtn.addEventListener("click", (e) => {
@@ -3697,14 +3527,6 @@ function createMenuBar(options) {
3697
3527
  activePinLayer.setVisible(!activePinLayer.visible);
3698
3528
  }
3699
3529
  });
3700
- prevBtn.addEventListener("click", (e) => {
3701
- e.stopPropagation();
3702
- activePinLayer?.prevCommit();
3703
- });
3704
- nextBtn.addEventListener("click", (e) => {
3705
- e.stopPropagation();
3706
- activePinLayer?.nextCommit();
3707
- });
3708
3530
  let unsubscribePinFilter = activePinLayer?.onFilterChange(() => updatePinUI());
3709
3531
  const presenceIcon = (0, import_lucide3.createElement)(import_lucide3.Users);
3710
3532
  presenceIcon.setAttribute("class", "size-3.5");
@@ -3798,7 +3620,7 @@ function createMenuBar(options) {
3798
3620
  container.appendChild(root);
3799
3621
  const syncButtonStates = () => {
3800
3622
  const state = session.getState();
3801
- const inspectActive = state.inspectorActive;
3623
+ const inspectActive = state.mode === "inspecting";
3802
3624
  inspectBtn.setAttribute(
3803
3625
  "data-uidex-menubar-inspect-active",
3804
3626
  inspectActive ? "true" : "false"
@@ -3917,6 +3739,49 @@ function createMenuBar(options) {
3917
3739
  };
3918
3740
  }
3919
3741
 
3742
+ // src/browser/internal/repositioner.ts
3743
+ function createRepositioner(onReflow) {
3744
+ let rafId = null;
3745
+ let attached = false;
3746
+ const schedule = () => {
3747
+ if (rafId !== null) return;
3748
+ rafId = typeof requestAnimationFrame === "function" ? requestAnimationFrame(() => {
3749
+ rafId = null;
3750
+ onReflow();
3751
+ }) : setTimeout(() => {
3752
+ rafId = null;
3753
+ onReflow();
3754
+ }, 0);
3755
+ };
3756
+ const cancel = () => {
3757
+ if (rafId === null) return;
3758
+ if (typeof cancelAnimationFrame === "function") cancelAnimationFrame(rafId);
3759
+ else clearTimeout(rafId);
3760
+ rafId = null;
3761
+ };
3762
+ const onScroll = () => schedule();
3763
+ const onResize = () => schedule();
3764
+ const attach = () => {
3765
+ if (attached) return;
3766
+ attached = true;
3767
+ window.addEventListener("resize", onResize);
3768
+ window.addEventListener("scroll", onScroll, {
3769
+ capture: true,
3770
+ passive: true
3771
+ });
3772
+ };
3773
+ const detach = () => {
3774
+ if (!attached) return;
3775
+ attached = false;
3776
+ window.removeEventListener("resize", onResize);
3777
+ window.removeEventListener("scroll", onScroll, {
3778
+ capture: true
3779
+ });
3780
+ cancel();
3781
+ };
3782
+ return { schedule, cancel, attach, detach };
3783
+ }
3784
+
3920
3785
  // src/browser/surface/overlay.ts
3921
3786
  var DEFAULT_COLOR = "#34d399";
3922
3787
  var DEFAULT_BORDER_WIDTH = 2;
@@ -3984,44 +3849,7 @@ function createOverlay(deps) {
3984
3849
  fillOpacity: DEFAULT_FILL_OPACITY,
3985
3850
  backdrop: false
3986
3851
  };
3987
- let rafId = null;
3988
- let attached = false;
3989
- const schedule = () => {
3990
- if (rafId !== null) return;
3991
- rafId = typeof requestAnimationFrame === "function" ? requestAnimationFrame(() => {
3992
- rafId = null;
3993
- updatePosition();
3994
- }) : setTimeout(() => {
3995
- rafId = null;
3996
- updatePosition();
3997
- }, 0);
3998
- };
3999
- const cancelSchedule = () => {
4000
- if (rafId === null) return;
4001
- if (typeof cancelAnimationFrame === "function") cancelAnimationFrame(rafId);
4002
- else clearTimeout(rafId);
4003
- rafId = null;
4004
- };
4005
- const onScroll = () => schedule();
4006
- const onResize = () => schedule();
4007
- const attach = () => {
4008
- if (attached) return;
4009
- attached = true;
4010
- window.addEventListener("resize", onResize);
4011
- window.addEventListener("scroll", onScroll, {
4012
- capture: true,
4013
- passive: true
4014
- });
4015
- };
4016
- const detach = () => {
4017
- if (!attached) return;
4018
- attached = false;
4019
- window.removeEventListener("resize", onResize);
4020
- window.removeEventListener("scroll", onScroll, {
4021
- capture: true
4022
- });
4023
- cancelSchedule();
4024
- };
3852
+ const repositioner = createRepositioner(() => updatePosition());
4025
3853
  function updatePosition() {
4026
3854
  if (!target) return;
4027
3855
  const rect = target.getBoundingClientRect();
@@ -4085,16 +3913,16 @@ function createOverlay(deps) {
4085
3913
  box.offsetHeight;
4086
3914
  }
4087
3915
  box.style.opacity = "1";
4088
- attach();
3916
+ repositioner.attach();
4089
3917
  },
4090
3918
  hide() {
4091
3919
  target = null;
4092
3920
  box.style.opacity = "0";
4093
3921
  backdrop.style.opacity = "0";
4094
- detach();
3922
+ repositioner.detach();
4095
3923
  },
4096
3924
  destroy() {
4097
- detach();
3925
+ repositioner.detach();
4098
3926
  box.remove();
4099
3927
  backdrop.remove();
4100
3928
  target = null;
@@ -4211,8 +4039,7 @@ function createSurfaceShell(options) {
4211
4039
  const overlay = createOverlay({ container: host.shadowRoot });
4212
4040
  cleanup.add(overlay);
4213
4041
  const tooltip = createCursorTooltip({
4214
- container: host.chromeEl,
4215
- session: options.session
4042
+ container: host.chromeEl
4216
4043
  });
4217
4044
  cleanup.add(tooltip);
4218
4045
  const afterHover = options.inspector?.onAfterHover;