@astryxdesign/core 0.7.0 → 0.7.1-canary.0365e23

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 (80) hide show
  1. package/dist/BottomSheet/BottomSheet.d.ts +1 -1
  2. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  3. package/dist/BottomSheet/BottomSheet.js +12 -2
  4. package/dist/CodeBlock/CodeBlock.d.ts +10 -1
  5. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  6. package/dist/CodeBlock/CodeBlock.js +158 -38
  7. package/dist/CodeBlock/tokenizer.d.ts +39 -0
  8. package/dist/CodeBlock/tokenizer.d.ts.map +1 -1
  9. package/dist/CodeBlock/tokenizer.js +108 -0
  10. package/dist/ContextMenu/ContextMenu.d.ts +1 -1
  11. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  12. package/dist/ContextMenu/ContextMenu.js +22 -8
  13. package/dist/Dialog/Dialog.d.ts.map +1 -1
  14. package/dist/Dialog/Dialog.js +3 -26
  15. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  16. package/dist/DropdownMenu/DropdownMenu.js +10 -3
  17. package/dist/Markdown/Markdown.d.ts.map +1 -1
  18. package/dist/Markdown/Markdown.js +19 -3
  19. package/dist/Typeahead/BaseTypeahead.d.ts +1 -1
  20. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  21. package/dist/Typeahead/BaseTypeahead.js +12 -3
  22. package/dist/astryx.css +13 -0
  23. package/dist/hooks/useIsomorphicLayoutEffect.d.ts +2 -2
  24. package/dist/hooks/useIsomorphicLayoutEffect.d.ts.map +1 -1
  25. package/dist/theme/syntax/SyntaxTheme.d.ts.map +1 -1
  26. package/dist/theme/syntax/SyntaxTheme.js +43 -2
  27. package/dist/theme/syntax/defineSyntaxTheme.d.ts +18 -5
  28. package/dist/theme/syntax/defineSyntaxTheme.d.ts.map +1 -1
  29. package/dist/theme/syntax/defineSyntaxTheme.js +38 -9
  30. package/dist/theme/syntax/index.d.ts +1 -1
  31. package/dist/theme/syntax/index.d.ts.map +1 -1
  32. package/dist/theme/syntax/tokens.d.ts +12 -2
  33. package/dist/theme/syntax/tokens.d.ts.map +1 -1
  34. package/dist/theme/syntax/tokens.js +25 -4
  35. package/dist/utils/focusReturn.d.ts +12 -8
  36. package/dist/utils/focusReturn.d.ts.map +1 -1
  37. package/dist/utils/focusReturn.js +44 -3
  38. package/package.json +4 -4
  39. package/src/BottomSheet/BottomSheet.test.tsx +114 -0
  40. package/src/BottomSheet/BottomSheet.tsx +12 -2
  41. package/src/BottomSheet/__tests__/BottomSheetFocusReturn.a11y.browser.spec.ts +96 -0
  42. package/src/Chat/__tests__/ChatLayoutScrollButtonSurface.a11y.chromium.spec.ts +5 -6
  43. package/src/CodeBlock/CodeBlock.doc.mjs +7 -0
  44. package/src/CodeBlock/CodeBlock.spec.md +55 -45
  45. package/src/CodeBlock/CodeBlock.test.tsx +89 -9
  46. package/src/CodeBlock/CodeBlock.tsx +205 -25
  47. package/src/CodeBlock/__tests__/CodeBlockOverflowStop.a11y.chromium.spec.ts +125 -0
  48. package/src/CodeBlock/__tests__/DiffRowPaint.a11y.chromium.spec.ts +93 -0
  49. package/src/CodeBlock/tokenizer.test.ts +112 -0
  50. package/src/CodeBlock/tokenizer.ts +106 -0
  51. package/src/ContextMenu/ContextMenu.spec.md +1 -1
  52. package/src/ContextMenu/ContextMenu.test.tsx +36 -3
  53. package/src/ContextMenu/ContextMenu.tsx +27 -11
  54. package/src/ContextMenu/__tests__/ContextMenuCursorAnchor.a11y.browser.spec.ts +153 -0
  55. package/src/Dialog/Dialog.tsx +2 -30
  56. package/src/Dialog/__tests__/Dialog.a11y.chromium.spec.ts +21 -14
  57. package/src/DropdownMenu/DropdownMenu.test.tsx +97 -1
  58. package/src/DropdownMenu/DropdownMenu.tsx +10 -3
  59. package/src/DropdownMenu/__tests__/DropdownMenuFocusReturn.a11y.browser.spec.ts +73 -0
  60. package/src/FieldStatus/__tests__/StatusMessage.a11y.chromium.spec.ts +21 -14
  61. package/src/Markdown/Markdown.spec.md +37 -23
  62. package/src/Markdown/Markdown.test.tsx +38 -0
  63. package/src/Markdown/Markdown.tsx +20 -2
  64. package/src/Markdown/plugins/semanticFence.test.tsx +3 -2
  65. package/src/NumberInput/__tests__/NumberInput.a11y.chromium.spec.ts +22 -15
  66. package/src/PowerSearch/PowerSearch.test.tsx +45 -0
  67. package/src/Switch/__tests__/Switch.a11y.chromium.spec.ts +25 -18
  68. package/src/TabList/__tests__/Tabs.a11y.chromium.spec.ts +19 -12
  69. package/src/TextInput/__tests__/TextInput.a11y.chromium.spec.ts +21 -14
  70. package/src/ToggleButton/__tests__/ToggleButton.a11y.chromium.spec.ts +18 -11
  71. package/src/Typeahead/BaseTypeahead.test.tsx +99 -1
  72. package/src/Typeahead/BaseTypeahead.tsx +17 -3
  73. package/src/theme/syntax/SyntaxTheme.tsx +46 -5
  74. package/src/theme/syntax/defineSyntaxTheme.diff.test.ts +91 -0
  75. package/src/theme/syntax/defineSyntaxTheme.ts +75 -15
  76. package/src/theme/syntax/index.ts +5 -1
  77. package/src/theme/syntax/tokens.ts +32 -2
  78. package/src/theme/syntax/useSyntaxTheme.diff.test.tsx +40 -0
  79. package/src/utils/focusReturn.test.ts +79 -2
  80. package/src/utils/focusReturn.ts +48 -3
