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
@@ -18,11 +18,6 @@ function isMetaEntity(entity) {
18
18
  function entityKey(entity) {
19
19
  return entity.kind === "route" ? entity.path : entity.id;
20
20
  }
21
- function sameRef(a, b) {
22
- if (a === b) return true;
23
- if (a === null || b === null) return false;
24
- return a.kind === b.kind && a.id === b.id;
25
- }
26
21
  var UnknownEntityKindError = class extends Error {
27
22
  kind;
28
23
  constructor(kind) {
@@ -87,13 +82,14 @@ function createRegistry() {
87
82
  };
88
83
  const getPatternsForKind = (kind) => {
89
84
  const cached = patternCache.get(kind);
90
- if (cached !== void 0)
91
- return cached;
85
+ if (cached !== void 0) return cached;
92
86
  const patterns = [];
93
87
  for (const [key, entity] of store[kind]) {
94
- if (key.endsWith("*")) {
88
+ if (key.includes("*")) {
89
+ const segments = key.split("*");
95
90
  patterns.push({
96
- prefix: key.slice(0, -1),
91
+ segments,
92
+ staticLength: segments.reduce((n, s) => n + s.length, 0),
97
93
  entity
98
94
  });
99
95
  }
@@ -104,13 +100,25 @@ function createRegistry() {
104
100
  );
105
101
  return patterns;
106
102
  };
103
+ const matchesSegments = (segments, id) => {
104
+ const first = segments[0];
105
+ const last = segments[segments.length - 1];
106
+ if (!id.startsWith(first)) return false;
107
+ let pos = first.length;
108
+ for (let i = 1; i < segments.length - 1; i++) {
109
+ const idx = id.indexOf(segments[i], pos);
110
+ if (idx === -1) return false;
111
+ pos = idx + segments[i].length;
112
+ }
113
+ return id.endsWith(last) && id.length - last.length >= pos;
114
+ };
107
115
  const matchPattern = (kind, id) => {
108
116
  assertEntityKind(kind);
109
117
  const patterns = getPatternsForKind(kind);
110
118
  if (patterns.length === 0) return void 0;
111
119
  let best;
112
120
  for (const entry of patterns) {
113
- if (id.startsWith(entry.prefix) && (best === void 0 || entry.prefix.length > best.prefix.length)) {
121
+ if (matchesSegments(entry.segments, id) && (best === void 0 || entry.staticLength > best.staticLength)) {
114
122
  best = entry;
115
123
  }
116
124
  }
@@ -301,8 +309,7 @@ var COMMAND_PALETTE_ENTRY = {
301
309
  function createModeStore(options) {
302
310
  const { nav, bindings } = options;
303
311
  const store = createStore(() => ({
304
- mode: "idle",
305
- inspectorActive: false
312
+ mode: "idle"
306
313
  }));
307
314
  const transition = {
308
315
  openPalette() {
@@ -311,17 +318,17 @@ function createModeStore(options) {
311
318
  bindings?.destroyInspector?.();
312
319
  }
313
320
  nav.nav.reset([COMMAND_PALETTE_ENTRY]);
314
- store.setState({ mode: "palette", inspectorActive: false });
321
+ store.setState({ mode: "palette" });
315
322
  },
316
323
  openInspector() {
317
324
  bindings?.mountInspector?.();
318
325
  nav.nav.clear();
319
- store.setState({ mode: "inspecting", inspectorActive: true });
326
+ store.setState({ mode: "inspecting" });
320
327
  },
321
328
  closeInspector() {
322
329
  bindings?.destroyInspector?.();
323
330
  nav.nav.clear();
324
- store.setState({ mode: "idle", inspectorActive: false });
331
+ store.setState({ mode: "idle" });
325
332
  },
326
333
  toggleInspector() {
327
334
  if (store.getState().mode === "inspecting") {
@@ -336,7 +343,7 @@ function createModeStore(options) {
336
343
  bindings?.destroyInspector?.();
337
344
  }
338
345
  nav.nav.reset(initialStack);
339
- store.setState({ mode: "viewing", inspectorActive: false });
346
+ store.setState({ mode: "viewing" });
340
347
  },
341
348
  dismiss() {
342
349
  const prev = store.getState();
@@ -344,7 +351,7 @@ function createModeStore(options) {
344
351
  bindings?.destroyInspector?.();
345
352
  }
346
353
  nav.nav.clear();
347
- store.setState({ mode: "idle", inspectorActive: false });
354
+ store.setState({ mode: "idle" });
348
355
  },
349
356
  popOrTransition() {
350
357
  const { stack } = nav.getState();
@@ -352,12 +359,12 @@ function createModeStore(options) {
352
359
  nav.nav.pop();
353
360
  } else if (stack.length === 2 && stack[0]?.id === "command-palette") {
354
361
  nav.nav.reset([COMMAND_PALETTE_ENTRY]);
355
- store.setState({ mode: "palette", inspectorActive: false });
362
+ store.setState({ mode: "palette" });
356
363
  } else if (stack.length === 2) {
357
364
  nav.nav.pop();
358
365
  } else {
359
366
  nav.nav.clear();
360
- store.setState({ mode: "idle", inspectorActive: false });
367
+ store.setState({ mode: "idle" });
361
368
  }
362
369
  },
363
370
  pushView(entry) {
@@ -374,7 +381,7 @@ function createModeStore(options) {
374
381
  case "inspecting":
375
382
  bindings?.destroyInspector?.();
376
383
  nav.nav.reset([entry]);
377
- store.setState({ mode: "viewing", inspectorActive: false });
384
+ store.setState({ mode: "viewing" });
378
385
  break;
379
386
  case "palette":
380
387
  case "viewing":
@@ -409,14 +416,6 @@ function createNavigationStore() {
409
416
  store.setState({ stack: s.slice(0, -1) });
410
417
  }
411
418
  },
412
- replace(entry) {
413
- const s = store.getState().stack;
414
- if (s.length === 0) {
415
- store.setState({ stack: [entry] });
416
- } else {
417
- store.setState({ stack: [...s.slice(0, -1), entry] });
418
- }
419
- },
420
419
  clear() {
421
420
  store.setState({ stack: [] });
422
421
  },
@@ -431,14 +430,11 @@ function createNavigationStore() {
431
430
 
432
431
  // src/browser/session/store.ts
433
432
  var defaultSnapshot = {
434
- hover: null,
435
- selection: null,
436
433
  stack: [],
437
434
  pinnedHighlight: null,
438
- inspectorActive: false,
435
+ mode: "idle",
439
436
  theme: "auto",
440
437
  resolvedTheme: "light",
441
- ingestActive: false,
442
438
  user: null
443
439
  };
444
440
  function resolveTheme(preference, detect) {
@@ -489,7 +485,6 @@ function createSession(options = {}) {
489
485
  } else if (highlightMode === "transient") {
490
486
  onUpdateOverlay?.(hlCtx);
491
487
  }
492
- store.setState({ hover: ref });
493
488
  },
494
489
  unhover() {
495
490
  if (highlightMode === "transient") {
@@ -499,7 +494,6 @@ function createSession(options = {}) {
499
494
  hlCtx.color = null;
500
495
  onHideOverlay?.();
501
496
  }
502
- store.setState({ hover: null });
503
497
  },
504
498
  pin(ref) {
505
499
  const pinRef = ref ?? hlCtx.ref;
@@ -527,14 +521,11 @@ function createSession(options = {}) {
527
521
  };
528
522
  const store = createStore3(() => ({
529
523
  ...defaultSnapshot,
530
- hover: overrides.hover ?? null,
531
- selection: overrides.selection ?? null,
532
524
  stack: [],
533
525
  pinnedHighlight: null,
534
- inspectorActive: false,
526
+ mode: "idle",
535
527
  theme: initialPref,
536
528
  resolvedTheme: initialResolved,
537
- ingestActive: overrides.ingestActive ?? false,
538
529
  user: overrides.user ?? null
539
530
  }));
540
531
  nav.subscribe(() => {
@@ -544,29 +535,21 @@ function createSession(options = {}) {
544
535
  }
545
536
  });
546
537
  modeStore.subscribe(() => {
547
- const { inspectorActive } = modeStore.getState();
548
- if (store.getState().inspectorActive !== inspectorActive) {
549
- store.setState({ inspectorActive });
538
+ const { mode } = modeStore.getState();
539
+ if (store.getState().mode !== mode) {
540
+ store.setState({ mode });
550
541
  }
551
542
  });
552
543
  const session = store;
553
544
  session.nav = nav;
554
545
  session.mode = modeStore;
555
546
  session.highlight = highlightActions;
556
- session.select = (ref) => {
557
- if (sameRef(store.getState().selection, ref)) return;
558
- store.setState({ selection: ref });
559
- };
560
547
  session.setTheme = (theme, resolved) => {
561
548
  const state = store.getState();
562
549
  const nextResolved = resolved ?? resolveTheme(theme, detectTheme);
563
550
  if (state.theme === theme && state.resolvedTheme === nextResolved) return;
564
551
  store.setState({ theme, resolvedTheme: nextResolved });
565
552
  };
566
- session.setIngest = (active) => {
567
- if (store.getState().ingestActive === active) return;
568
- store.setState({ ingestActive: active });
569
- };
570
553
  if (initialStack.length > 0) {
571
554
  modeStore.transition.openPalette();
572
555
  for (let i = 1; i < initialStack.length; i++) {
@@ -879,9 +862,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
879
862
  .right-0 {
880
863
  right: calc(var(--spacing) * 0);
881
864
  }
882
- .right-2 {
883
- right: calc(var(--spacing) * 2);
884
- }
885
865
  .bottom-full {
886
866
  bottom: 100%;
887
867
  }
@@ -924,9 +904,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
924
904
  .mx-2 {
925
905
  margin-inline: calc(var(--spacing) * 2);
926
906
  }
927
- .my-1 {
928
- margin-block: calc(var(--spacing) * 1);
929
- }
930
907
  .ms-auto {
931
908
  margin-inline-start: auto;
932
909
  }
@@ -963,9 +940,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
963
940
  .inline-flex {
964
941
  display: inline-flex;
965
942
  }
966
- .list-item {
967
- display: list-item;
968
- }
969
943
  .table {
970
944
  display: table;
971
945
  }
@@ -973,10 +947,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
973
947
  width: calc(var(--spacing) * 2);
974
948
  height: calc(var(--spacing) * 2);
975
949
  }
976
- .size-3 {
977
- width: calc(var(--spacing) * 3);
978
- height: calc(var(--spacing) * 3);
979
- }
980
950
  .size-3\\.5 {
981
951
  width: calc(var(--spacing) * 3.5);
982
952
  height: calc(var(--spacing) * 3.5);
@@ -1034,15 +1004,9 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1034
1004
  .h-\\[26rem\\] {
1035
1005
  height: 26rem;
1036
1006
  }
1037
- .h-auto {
1038
- height: auto;
1039
- }
1040
1007
  .h-full {
1041
1008
  height: 100%;
1042
1009
  }
1043
- .h-px {
1044
- height: 1px;
1045
- }
1046
1010
  .max-h-32 {
1047
1011
  max-height: calc(var(--spacing) * 32);
1048
1012
  }
@@ -1052,9 +1016,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1052
1016
  .min-h-0 {
1053
1017
  min-height: calc(var(--spacing) * 0);
1054
1018
  }
1055
- .min-h-7 {
1056
- min-height: calc(var(--spacing) * 7);
1057
- }
1058
1019
  .min-h-8 {
1059
1020
  min-height: calc(var(--spacing) * 8);
1060
1021
  }
@@ -1079,9 +1040,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1079
1040
  .w-56 {
1080
1041
  width: calc(var(--spacing) * 56);
1081
1042
  }
1082
- .w-auto {
1083
- width: auto;
1084
- }
1085
1043
  .w-full {
1086
1044
  width: 100%;
1087
1045
  }
@@ -1156,9 +1114,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1156
1114
  .animate-spin {
1157
1115
  animation: var(--animate-spin);
1158
1116
  }
1159
- .cursor-default {
1160
- cursor: default;
1161
- }
1162
1117
  .cursor-pointer {
1163
1118
  cursor: pointer;
1164
1119
  }
@@ -1168,9 +1123,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1168
1123
  .scroll-py-2 {
1169
1124
  scroll-padding-block: calc(var(--spacing) * 2);
1170
1125
  }
1171
- .list-none {
1172
- list-style-type: none;
1173
- }
1174
1126
  .appearance-none {
1175
1127
  appearance: none;
1176
1128
  }
@@ -1192,9 +1144,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1192
1144
  .justify-center {
1193
1145
  justify-content: center;
1194
1146
  }
1195
- .justify-start {
1196
- justify-content: flex-start;
1197
- }
1198
1147
  .gap-0 {
1199
1148
  gap: calc(var(--spacing) * 0);
1200
1149
  }
@@ -1219,9 +1168,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1219
1168
  .gap-6 {
1220
1169
  gap: calc(var(--spacing) * 6);
1221
1170
  }
1222
- .self-start {
1223
- align-self: flex-start;
1224
- }
1225
1171
  .truncate {
1226
1172
  overflow: hidden;
1227
1173
  text-overflow: ellipsis;
@@ -1436,9 +1382,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1436
1382
  .p-6 {
1437
1383
  padding: calc(var(--spacing) * 6);
1438
1384
  }
1439
- .px-0 {
1440
- padding-inline: calc(var(--spacing) * 0);
1441
- }
1442
1385
  .px-1 {
1443
1386
  padding-inline: calc(var(--spacing) * 1);
1444
1387
  }
@@ -1463,9 +1406,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1463
1406
  .px-6 {
1464
1407
  padding-inline: calc(var(--spacing) * 6);
1465
1408
  }
1466
- .py-0 {
1467
- padding-block: calc(var(--spacing) * 0);
1468
- }
1469
1409
  .py-1 {
1470
1410
  padding-block: calc(var(--spacing) * 1);
1471
1411
  }
@@ -1538,9 +1478,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1538
1478
  .text-\\[9px\\] {
1539
1479
  font-size: 9px;
1540
1480
  }
1541
- .text-\\[10px\\] {
1542
- font-size: 10px;
1543
- }
1544
1481
  .text-\\[11px\\] {
1545
1482
  font-size: 11px;
1546
1483
  }
@@ -1780,10 +1717,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1780
1717
  outline-style: var(--tw-outline-style);
1781
1718
  outline-width: 1px;
1782
1719
  }
1783
- .blur {
1784
- --tw-blur: blur(8px);
1785
- 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,);
1786
- }
1787
1720
  .filter {
1788
1721
  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,);
1789
1722
  }
@@ -1949,25 +1882,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1949
1882
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
1950
1883
  }
1951
1884
  }
1952
- .focus-within\\:border-ring {
1953
- &:focus-within {
1954
- border-color: var(--ring);
1955
- }
1956
- }
1957
- .focus-within\\:ring-\\[3px\\] {
1958
- &:focus-within {
1959
- --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
1960
- box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
1961
- }
1962
- }
1963
- .focus-within\\:ring-ring\\/30 {
1964
- &:focus-within {
1965
- --tw-ring-color: var(--ring);
1966
- @supports (color: color-mix(in lab, red, red)) {
1967
- --tw-ring-color: color-mix(in oklab, var(--ring) 30%, transparent);
1968
- }
1969
- }
1970
- }
1971
1885
  .hover\\:border-destructive\\/30 {
1972
1886
  &:hover {
1973
1887
  @media (hover: hover) {
@@ -2111,11 +2025,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
2111
2025
  pointer-events: none;
2112
2026
  }
2113
2027
  }
2114
- .disabled\\:cursor-not-allowed {
2115
- &:disabled {
2116
- cursor: not-allowed;
2117
- }
2118
- }
2119
2028
  .disabled\\:opacity-50 {
2120
2029
  &:disabled {
2121
2030
  opacity: 50%;
@@ -2126,11 +2035,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
2126
2035
  opacity: 60%;
2127
2036
  }
2128
2037
  }
2129
- .has-disabled\\:opacity-60 {
2130
- &:has(*:disabled) {
2131
- opacity: 60%;
2132
- }
2133
- }
2134
2038
  .aria-invalid\\:border-destructive\\/40 {
2135
2039
  &[aria-invalid="true"] {
2136
2040
  border-color: var(--destructive);
@@ -2537,32 +2441,6 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
2537
2441
  height: calc(var(--spacing) * 4.5);
2538
2442
  }
2539
2443
  }
2540
- .\\[\\&\\>svg\\]\\:pointer-events-none {
2541
- &>svg {
2542
- pointer-events: none;
2543
- }
2544
- }
2545
- .\\[\\&\\>svg\\]\\:-mx-0\\.5 {
2546
- &>svg {
2547
- margin-inline: calc(var(--spacing) * -0.5);
2548
- }
2549
- }
2550
- .\\[\\&\\>svg\\]\\:shrink-0 {
2551
- &>svg {
2552
- flex-shrink: 0;
2553
- }
2554
- }
2555
- .\\[\\&\\>svg\\:not\\(\\[class\\*\\=\\'opacity-\\'\\]\\)\\]\\:opacity-80 {
2556
- &>svg:not([class*='opacity-']) {
2557
- opacity: 80%;
2558
- }
2559
- }
2560
- .\\[\\&\\>svg\\:not\\(\\[class\\*\\=\\'size-\\'\\]\\)\\]\\:size-4 {
2561
- &>svg:not([class*='size-']) {
2562
- width: calc(var(--spacing) * 4);
2563
- height: calc(var(--spacing) * 4);
2564
- }
2565
- }
2566
2444
  .\\[\\[data-kbd-nav\\]_\\&\\]\\:focus-within\\:bg-accent {
2567
2445
  [data-kbd-nav] & {
2568
2446
  &:focus-within {
@@ -3124,11 +3002,10 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
3124
3002
 
3125
3003
  // src/browser/surface/constants.ts
3126
3004
  var SURFACE_HOST_CLASS = "uidex-surface-host";
3127
- var SURFACE_CONTAINER_CLASS = "uidex-container";
3128
3005
  var Z_BASE = 2147483630;
3129
3006
  var Z_OVERLAY = 2147483635;
3130
3007
  var Z_CHROME = 2147483645;
3131
- var SURFACE_IGNORE_SELECTOR = `.${SURFACE_HOST_CLASS},.${SURFACE_CONTAINER_CLASS}`;
3008
+ var SURFACE_IGNORE_SELECTOR = `.${SURFACE_HOST_CLASS}`;
3132
3009
  var UIDEX_ATTR_TO_KIND = [
3133
3010
  ["data-uidex", "element"],
3134
3011
  ["data-uidex-region", "region"],
@@ -3415,7 +3292,6 @@ function createInspector(options) {
3415
3292
  e.preventDefault();
3416
3293
  e.stopPropagation();
3417
3294
  const match = stack[layerIndex];
3418
- session.select(match.ref);
3419
3295
  onSelect?.(match, { x: e.clientX, y: e.clientY });
3420
3296
  };
3421
3297
  const onContextMenu = (e) => {
@@ -3464,8 +3340,6 @@ function createInspector(options) {
3464
3340
 
3465
3341
  // src/browser/surface/menu-bar.ts
3466
3342
  import {
3467
- ChevronLeft,
3468
- ChevronRight,
3469
3343
  Command,
3470
3344
  Highlighter,
3471
3345
  MapPin,
@@ -3621,49 +3495,12 @@ function createMenuBar(options) {
3621
3495
  },
3622
3496
  pinIcon
3623
3497
  );
3624
- const commitCycler = el("div", {
3625
- class: "relative z-1 inline-flex items-center gap-0.5",
3626
- attrs: { "data-uidex-menubar-commit-cycler": "" }
3627
- });
3628
- commitCycler.hidden = true;
3629
- const prevIcon = createLucideElement2(ChevronLeft);
3630
- prevIcon.setAttribute("class", "size-3");
3631
- prevIcon.setAttribute("aria-hidden", "true");
3632
- const prevBtn = el(
3633
- "button",
3634
- {
3635
- class: BUTTON_CLASS,
3636
- attrs: { type: "button", "aria-label": "Previous commit" },
3637
- style: { width: "18px", height: "18px" }
3638
- },
3639
- prevIcon
3640
- );
3641
- const commitLabel = el("span", {
3642
- class: "relative z-1 whitespace-nowrap px-1 text-[10px] font-mono text-muted-foreground",
3643
- attrs: { "data-uidex-menubar-commit-label": "" }
3644
- });
3645
- const nextIcon = createLucideElement2(ChevronRight);
3646
- nextIcon.setAttribute("class", "size-3");
3647
- nextIcon.setAttribute("aria-hidden", "true");
3648
- const nextBtn = el(
3649
- "button",
3650
- {
3651
- class: BUTTON_CLASS,
3652
- attrs: { type: "button", "aria-label": "Next commit" },
3653
- style: { width: "18px", height: "18px" }
3654
- },
3655
- nextIcon
3656
- );
3657
- commitCycler.appendChild(prevBtn);
3658
- commitCycler.appendChild(commitLabel);
3659
- commitCycler.appendChild(nextBtn);
3660
3498
  const pinWrapper = el("div", {
3661
3499
  class: "relative z-1 inline-flex items-center gap-0.5",
3662
3500
  attrs: { "data-uidex-menubar-pin-wrapper": "" }
3663
3501
  });
3664
3502
  pinWrapper.hidden = true;
3665
3503
  pinWrapper.appendChild(pinBtn);
3666
- pinWrapper.appendChild(commitCycler);
3667
3504
  root.appendChild(pinWrapper);
3668
3505
  const updatePinUI = () => {
3669
3506
  if (!activePinLayer) {
@@ -3671,16 +3508,7 @@ function createMenuBar(options) {
3671
3508
  return;
3672
3509
  }
3673
3510
  const pinsVisible = activePinLayer.visible;
3674
- const state = activePinLayer.filterState;
3675
- const hasCommits = state.commits.length > 0;
3676
3511
  pinWrapper.hidden = false;
3677
- commitCycler.hidden = !pinsVisible || !hasCommits;
3678
- if (state.commitIndex === -1 || !state.commits[state.commitIndex]) {
3679
- commitLabel.textContent = `all (${state.commits.length})`;
3680
- } else {
3681
- const sha = state.commits[state.commitIndex] ?? "";
3682
- commitLabel.textContent = sha.slice(0, 7);
3683
- }
3684
3512
  pinBtn.className = cn(BUTTON_CLASS, pinsVisible && BUTTON_ACTIVE_CLASS);
3685
3513
  };
3686
3514
  pinBtn.addEventListener("click", (e) => {
@@ -3689,14 +3517,6 @@ function createMenuBar(options) {
3689
3517
  activePinLayer.setVisible(!activePinLayer.visible);
3690
3518
  }
3691
3519
  });
3692
- prevBtn.addEventListener("click", (e) => {
3693
- e.stopPropagation();
3694
- activePinLayer?.prevCommit();
3695
- });
3696
- nextBtn.addEventListener("click", (e) => {
3697
- e.stopPropagation();
3698
- activePinLayer?.nextCommit();
3699
- });
3700
3520
  let unsubscribePinFilter = activePinLayer?.onFilterChange(() => updatePinUI());
3701
3521
  const presenceIcon = createLucideElement2(Users);
3702
3522
  presenceIcon.setAttribute("class", "size-3.5");
@@ -3790,7 +3610,7 @@ function createMenuBar(options) {
3790
3610
  container.appendChild(root);
3791
3611
  const syncButtonStates = () => {
3792
3612
  const state = session.getState();
3793
- const inspectActive = state.inspectorActive;
3613
+ const inspectActive = state.mode === "inspecting";
3794
3614
  inspectBtn.setAttribute(
3795
3615
  "data-uidex-menubar-inspect-active",
3796
3616
  inspectActive ? "true" : "false"
@@ -3909,6 +3729,49 @@ function createMenuBar(options) {
3909
3729
  };
3910
3730
  }
3911
3731
 
3732
+ // src/browser/internal/repositioner.ts
3733
+ function createRepositioner(onReflow) {
3734
+ let rafId = null;
3735
+ let attached = false;
3736
+ const schedule = () => {
3737
+ if (rafId !== null) return;
3738
+ rafId = typeof requestAnimationFrame === "function" ? requestAnimationFrame(() => {
3739
+ rafId = null;
3740
+ onReflow();
3741
+ }) : setTimeout(() => {
3742
+ rafId = null;
3743
+ onReflow();
3744
+ }, 0);
3745
+ };
3746
+ const cancel = () => {
3747
+ if (rafId === null) return;
3748
+ if (typeof cancelAnimationFrame === "function") cancelAnimationFrame(rafId);
3749
+ else clearTimeout(rafId);
3750
+ rafId = null;
3751
+ };
3752
+ const onScroll = () => schedule();
3753
+ const onResize = () => schedule();
3754
+ const attach = () => {
3755
+ if (attached) return;
3756
+ attached = true;
3757
+ window.addEventListener("resize", onResize);
3758
+ window.addEventListener("scroll", onScroll, {
3759
+ capture: true,
3760
+ passive: true
3761
+ });
3762
+ };
3763
+ const detach = () => {
3764
+ if (!attached) return;
3765
+ attached = false;
3766
+ window.removeEventListener("resize", onResize);
3767
+ window.removeEventListener("scroll", onScroll, {
3768
+ capture: true
3769
+ });
3770
+ cancel();
3771
+ };
3772
+ return { schedule, cancel, attach, detach };
3773
+ }
3774
+
3912
3775
  // src/browser/surface/overlay.ts
3913
3776
  var DEFAULT_COLOR = "#34d399";
3914
3777
  var DEFAULT_BORDER_WIDTH = 2;
@@ -3976,44 +3839,7 @@ function createOverlay(deps) {
3976
3839
  fillOpacity: DEFAULT_FILL_OPACITY,
3977
3840
  backdrop: false
3978
3841
  };
3979
- let rafId = null;
3980
- let attached = false;
3981
- const schedule = () => {
3982
- if (rafId !== null) return;
3983
- rafId = typeof requestAnimationFrame === "function" ? requestAnimationFrame(() => {
3984
- rafId = null;
3985
- updatePosition();
3986
- }) : setTimeout(() => {
3987
- rafId = null;
3988
- updatePosition();
3989
- }, 0);
3990
- };
3991
- const cancelSchedule = () => {
3992
- if (rafId === null) return;
3993
- if (typeof cancelAnimationFrame === "function") cancelAnimationFrame(rafId);
3994
- else clearTimeout(rafId);
3995
- rafId = null;
3996
- };
3997
- const onScroll = () => schedule();
3998
- const onResize = () => schedule();
3999
- const attach = () => {
4000
- if (attached) return;
4001
- attached = true;
4002
- window.addEventListener("resize", onResize);
4003
- window.addEventListener("scroll", onScroll, {
4004
- capture: true,
4005
- passive: true
4006
- });
4007
- };
4008
- const detach = () => {
4009
- if (!attached) return;
4010
- attached = false;
4011
- window.removeEventListener("resize", onResize);
4012
- window.removeEventListener("scroll", onScroll, {
4013
- capture: true
4014
- });
4015
- cancelSchedule();
4016
- };
3842
+ const repositioner = createRepositioner(() => updatePosition());
4017
3843
  function updatePosition() {
4018
3844
  if (!target) return;
4019
3845
  const rect = target.getBoundingClientRect();
@@ -4077,16 +3903,16 @@ function createOverlay(deps) {
4077
3903
  box.offsetHeight;
4078
3904
  }
4079
3905
  box.style.opacity = "1";
4080
- attach();
3906
+ repositioner.attach();
4081
3907
  },
4082
3908
  hide() {
4083
3909
  target = null;
4084
3910
  box.style.opacity = "0";
4085
3911
  backdrop.style.opacity = "0";
4086
- detach();
3912
+ repositioner.detach();
4087
3913
  },
4088
3914
  destroy() {
4089
- detach();
3915
+ repositioner.detach();
4090
3916
  box.remove();
4091
3917
  backdrop.remove();
4092
3918
  target = null;
@@ -4203,8 +4029,7 @@ function createSurfaceShell(options) {
4203
4029
  const overlay = createOverlay({ container: host.shadowRoot });
4204
4030
  cleanup.add(overlay);
4205
4031
  const tooltip = createCursorTooltip({
4206
- container: host.chromeEl,
4207
- session: options.session
4032
+ container: host.chromeEl
4208
4033
  });
4209
4034
  cleanup.add(tooltip);
4210
4035
  const afterHover = options.inspector?.onAfterHover;