@@ -9,7 +9,7 @@
9
9
  * @position Core implementation; consumed by index.ts
10
10
  *
11
11
  * Right-click context menu positioned at the cursor. The cursor point is
12
- * captured as an offset *inside the trigger* and materialized as a zero-size
12
+ * captured as an offset *inside the trigger* and materialized as a 1px
13
13
  * anchor element, so the menu is positioned relative to the trigger's context
14
14
  * (via CSS anchor positioning) rather than the viewport. It therefore follows
15
15
  * the content on scroll and auto-flips at viewport edges, while still appearing
@@ -134,6 +134,17 @@ const styles = {
134
134
  }
135
135
  };
136
136
 
137
+ /**
138
+ * Keeps the 1px cursor anchor inside the trigger along one axis. A point in
139
+ * the trigger's last pixel (Shift+F10 opens on its bottom edge) steps back by
140
+ * that pixel: past the edge the anchor would add scrollable overflow, and a
141
+ * scroller whose edge meets the trigger's would clip it and hide the menu.
142
+ * Any other point, inside the trigger or not, stays where it is.
143
+ */
144
+ function keepAnchorInside(offset, size) {
145
+ return offset > size - 1 && offset <= size ? Math.max(size - 1, 0) : offset;
146
+ }
147
+
137
148
  // =============================================================================
138
149
  // Types
139
150
  // =============================================================================
@@ -203,7 +214,7 @@ export function ContextMenu({
203
214
  const menuContent = menuContentProp;
204
215
  const menuId = useId();
205
216
  // Cursor point in the trigger's local coordinate space (offset from the
206
- // trigger's top-left, in-flow). Stored here and written to the zero-size
217
+ // trigger's top-left, in-flow). Stored here and written to the cursor
207
218
  // anchor element so the menu is positioned relative to the trigger context
208
219
  // — it scrolls with the content instead of sitting at a fixed viewport point.
209
220
  const positionRef = useRef({
@@ -380,20 +391,23 @@ export function ContextMenu({
380
391
  listNavKeyDown(e);
381
392
  }, [listNavKeyDown, closeMenu, typeahead, ownsEvent]);
382
393
 
383
- // Place the zero-size cursor anchor at a point in the trigger's local
394
+ // Place the 1px cursor anchor at a point in the trigger's local
384
395
  // coordinate space and open the menu. Positioning the anchor inside the
385
396
  // trigger (rather than storing viewport coordinates on the menu itself) is
386
397
  // what makes the menu context-relative: it scrolls with the content and the
387
398
  // browser auto-flips it against the viewport edges via CSS anchor positioning.
388
399
  const openAtLocalPoint = useCallback((localX, localY, focusEl) => {
400
+ const rect = triggerRef.current?.getBoundingClientRect();
401
+ const x = rect ? keepAnchorInside(localX, rect.width) : localX;
402
+ const y = rect ? keepAnchorInside(localY, rect.height) : localY;
389
403
  positionRef.current = {
390
- x: localX,
391
- y: localY
404
+ x,
405
+ y
392
406
  };
393
407
  const anchorEl = cursorAnchorRef.current;
394
408
  if (anchorEl) {
395
- anchorEl.style.left = `${localX}px`;
396
- anchorEl.style.top = `${localY}px`;
409
+ anchorEl.style.left = `${x}px`;
410
+ anchorEl.style.top = `${y}px`;
397
411
  }
398
412
  // Remember the element focused before opening so we can restore it on
399
413
  // close (Escape or outside-click), instead of dropping focus to <body>.
@@ -534,7 +548,7 @@ export function ContextMenu({
534
548
  ref: useMergedRefs(cursorAnchorRef, layer.ref),
535
549
  "aria-hidden": "true",
536
550
  ...mergeProps({
537
- className: "x10l6tqk xnalus7 xqtp20y x47corl"
551
+ className: "x10l6tqk x1i1rx1s xjm9jq1 x47corl"
538
552
  }, {
539
553
  style: {
540
554
  left: `${positionRef.current.x}px`,
@@ -1 +1 @@
1
- {"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../../src/Dialog/Dialog.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AA2B5C,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAKhD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,SAAS,CAAC;AAqD9C;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAEzD,4EAA4E;AAC5E,UAAU,mBAAmB;IAC3B,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAe,SAAQ,mBAAmB;IACzD,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAuBD,2FAA2F;AAC3F,eAAO,MAAM,uCAAuC;;;;;;;;;;;CAW1C,CAAC;AAoJX;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,cAAc;;;;;EAUpE;AAED,MAAM,WAAW,WAAY,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IAC/D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAEhB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;;;;OAOG;IACH,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IAE3C;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAExB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAE5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;IAEpC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;IAExB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;IAExB;;;;OAIG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IAEtB;;;OAGG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,MAAM,CAAC,EACrB,MAAM,EACN,QAAgB,EAChB,YAAY,EACZ,KAAW,EACX,SAAmB,EACnB,QAAQ,EACR,OAAoB,EACpB,OAAgB,EAChB,OAAO,EACP,QAAQ,EACR,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,KAAK,EACT,EAAE,WAAW,sCAiUb;yBAjVe,MAAM"}
1
+ {"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../../src/Dialog/Dialog.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AA2B5C,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAKhD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,SAAS,CAAC;AAyB9C;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAEzD,4EAA4E;AAC5E,UAAU,mBAAmB;IAC3B,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAe,SAAQ,mBAAmB;IACzD,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAuBD,2FAA2F;AAC3F,eAAO,MAAM,uCAAuC;;;;;;;;;;;CAW1C,CAAC;AAoJX;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,cAAc;;;;;EAUpE;AAED,MAAM,WAAW,WAAY,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IAC/D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAEhB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;;;;OAOG;IACH,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IAE3C;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAExB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAE5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;IAEpC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;IAExB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;IAExB;;;;OAIG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IAEtB;;;OAGG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,MAAM,CAAC,EACrB,MAAM,EACN,QAAgB,EAChB,YAAY,EACZ,KAAW,EACX,SAAmB,EACnB,QAAQ,EACR,OAAoB,EACpB,OAAgB,EAChB,OAAO,EACP,QAAQ,EACR,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,KAAK,EACT,EAAE,WAAW,sCAiUb;yBAjVe,MAAM"}
@@ -45,38 +45,15 @@ import { devWarn } from "../utils/devWarning.js";
45
45
  import { DialogContext } from "./DialogContext.js";
46
46
  import { themeProps } from "../utils/themeProps.js";
47
47
  import { focusOutlineProps } from "../utils/focusOutline.stylex.js";
48
- import { getInteractionModality, useInteractionModalityTracking } from "../utils/interactionModality.js";
48
+ import { useInteractionModalityTracking } from "../utils/interactionModality.js";
49
+ import { focusForLastInput } from "../utils/focusReturn.js";
49
50
  import { useMergedRefs } from "../hooks/useMergedRefs.js";
50
- /**
51
- * Move focus programmatically so its ring follows the last input. Dialog does
52
- * not render the element that opened it or the consumer's autofocus target, so
53
- * the browser's focus option is the one way to reach them.
54
- */
55
- import { jsx as _jsx } from "react/jsx-runtime";
56
- function focusForLastInput(element) {
57
- // A text-entry field paints its own focus treatment to show where typing
58
- // goes, and an extra blur there can run validation or mark it touched.
59
- const isTextEntry = element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement || element.isContentEditable;
60
- if (isTextEntry || getInteractionModality() !== 'pointer') {
61
- element.focus();
62
- return;
63
- }
64
- // Focusing the element that already has focus does nothing, so a ring the
65
- // browser already drew would stay. WebKit draws one when showModal() or its
66
- // native close moves focus itself, so clear that focus first.
67
- if (element.matches(':focus-visible')) {
68
- element.blur();
69
- }
70
- element.focus({
71
- focusVisible: false
72
- });
73
- }
74
-
75
51
  /**
76
52
  * Calculate a directional translate offset for dialog entry animation.
77
53
  * Returns a normalized vector from the trigger element toward the viewport
78
54
  * center, scaled to the given distance.
79
55
  */
56
+ import { jsx as _jsx } from "react/jsx-runtime";
80
57
  function getDialogDirection(triggerEl, distance = 16) {
81
58
  const rect = triggerEl.getBoundingClientRect();
82
59
  const dx = rect.left + rect.width / 2 - window.innerWidth / 2;
@@ -1 +1 @@
1
- {"version":3,"file":"DropdownMenu.d.ts","sourceRoot":"","sources":["../../src/DropdownMenu/DropdownMenu.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DropdownMenu.d.ts","sourceRoot":"","sources":["../../src/DropdownMenu/DropdownMenu.tsx"],"names":[],"mappings":"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"}
@@ -48,6 +48,7 @@ import { useListFocus } from "../hooks/useListFocus.js";
48
48
  import { useMenuPress } from "../hooks/useMenuPress.js";
49
49
  import { useTypeahead } from "../hooks/useTypeahead.js";
50
50
  import { useFocusReturnVisibility } from "../hooks/useFocusReturnVisibility.js";
51
+ import { focusForLastInput } from "../utils/focusReturn.js";
51
52
  import { useMenuOverflow } from "./useMenuOverflow.js";
52
53
  import { MenuRegionsContext } from "./menuRegionsContext.js";
53
54
  import { getFocusableElements } from "../hooks/useFocusTrap.js";
@@ -654,7 +655,12 @@ function DropdownMenuPopover({
654
655
  return;
655
656
  }
656
657
  prepareFocusReturn();
657
- trigger.focus({
658
+ // After pointer input the trigger takes focus without the focus-visible
659
+ // ring (`component:DropdownMenu/DEC-1`). The style the helper above adds
660
+ // reaches only the design system's own Button; the browser's focus option
661
+ // also reaches a control the caller renders, which the browser would
662
+ // otherwise ring (Chromium after a mouse pick, WebKit after a touch).
663
+ focusForLastInput(trigger, {
658
664
  preventScroll: true
659
665
  });
660
666
  }, [isControlled, onOpenChange, prepareFocusReturn]);
@@ -1072,8 +1078,9 @@ function DropdownMenuPopover({
1072
1078
  onPointerDown: menuPress.triggerProps.onPointerDown,
1073
1079
  onContextMenu: menuPress.triggerProps.onContextMenu,
1074
1080
  onKeyDown: handleButtonKeyDown,
1075
- // The popover's focus-return hook is a separate change; until it lands
1076
- // the control's focus needs no bookkeeping here.
1081
+ // The caller's control paints its own ring, and the menu's focus return
1082
+ // keeps the browser from drawing one after pointer input (see
1083
+ // handleLayerHide), so its focus needs no bookkeeping here.
1077
1084
  onFocus: () => {},
1078
1085
  'aria-haspopup': 'menu',
1079
1086
  'aria-expanded': isOpen,
@@ -1 +1 @@
1
- {"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../src/Markdown/Markdown.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../src/Markdown/Markdown.tsx"],"names":[],"mappings":"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"}
@@ -14,6 +14,7 @@ import * as stylex from '@stylexjs/stylex';
14
14
  import "../theme/tokens.stylex.js";
15
15
  import { colorVars, spacingVars, radiusVars, typeScaleVars, typographyVars, fontWeightVars, borderVars, durationVars, easeVars } from "../theme/tokens.stylex.js";
16
16
  import { CodeBlock, Code } from "../CodeBlock/index.js";
17
+ import { parseFenceLanguage } from "../CodeBlock/tokenizer.js";
17
18
  import { CheckboxList } from "../CheckboxList/CheckboxList.js";
18
19
  import { CheckboxListItem } from "../CheckboxList/CheckboxListItem.js";
19
20
  import { Blockquote } from "../Blockquote/Blockquote.js";
@@ -1009,15 +1010,29 @@ listDepth = 0) {
1009
1010
  {
1010
1011
  // Track codeblock content in cursor for accurate character counting
1011
1012
  cursor.offset += node.value.length;
1012
- const language = getMarkdownAstLegacyCodeLanguage(node) ?? 'plaintext';
1013
+ // `diff-<lang>` fences are the diff layer over <lang>; `diff` is the
1014
+ // layer over plaintext. The legacy language is the info
1015
+ // string's leading word characters, which stops at the hyphen, so the
1016
+ // diff mapping reads the whole first word and then applies the same
1017
+ // word rule to the language it names.
1018
+ const legacyLanguage = getMarkdownAstLegacyCodeLanguage(node) ?? 'plaintext';
1019
+ const fence = parseFenceLanguage(node.lang ?? legacyLanguage);
1020
+ const isDiff = fence.isDiff;
1021
+ // The language under the diff layer; the default CodeBlock renders it.
1022
+ const diffLanguage = isDiff ? fence.language.match(/^\w*/)?.[0] || 'plaintext' : undefined;
1023
+ const language = diffLanguage ?? legacyLanguage;
1013
1024
  // A semantic-fence proposal claims its fence before the host's code
1014
1025
  // renderer (spec:AST-036 FR17). The host renderer, or the default Code
1015
1026
  // block without one, draws every unclaimed fence and is the fallback
1016
1027
  // when the claiming renderer is absent, declines, throws, or suspends.
1017
1028
  const CodeBlockComp = components?.code;
1018
1029
  const fallback = CodeBlockComp ? /*#__PURE__*/_jsx(CodeBlockComp, {
1019
- code: node.value,
1020
- language: language,
1030
+ code: node.value
1031
+ // A supplied renderer's contract is unchanged: it keeps receiving
1032
+ // the leading word characters (`diff` for a `diff-tsx` fence, as
1033
+ // today) and nothing new; only the default path maps the layer.
1034
+ ,
1035
+ language: legacyLanguage,
1021
1036
  ...lineProp
1022
1037
  }, index) : /*#__PURE__*/_jsx("div", {
1023
1038
  ...mergeProps(themeProps('markdown-codeblock', {
@@ -1027,6 +1042,7 @@ listDepth = 0) {
1027
1042
  children: /*#__PURE__*/_jsx(CodeBlock, {
1028
1043
  code: node.value,
1029
1044
  language: language,
1045
+ isDiff: isDiff,
1030
1046
  isCollapsible: true,
1031
1047
  xstyle: [contentWidthValue != null ? dynamicStyles.blockWidth(contentWidthValue) : undefined, blockAlignStyle]
1032
1048
  })
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @file BaseTypeahead.tsx
3
3
  * @input Uses React, StyleX, usePopover, TypeaheadItem
4
- * @output Exports BaseTypeahead with focused-input menu reactivation
4
+ * @output Exports BaseTypeahead; focus bootstraps a replaced search source
5
5
  * @position Core implementation; used by Typeahead and Tokenizer
6
6
  *
7
7
  * Pure combobox engine: input, search, keyboard navigation, dropdown.
@@ -1 +1 @@
1
- {"version":3,"file":"BaseTypeahead.d.ts","sourceRoot":"","sources":["../../src/Typeahead/BaseTypeahead.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,EAMZ,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,kBAAkB,CAAC;AA2BnD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,cAAc,EAAE,YAAY,EAAC,MAAM,SAAS,CAAC;AAW1D,MAAM,WAAW,kBAAkB,CAAC,CAAC,SAAS,cAAc,CAAE,SAAQ,IAAI,CACxE,SAAS,CAAC,WAAW,CAAC,EACtB,UAAU,CACX;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAClC;;OAEG;IACH,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAE9B;;OAEG;IACH,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IAEhB;;OAEG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC;IAEnC;;OAEG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,SAAS,CAAC;IAEpC;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;;;;;OAUG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;;;;;;;;;;OAaG;IACH,eAAe,CAAC,EAAE,SAAS,CAAC;IAE5B;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;;;;;;OASG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAExC;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAEzC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;IAEtD;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,WAAW,CAAC,EAAE,YAAY,CAAC;IAE3B;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAE1C;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IAE/D;;;;OAIG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;CAC3B;AAoKD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,aAAa,EAs0BrB,CAAC,CAAC,SAAS,cAAc,EAC5B,KAAK,EAAE,kBAAkB,CAAC,CAAC,CAAC,KACzB,KAAK,CAAC,YAAY,CAAC"}
1
+ {"version":3,"file":"BaseTypeahead.d.ts","sourceRoot":"","sources":["../../src/Typeahead/BaseTypeahead.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,EAMZ,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,kBAAkB,CAAC;AA2BnD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,cAAc,EAAE,YAAY,EAAC,MAAM,SAAS,CAAC;AAW1D,MAAM,WAAW,kBAAkB,CAAC,CAAC,SAAS,cAAc,CAAE,SAAQ,IAAI,CACxE,SAAS,CAAC,WAAW,CAAC,EACtB,UAAU,CACX;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAClC;;OAEG;IACH,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAE9B;;OAEG;IACH,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IAEhB;;OAEG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC;IAEnC;;OAEG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,SAAS,CAAC;IAEpC;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;;;;;OAUG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;;;;;;;;;;OAaG;IACH,eAAe,CAAC,EAAE,SAAS,CAAC;IAE5B;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;;;;;;OASG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAExC;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAEzC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;IAEtD;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,WAAW,CAAC,EAAE,YAAY,CAAC;IAE3B;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAE1C;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IAE/D;;;;OAIG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;CAC3B;AAoKD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,aAAa,EAo1BrB,CAAC,CAAC,SAAS,cAAc,EAC5B,KAAK,EAAE,kBAAkB,CAAC,CAAC,CAAC,KACzB,KAAK,CAAC,YAAY,CAAC"}
@@ -5,7 +5,7 @@
5
5
  /**
6
6
  * @file BaseTypeahead.tsx
7
7
  * @input Uses React, StyleX, usePopover, TypeaheadItem
8
- * @output Exports BaseTypeahead with focused-input menu reactivation
8
+ * @output Exports BaseTypeahead; focus bootstraps a replaced search source
9
9
  * @position Core implementation; used by Typeahead and Tokenizer
10
10
  *
11
11
  * Pure combobox engine: input, search, keyboard navigation, dropdown.
@@ -326,6 +326,10 @@ export const BaseTypeahead = function BaseTypeahead({
326
326
  // in the closure are stale (a selection cleared them) and shouldn't
327
327
  // be re-shown.
328
328
  const resultsGenRef = useRef(0);
329
+ // The generation at which the current searchSource took over. Results
330
+ // populated before it (resultsGenRef below this) came from a replaced
331
+ // source: they can never be re-shown, so focus bootstraps the new source.
332
+ const sourceGenRef = useRef(0);
329
333
 
330
334
  // Results still arriving from a replaced source must not land in the new
331
335
  // one's menu.
@@ -333,7 +337,7 @@ export const BaseTypeahead = function BaseTypeahead({
333
337
  if (prevSearchSourceRef.current !== searchSource) {
334
338
  prevSearchSourceRef.current.cancel?.();
335
339
  prevSearchSourceRef.current = searchSource;
336
- searchGenRef.current++;
340
+ sourceGenRef.current = ++searchGenRef.current;
337
341
  }
338
342
 
339
343
  // Layer for dropdown
@@ -551,11 +555,16 @@ export const BaseTypeahead = function BaseTypeahead({
551
555
  // Shared by handleFocus and handleClick: bootstrap entries if none are
552
556
  // loaded yet, or re-show cached results that haven't been invalidated by
553
557
  // a selection since (comparing the two generation refs catches that).
558
+ // Results cached from a replaced search source count as none, so focusing
559
+ // an empty field bootstraps the new source instead of opening nothing.
560
+ // Results a selection invalidated still keep the menu closed when the
561
+ // selection returns focus to the input.
554
562
  const openIfEligible = useCallback(() => {
555
563
  if (isDisabled) {
556
564
  return;
557
565
  }
558
- if (hasEntriesOnFocus && results.length === 0 && query.length === 0) {
566
+ const hasResultsFromCurrentSource = results.length > 0 && resultsGenRef.current >= sourceGenRef.current;
567
+ if (hasEntriesOnFocus && !hasResultsFromCurrentSource && query.length === 0) {
559
568
  void performBootstrap();
560
569
  } else if (results.length > 0 && (query.length > 0 || hasEntriesOnFocus) && resultsGenRef.current === searchGenRef.current) {
561
570
  showLayer();
package/dist/astryx.css CHANGED
@@ -772,7 +772,10 @@
772
772
  .xprdx6m:not(#\#):not(#\#):not(#\#){background-color:var(--color-skeleton)}
773
773
  .xu13z74:not(#\#):not(#\#):not(#\#){background-color:var(--color-success-muted)}
774
774
  .xdsz4j9:not(#\#):not(#\#):not(#\#){background-color:var(--color-success)}
775
+ .xjqijk9:not(#\#):not(#\#):not(#\#){background-color:var(--color-syntax-added)}
775
776
  .xzyc27v:not(#\#):not(#\#):not(#\#){background-color:var(--color-syntax-background)}
777
+ .x11ds9ch:not(#\#):not(#\#):not(#\#){background-color:var(--color-syntax-diff-header)}
778
+ .xv48ua2:not(#\#):not(#\#):not(#\#){background-color:var(--color-syntax-removed)}
776
779
  .x16fr6go:not(#\#):not(#\#):not(#\#){background-color:var(--color-text-disabled)}
777
780
  .x19aspcf:not(#\#):not(#\#):not(#\#){background-color:var(--color-text-primary)}
778
781
  .xdomwnj:not(#\#):not(#\#):not(#\#){background-color:var(--color-text-secondary)}
@@ -877,7 +880,10 @@
877
880
  .xri61p4:not(#\#):not(#\#):not(#\#){color:var(--color-on-success)}
878
881
  .xrebv38:not(#\#):not(#\#):not(#\#){color:var(--color-on-warning)}
879
882
  .xtjic6:not(#\#):not(#\#):not(#\#){color:var(--color-success)}
883
+ .x1wxerb0:not(#\#):not(#\#):not(#\#){color:var(--color-syntax-added-marker)}
880
884
  .x1mjzq1q:not(#\#):not(#\#):not(#\#){color:var(--color-syntax-comment)}
885
+ .xt5rlkq:not(#\#):not(#\#):not(#\#){color:var(--color-syntax-punctuation)}
886
+ .x103bwea:not(#\#):not(#\#):not(#\#){color:var(--color-syntax-removed-marker)}
881
887
  .xdfisg:not(#\#):not(#\#):not(#\#){color:var(--color-syntax-variable)}
882
888
  .xjse4m1:not(#\#):not(#\#):not(#\#){color:var(--color-text-accent)}
883
889
  .x1vvqiwl:not(#\#):not(#\#):not(#\#){color:var(--color-text-blue)}
@@ -895,6 +901,7 @@
895
901
  .xdhq94a:not(#\#):not(#\#):not(#\#){color:var(--color-text-yellow)}
896
902
  .xs3pv69:not(#\#):not(#\#):not(#\#){color:var(--color-warning)}
897
903
  .x14rh7hd:not(#\#):not(#\#):not(#\#){color:var(--x-color)}
904
+ .x1o1pmfc:not(#\#):not(#\#):not(#\#){column-gap:0}
898
905
  .xf5zn4v:not(#\#):not(#\#):not(#\#){column-gap:calc(var(--spacing-3) + var(--border-width) + var(--spacing-4))}
899
906
  .x1kihgfc:not(#\#):not(#\#):not(#\#){column-gap:var(--spacing-0-5)}
900
907
  .x1o57wo1:not(#\#):not(#\#):not(#\#){column-gap:var(--spacing-0)}
@@ -1023,6 +1030,7 @@
1023
1030
  .xhij9v2:not(#\#):not(#\#):not(#\#){grid-auto-rows:var(--x-gridAutoRows)}
1024
1031
  .xcrlgei:not(#\#):not(#\#):not(#\#){grid-column-start:1}
1025
1032
  .x1agbcgv:not(#\#):not(#\#):not(#\#){grid-row-start:1}
1033
+ .xrnahuw:not(#\#):not(#\#):not(#\#){grid-template-columns:1ch 1fr}
1026
1034
  .x134kloy:not(#\#):not(#\#):not(#\#){grid-template-columns:1fr auto 1fr}
1027
1035
  .x52fmzj:not(#\#):not(#\#):not(#\#){grid-template-columns:1fr auto}
1028
1036
  .x1y6fwsi:not(#\#):not(#\#):not(#\#){grid-template-columns:1fr}
@@ -1033,6 +1041,7 @@
1033
1041
  .x1mzazjb:not(#\#):not(#\#):not(#\#){grid-template-columns:repeat(7,1fr)}
1034
1042
  .x189bvgu:not(#\#):not(#\#):not(#\#){grid-template-columns:repeat(auto-fill,minmax(280px,1fr))}
1035
1043
  .x1xx4m37:not(#\#):not(#\#):not(#\#){grid-template-columns:var(--_codeblock-gutter-width) 1fr}
1044
+ .x1v9b7p9:not(#\#):not(#\#):not(#\#){grid-template-columns:var(--_codeblock-gutter-width) auto 1fr}
1036
1045
  .xqketvx:not(#\#):not(#\#):not(#\#){grid-template-columns:var(--x-gridTemplateColumns)}
1037
1046
  .xihq33y:not(#\#):not(#\#):not(#\#){grid-template-rows:0fr}
1038
1047
  .x1tu4anv:not(#\#):not(#\#):not(#\#){grid-template-rows:1fr}
@@ -1121,6 +1130,7 @@
1121
1130
  .xs69w1r:not(#\#):not(#\#):not(#\#){margin-inline-start:calc((40px - min(var(--spacing-6),40px)) / 2 - var(--spacing-3))}
1122
1131
  .x1idpjx9:not(#\#):not(#\#):not(#\#){margin-inline-start:calc((40px - min(var(--spacing-6),40px)) / 2 - var(--spacing-4))}
1123
1132
  .x1xrm450:not(#\#):not(#\#):not(#\#){margin-inline-start:calc(var(--spacing-2) - var(--spacing-1) + 1px)}
1133
+ .x6w1cxl:not(#\#):not(#\#):not(#\#){margin-inline-start:calc(var(--spacing-3) + var(--border-width) + var(--spacing-4))}
1124
1134
  .x13hpdyo:not(#\#):not(#\#):not(#\#){margin-inline-start:var(--_avatar-group-overlap)}
1125
1135
  .x12vn87o:not(#\#):not(#\#):not(#\#){margin-inline-start:var(--_tree-indent,0px)}
1126
1136
  .xladpz9:not(#\#):not(#\#):not(#\#){margin-inline-start:var(--spacing-0-5)}
@@ -1844,6 +1854,7 @@
1844
1854
  .x15x72sd:not(#\#):not(#\#):not(#\#):not(#\#){min-width:auto}
1845
1855
  .x8wyhu6:not(#\#):not(#\#):not(#\#):not(#\#){min-width:calc(anchor-size(width) + 16px)}
1846
1856
  .x1pshirs:not(#\#):not(#\#):not(#\#):not(#\#){min-width:fit-content}
1857
+ .xk8lq53:not(#\#):not(#\#):not(#\#):not(#\#){min-width:max-content}
1847
1858
  .xg3bzn3:not(#\#):not(#\#):not(#\#):not(#\#){min-width:min(400px,calc(100vw - var(--spacing-4) - var(--spacing-4) - var(--astryx-layer-inset-inline-start, 0px) - var(--astryx-layer-inset-inline-end, 0px)));min-width:min(400px,calc(100vi - calc(max(var(--spacing-4), env(safe-area-inset-left, 0px)) + var(--astryx-layer-inset-inline-start, 0px)) - calc(max(var(--spacing-4), env(safe-area-inset-right, 0px)) + var(--astryx-layer-inset-inline-end, 0px))))}
1848
1859
  .x17ydmr0:not(#\#):not(#\#):not(#\#):not(#\#){min-width:var(--size-element-md)}
1849
1860
  .x1nkkqge:not(#\#):not(#\#):not(#\#):not(#\#){min-width:var(--size-element-sm)}
@@ -2082,7 +2093,9 @@
2082
2093
  .xnnzo76:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::after{border-inline-start-color:var(--color-border)}
2083
2094
  .xvsnedh:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::after{border-inline-start-style:solid}
2084
2095
  .x1p96cux:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::after{border-inline-start-width:var(--border-width)}
2096
+ .x147exv5:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::before{color:var(--color-syntax-added-marker)}
2085
2097
  .xtkarl4:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::before{color:var(--color-syntax-punctuation)}
2098
+ .x16hy5kr:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::before{color:var(--color-syntax-removed-marker)}
2086
2099
  .xnf3u0:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::placeholder{color:var(--color-text-disabled)}
2087
2100
  .xeyghm5:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::placeholder{color:var(--color-text-secondary)}
2088
2101
  .x1cpjm7i:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::before{content:""}
@@ -11,6 +11,6 @@
11
11
  * identical — neither hook fires during server rendering — but React only
12
12
  * warns about useLayoutEffect.
13
13
  */
14
- import { useLayoutEffect } from 'react';
15
- export declare const useIsomorphicLayoutEffect: typeof useLayoutEffect;
14
+ import { useEffect } from 'react';
15
+ export declare const useIsomorphicLayoutEffect: typeof useEffect;
16
16
  //# sourceMappingURL=useIsomorphicLayoutEffect.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useIsomorphicLayoutEffect.d.ts","sourceRoot":"","sources":["../../src/hooks/useIsomorphicLayoutEffect.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAY,eAAe,EAAC,MAAM,OAAO,CAAC;AAEjD,eAAO,MAAM,yBAAyB,wBACuB,CAAC"}
1
+ {"version":3,"file":"useIsomorphicLayoutEffect.d.ts","sourceRoot":"","sources":["../../src/hooks/useIsomorphicLayoutEffect.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAC,SAAS,EAAkB,MAAM,OAAO,CAAC;AAEjD,eAAO,MAAM,yBAAyB,kBACuB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"SyntaxTheme.d.ts","sourceRoot":"","sources":["../../../src/theme/syntax/SyntaxTheme.tsx"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAEH,OAAO,KAAoC,MAAM,OAAO,CAAC;AACzD,OAAO,EAIL,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACzB,MAAM,qBAAqB,CAAC;AAmB7B,MAAM,WAAW,oBAAoB;IACnC,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;IACvB;;;;;OAKG;IACH,KAAK,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,MAAM,CAAC;IAC7C;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;CAC7C;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,IAAI,oBAAoB,GAAG,IAAI,CA6B5D;AAMD,UAAU,gBAAgB;IACxB,KAAK,EAAE,qBAAqB,CAAC;IAC7B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,QAAQ,GACT,EAAE,gBAAgB,GAAG,KAAK,CAAC,YAAY,CAWvC;yBAde,WAAW"}
1
+ {"version":3,"file":"SyntaxTheme.d.ts","sourceRoot":"","sources":["../../../src/theme/syntax/SyntaxTheme.tsx"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAEH,OAAO,KAAoC,MAAM,OAAO,CAAC;AACzD,OAAO,EAIL,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACzB,MAAM,qBAAqB,CAAC;AAqB7B,MAAM,WAAW,oBAAoB;IACnC,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;IACvB;;;;;OAKG;IACH,KAAK,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,MAAM,CAAC;IAC7C;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;CAC7C;AAsBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,IAAI,oBAAoB,GAAG,IAAI,CAoD5D;AAMD,UAAU,gBAAgB;IACxB,KAAK,EAAE,qBAAqB,CAAC;IAC7B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,QAAQ,GACT,EAAE,gBAAgB,GAAG,KAAK,CAAC,YAAY,CAWvC;yBAde,WAAW"}
@@ -13,6 +13,8 @@
13
13
  import React, { createContext, use, useMemo } from 'react';
14
14
  import { syntaxThemeStyle, resolveSyntaxTokenForMode, ALL_SYNTAX_KEYS } from "./defineSyntaxTheme.js";
15
15
  import { useMediaQuery } from "../../hooks/useMediaQuery.js";
16
+ import { useTheme } from "../useTheme.js";
17
+ import { formatColor, parseColor } from "../../utils/color.js";
16
18
 
17
19
  // =============================================================================
18
20
  // Context
@@ -31,6 +33,22 @@ SyntaxThemeContext.displayName = 'SyntaxThemeContext';
31
33
  // Hook
32
34
  // =============================================================================
33
35
 
36
+ /** The strength of the default diff row paints: the muted tokens at 25%. */
37
+ const DIFF_TINT_STRENGTH = 0.25;
38
+
39
+ /**
40
+ * The colour `color-mix(in srgb, <colour> <strength>, transparent)` paints, as
41
+ * a value a canvas can use. Returns undefined for a colour the shared parser
42
+ * does not read (the CSS default then stands).
43
+ */
44
+ function mixWithTransparent(colour, strength) {
45
+ const parsed = parseColor(colour);
46
+ return parsed ? formatColor({
47
+ ...parsed,
48
+ a: parsed.a * strength
49
+ }) : undefined;
50
+ }
51
+
34
52
  /**
35
53
  * Access the current syntax theme's token values, resolved for the active
36
54
  * color mode. Returns null if no SyntaxTheme provider is present.
@@ -46,6 +64,7 @@ SyntaxThemeContext.displayName = 'SyntaxThemeContext';
46
64
  */
47
65
  export function useSyntaxTheme() {
48
66
  const ctx = use(SyntaxThemeContext);
67
+ const page = useTheme();
49
68
  const prefersDark = useMediaQuery('(prefers-color-scheme: dark)');
50
69
  const effectiveMode = prefersDark ? 'dark' : 'light';
51
70
  const tokens = useMemo(() => {
@@ -54,10 +73,32 @@ export function useSyntaxTheme() {
54
73
  }
55
74
  const resolved = {};
56
75
  for (const key of ALL_SYNTAX_KEYS) {
57
- resolved[key] = resolveSyntaxTokenForMode(ctx.theme.__inputTokens[key], effectiveMode);
76
+ const input = ctx.theme.__inputTokens[key];
77
+ if (input !== undefined) {
78
+ resolved[key] = resolveSyntaxTokenForMode(input, effectiveMode);
79
+ }
80
+ }
81
+ // A diff row slot the theme did not set follows its CSS default; a canvas
82
+ // consumer needs a colour it can paint, so the marker slots take the
83
+ // theme's own resolved punctuation colour and the row paints derive from
84
+ // the enclosing page theme's resolved tokens (the same mix the CSS
85
+ // default makes), never from a probe outside the nearest Theme.
86
+ for (const key of ALL_SYNTAX_KEYS) {
87
+ if (resolved[key] !== undefined) {
88
+ continue;
89
+ }
90
+ const fallback = ctx.theme.tokens[key] ?? '';
91
+ if (key === 'added-marker' || key === 'removed-marker') {
92
+ resolved[key] = resolved.punctuation ?? fallback;
93
+ } else if (key === 'added' || key === 'removed') {
94
+ const base = page.token(key === 'added' ? '--color-success-muted' : '--color-error-muted');
95
+ resolved[key] = mixWithTransparent(base, DIFF_TINT_STRENGTH) ?? fallback;
96
+ } else {
97
+ resolved[key] = fallback;
98
+ }
58
99
  }
59
100
  return resolved;
60
- }, [ctx, effectiveMode]);
101
+ }, [ctx, effectiveMode, page]);
61
102
  if (!ctx || !tokens) {
62
103
  return null;
63
104
  }
@@ -1,14 +1,25 @@
1
1
  /** Human-readable syntax token name (without CSS custom property prefix). */
2
- export type SyntaxThemeTokenKey = 'keyword' | 'string' | 'comment' | 'number' | 'function' | 'type' | 'variable' | 'operator' | 'constant' | 'tag' | 'attribute' | 'property' | 'punctuation' | 'background';
2
+ export type SyntaxThemeTokenKey = 'keyword' | 'string' | 'comment' | 'number' | 'function' | 'type' | 'variable' | 'operator' | 'constant' | 'tag' | 'attribute' | 'property' | 'punctuation' | 'background' | DiffSyntaxThemeTokenKey;
3
+ /** The diff row slots a syntax theme MAY set; unset ones keep their defaults. */
4
+ export type DiffSyntaxThemeTokenKey = 'added' | 'removed' | 'diff-header' | 'added-marker' | 'removed-marker';
3
5
  /**
4
6
  * Token value — either a single string or a [light, dark] tuple.
5
7
  * Tuples are converted to CSS light-dark() at theme creation time.
6
8
  */
7
9
  export type SyntaxTokenValue = string | [light: string, dark: string];
8
- /** Token map for defineSyntaxTheme input — values can be strings or tuples. */
9
- export type SyntaxThemeTokenInput = Record<SyntaxThemeTokenKey, SyntaxTokenValue>;
10
- /** Resolved token map — all values are CSS strings (tuples resolved to light-dark()). */
11
- export type SyntaxThemeTokenMap = Record<SyntaxThemeTokenKey, string>;
10
+ /**
11
+ * Token map for defineSyntaxTheme input — values can be strings or tuples.
12
+ * The diff row slots are optional: a theme that sets none keeps the defaults
13
+ * (semantic success/error muted tints and the muted surface).
14
+ */
15
+ export type SyntaxThemeTokenInput = Record<Exclude<SyntaxThemeTokenKey, DiffSyntaxThemeTokenKey>, SyntaxTokenValue> & Partial<Record<DiffSyntaxThemeTokenKey, SyntaxTokenValue>>;
16
+ /**
17
+ * Resolved token map — all values are CSS strings (tuples resolved to
18
+ * light-dark()). The diff row slots are optional here as in the input, so a
19
+ * map written before they existed still type-checks; an unset slot renders
20
+ * its default.
21
+ */
22
+ export type SyntaxThemeTokenMap = Record<Exclude<SyntaxThemeTokenKey, DiffSyntaxThemeTokenKey>, string> & Partial<Record<DiffSyntaxThemeTokenKey, string>>;
12
23
  /** Input to defineSyntaxTheme. */
13
24
  export interface SyntaxThemeInput {
14
25
  name: string;
@@ -25,6 +36,8 @@ export interface SyntaxThemeDefinition {
25
36
  }
26
37
  /** All valid human-readable token keys, derived from the defaults. */
27
38
  export declare const ALL_SYNTAX_KEYS: SyntaxThemeTokenKey[];
39
+ /** The keys every syntax theme must set: everything but the diff rows. */
40
+ export declare const REQUIRED_SYNTAX_KEYS: SyntaxThemeTokenKey[];
28
41
  /**
29
42
  * Resolve a token value for a specific color mode.
30
43
  * - [light, dark] tuple → picks the correct side
@@ -1 +1 @@
1
- {"version":3,"file":"defineSyntaxTheme.d.ts","sourceRoot":"","sources":["../../../src/theme/syntax/defineSyntaxTheme.ts"],"names":[],"mappings":"AAoBA,6EAA6E;AAC7E,MAAM,MAAM,mBAAmB,GAC3B,SAAS,GACT,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,UAAU,GACV,MAAM,GACN,UAAU,GACV,UAAU,GACV,UAAU,GACV,KAAK,GACL,WAAW,GACX,UAAU,GACV,aAAa,GACb,YAAY,CAAC;AAEjB;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AAEtE,+EAA+E;AAC/E,MAAM,MAAM,qBAAqB,GAAG,MAAM,CACxC,mBAAmB,EACnB,gBAAgB,CACjB,CAAC;AAEF,yFAAyF;AACzF,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;AAEtE,kCAAkC;AAClC,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,qBAAqB,CAAC;CAC/B;AAED,mEAAmE;AACnE,MAAM,WAAW,qBAAqB;IACpC,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,MAAM,EAAE,mBAAmB,CAAC;IAC5B,mEAAmE;IACnE,aAAa,EAAE,qBAAqB,CAAC;CACtC;AAYD,sEAAsE;AACtE,eAAO,MAAM,eAAe,EAAE,mBAAmB,EAEW,CAAC;AAc7D;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,gBAAgB,EACvB,IAAI,EAAE,OAAO,GAAG,MAAM,GACrB,MAAM,CASR;AAMD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,gBAAgB,GACtB,qBAAqB,CAqBvB;AAMD,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,qBAAqB,GAC3B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMxB;AAED,wEAAwE;AACxE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAIrE"}
1
+ {"version":3,"file":"defineSyntaxTheme.d.ts","sourceRoot":"","sources":["../../../src/theme/syntax/defineSyntaxTheme.ts"],"names":[],"mappings":"AAwBA,6EAA6E;AAC7E,MAAM,MAAM,mBAAmB,GAC3B,SAAS,GACT,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,UAAU,GACV,MAAM,GACN,UAAU,GACV,UAAU,GACV,UAAU,GACV,KAAK,GACL,WAAW,GACX,UAAU,GACV,aAAa,GACb,YAAY,GACZ,uBAAuB,CAAC;AAE5B,iFAAiF;AACjF,MAAM,MAAM,uBAAuB,GACjC,OAAO,GAAG,SAAS,GAAG,aAAa,GAAG,cAAc,GAAG,gBAAgB,CAAC;AAE1E;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AAEtE;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,MAAM,CACxC,OAAO,CAAC,mBAAmB,EAAE,uBAAuB,CAAC,EACrD,gBAAgB,CACjB,GACC,OAAO,CAAC,MAAM,CAAC,uBAAuB,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAE7D;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,CACtC,OAAO,CAAC,mBAAmB,EAAE,uBAAuB,CAAC,EACrD,MAAM,CACP,GACC,OAAO,CAAC,MAAM,CAAC,uBAAuB,EAAE,MAAM,CAAC,CAAC,CAAC;AAEnD,kCAAkC;AAClC,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,qBAAqB,CAAC;CAC/B;AAED,mEAAmE;AACnE,MAAM,WAAW,qBAAqB;IACpC,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,MAAM,EAAE,mBAAmB,CAAC;IAC5B,mEAAmE;IACnE,aAAa,EAAE,qBAAqB,CAAC;CACtC;AAYD,sEAAsE;AACtE,eAAO,MAAM,eAAe,EAAE,mBAAmB,EAEW,CAAC;AAc7D,0EAA0E;AAC1E,eAAO,MAAM,oBAAoB,EAAE,mBAAmB,EACF,CAAC;AAcrD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,gBAAgB,EACvB,IAAI,EAAE,OAAO,GAAG,MAAM,GACrB,MAAM,CASR;AAMD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,gBAAgB,GACtB,qBAAqB,CAuCvB;AAMD,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,qBAAqB,GAC3B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQxB;AAED,wEAAwE;AACxE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAKrE"}